Project

General

Profile

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

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

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
///////////////////////////////////////////////////////////////////////////////////////////////////
24
/**
25
 * Create a polygon of any shape and varying elevations from the edges towards the center.
26
 * <p>
27
 * Specify a list of vertices. Any two adjacent vertices + the center (0,0,0) form a triangle. The
28 2d732361 Leszek Koltunski
 * polygon is going to be split into such triangles, and each triangle is split into adjustable number
29 808ef3aa Leszek Koltunski
 * of 'bands' form the outer edge towards the center. Edges of each band can can at any elevation.
30
 */
31
public class MeshPolygon extends MeshBase
32
  {
33
  private float[] mPolygonVertices;
34
  private int mNumPolygonVertices;
35
  private float[] mPolygonBands;
36
  private int mNumPolygonBands;
37
38
  private int remainingVert;
39
  private int numVertices;
40 d456b075 Leszek Koltunski
  private int extraIndex, extraVertices;
41 808ef3aa Leszek Koltunski
42 eeb5d115 Leszek Koltunski
  private float[] mBandQuot;
43
44 808ef3aa Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
45
// polygonVertices>=3 , polygonBands>=2
46
47 d456b075 Leszek Koltunski
  private void computeNumberOfVertices()
48 808ef3aa Leszek Koltunski
     {
49 fa640198 Leszek Koltunski
     if( mNumPolygonBands==2 && extraIndex>0 )
50
       {
51
       numVertices = 1 + 2*mNumPolygonVertices*(1+extraIndex+2*extraVertices);
52
       }
53
     else
54
       {
55
       numVertices = (mNumPolygonVertices*mNumPolygonBands+2)*(mNumPolygonBands-1) - 1;
56
       numVertices+= 2*mNumPolygonVertices*(2*extraIndex*extraVertices);
57
       }
58 d456b075 Leszek Koltunski
59 ac6a08e7 Leszek Koltunski
     remainingVert = numVertices;
60 808ef3aa Leszek Koltunski
     }
61
62
///////////////////////////////////////////////////////////////////////////////////////////////////
63
64 eeb5d115 Leszek Koltunski
  private void computeCache()
65 808ef3aa Leszek Koltunski
    {
66 eeb5d115 Leszek Koltunski
    mBandQuot = new float[mNumPolygonBands];
67 ac6a08e7 Leszek Koltunski
68 eeb5d115 Leszek Koltunski
    int next, prev;
69 ac6a08e7 Leszek Koltunski
70 eeb5d115 Leszek Koltunski
    for(int band=0; band<mNumPolygonBands; band++)
71
      {
72
      next = (band==mNumPolygonBands-1 ? band : band+1);
73
      prev = (band==                 0 ? band : band-1);
74 ac6a08e7 Leszek Koltunski
75 eeb5d115 Leszek Koltunski
      mBandQuot[band] = (mPolygonBands[2*prev+1]-mPolygonBands[2*next+1]) / (mPolygonBands[2*next]-mPolygonBands[2*prev]);
76
      }
77
    }
78 808ef3aa Leszek Koltunski
79 fa640198 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
80
81
  private float getSpecialQuot(int index)
82
    {
83
    int num = 1 + extraIndex + 2*extraVertices;
84
    int change1 = extraVertices+1;
85
    int change2 = num-change1;
86
    float quot = 1.0f/(extraIndex+1);
87
88
    if( index<change1 )      return index*quot/change1;
89
    else if( index>change2 ) return 1-quot + (index-change2)*quot/change1;
90
    else                     return (index-change1+1)*quot;
91
    }
92
93 eeb5d115 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
94 808ef3aa Leszek Koltunski
95 d456b075 Leszek Koltunski
  private float getQuot(int index, int band, boolean isExtra)
96 eeb5d115 Leszek Koltunski
    {
97 d456b075 Leszek Koltunski
    int num = mNumPolygonBands-1-band;
98 808ef3aa Leszek Koltunski
99 d456b075 Leszek Koltunski
    if( num>0 )
100
      {
101
      if( isExtra )
102
        {
103
        int extra = extraIndex-band+extraVertices;
104
105
        if( index < extra )
106
          {
107
          float quot = ((float)extraIndex-band)/(extra*num);
108
          return index*quot;
109
          }
110
        else if( index > num+2*extraVertices-extra )
111
          {
112
          float quot = ((float)extraIndex-band)/(extra*num);
113
          return (1.0f-((float)extraIndex-band)/num) + (index-num-2*extraVertices+extra)*quot;
114
          }
115
        else
116
          {
117
          return ((float)(index-extraVertices))/num;
118
          }
119
        }
120 808ef3aa Leszek Koltunski
121 d456b075 Leszek Koltunski
      return (float)index/num;
122
      }
123 808ef3aa Leszek Koltunski
124 d456b075 Leszek Koltunski
    return 1.0f;
125
    }
126
127
///////////////////////////////////////////////////////////////////////////////////////////////////
128
129
  private int addVertex(int vertex, int polyBand, int polyVertex, int polyEndVer, float quot, float[] attribs1, float[] attribs2)
130
    {
131
    remainingVert--;
132
133
    float vx,vy,vz;
134 eeb5d115 Leszek Koltunski
    float Xfirst= mPolygonVertices[2*polyVertex  ];
135
    float Yfirst= mPolygonVertices[2*polyVertex+1];
136
    float Xlast = mPolygonVertices[2*polyEndVer  ];
137
    float Ylast = mPolygonVertices[2*polyEndVer+1];
138 808ef3aa Leszek Koltunski
139 eeb5d115 Leszek Koltunski
    float xEdge = Xfirst + quot*(Xlast-Xfirst);
140
    float yEdge = Yfirst + quot*(Ylast-Yfirst);
141 808ef3aa Leszek Koltunski
142 eeb5d115 Leszek Koltunski
    float x = mPolygonBands[2*polyBand]*xEdge;
143
    float y = mPolygonBands[2*polyBand]*yEdge;
144 808ef3aa Leszek Koltunski
145 eeb5d115 Leszek Koltunski
    if( quot==0.0f || quot==1.0f )
146
      {
147
      vx = mBandQuot[polyBand]*xEdge;
148
      vy = mBandQuot[polyBand]*yEdge;
149
      vz = xEdge*xEdge + yEdge*yEdge;
150 ac6a08e7 Leszek Koltunski
      }
151
    else
152
      {
153 eeb5d115 Leszek Koltunski
      vx = mBandQuot[polyBand]*(Ylast-Yfirst);
154
      vy = mBandQuot[polyBand]*(Xfirst-Xlast);
155
      float tmp = Xfirst*Ylast - Xlast*Yfirst;
156
      vz = (tmp<0 ? -tmp:tmp);
157
      }
158 ac6a08e7 Leszek Koltunski
159 eeb5d115 Leszek Koltunski
    float len = (float)Math.sqrt(vx*vx + vy*vy + vz*vz);
160 ac6a08e7 Leszek Koltunski
161 eeb5d115 Leszek Koltunski
    attribs1[VERT1_ATTRIBS*vertex + POS_ATTRIB  ] = x;
162
    attribs1[VERT1_ATTRIBS*vertex + POS_ATTRIB+1] = y;
163
    attribs1[VERT1_ATTRIBS*vertex + POS_ATTRIB+2] = mPolygonBands[2*polyBand+1];
164
165
    attribs1[VERT1_ATTRIBS*vertex + NOR_ATTRIB  ] = vx/len;
166
    attribs1[VERT1_ATTRIBS*vertex + NOR_ATTRIB+1] = vy/len;
167
    attribs1[VERT1_ATTRIBS*vertex + NOR_ATTRIB+2] = vz/len;
168
169
    attribs2[VERT2_ATTRIBS*vertex + TEX_ATTRIB  ] = x+0.5f;
170
    attribs2[VERT2_ATTRIBS*vertex + TEX_ATTRIB+1] = y+0.5f;
171 808ef3aa Leszek Koltunski
172
    return vertex+1;
173
    }
174
175
///////////////////////////////////////////////////////////////////////////////////////////////////
176
177
  private int createBandStrip(int vertex, int polyBand, int polyVertex, float[] attribs1, float[] attribs2)
178
    {
179
    if( polyVertex==0 )
180
      {
181 eeb5d115 Leszek Koltunski
      vertex = addVertex(vertex,polyBand,0,1,0,attribs1,attribs2);
182 808ef3aa Leszek Koltunski
183
      if( polyBand>0 )
184
        {
185 eeb5d115 Leszek Koltunski
        vertex = addVertex(vertex,polyBand,0,1,0,attribs1,attribs2);
186 808ef3aa Leszek Koltunski
        }
187
      }
188
189 fa640198 Leszek Koltunski
    boolean specialCase = mNumPolygonBands==2 && polyBand==0 && extraIndex>0;
190 d456b075 Leszek Koltunski
    boolean isExtra = polyBand<extraIndex;
191 fa640198 Leszek Koltunski
    int numPairs = specialCase ? extraIndex+1 : mNumPolygonBands-1-polyBand;
192
    if( isExtra ) numPairs += 2*extraVertices;
193 d456b075 Leszek Koltunski
194 eeb5d115 Leszek Koltunski
    int polyEndVer = polyVertex==mNumPolygonVertices-1 ? 0 : polyVertex+1;
195 d456b075 Leszek Koltunski
    float quot1, quot2;
196 808ef3aa Leszek Koltunski
197 eeb5d115 Leszek Koltunski
    for(int index=0; index<numPairs; index++)
198 808ef3aa Leszek Koltunski
      {
199 fa640198 Leszek Koltunski
      if( specialCase )
200
        {
201
        quot1 = 1.0f;
202
        quot2 = getSpecialQuot(index+1);
203
        }
204
      else
205
        {
206
        quot1 = getQuot(index  ,polyBand+1, isExtra);
207
        quot2 = getQuot(index+1,polyBand  , isExtra);
208
        }
209 d456b075 Leszek Koltunski
210
      vertex = addVertex(vertex,polyBand+1,polyVertex,polyEndVer,quot1,attribs1,attribs2);
211
      vertex = addVertex(vertex,polyBand  ,polyVertex,polyEndVer,quot2,attribs1,attribs2);
212 808ef3aa Leszek Koltunski
      }
213
214
    return vertex;
215
    }
216
217
///////////////////////////////////////////////////////////////////////////////////////////////////
218
219
  private void buildGrid(float[] attribs1, float[] attribs2)
220
    {
221
    int vertex=0;
222
223 ac6a08e7 Leszek Koltunski
    for(int polyBand=0; polyBand<mNumPolygonBands-1; polyBand++)
224 808ef3aa Leszek Koltunski
      for(int polyVertex=0; polyVertex<mNumPolygonVertices; polyVertex++)
225
        {
226 ac6a08e7 Leszek Koltunski
        vertex = createBandStrip(vertex,polyBand,polyVertex,attribs1,attribs2);
227 808ef3aa Leszek Koltunski
        }
228
    }
229
230
///////////////////////////////////////////////////////////////////////////////////////////////////
231
// PUBLIC API
232
///////////////////////////////////////////////////////////////////////////////////////////////////
233
/**
234
 * Create a polygon of any shape and varying elevations from the edges towards the center.
235 d456b075 Leszek Koltunski
 * Optionally make it more dense at the vertices.
236 808ef3aa Leszek Koltunski
 *
237
 * @param verticesXY 2N floats - packed description of polygon vertices. N pairs (x,y).
238 8b082b9f Leszek Koltunski
 *                   Vertices HAVE TO be specified in a COUNTERCLOCKWISE order (starting from any).
239 808ef3aa Leszek Koltunski
 * @param bands      2K floats; K pairs of two floats each describing a single band.
240
 *                   From (1.0,Z[0]) (outer edge, its Z elevation) to (0.0,Z[K]) (the center,
241
 *                   its elevation). The polygon is split into such concentric bands.
242 ac6a08e7 Leszek Koltunski
 *                   Must be band[2*i] > band[2*(i+1)] !
243 d456b075 Leszek Koltunski
 * @param exIndex    This and the next parameter describe how to make the mesh denser at the
244
 *                   polyVertices. If e.g. exIndex=3 and exVertices=2, then 3 triangles of the
245 f4a2d97e Leszek Koltunski
 *                   outermost band (and 2 triangles of the next band, and 1 triangle of the third
246 d456b075 Leszek Koltunski
 *                   band) get denser - the 3 triangles become 3+2 = 5.
247
 * @param exVertices See above.
248 0b732630 Leszek Koltunski
 * @param centerX    the X coordinate of the 'center' of the Polygon, i.e. point of the mesh
249
 *                   all bands go to.
250
 * @param centerY    Y coordinate of the center.
251 808ef3aa Leszek Koltunski
 */
252 0b732630 Leszek Koltunski
  public MeshPolygon(float[] verticesXY, float[] bands, int exIndex, int exVertices, float centerX, float centerY)
253 808ef3aa Leszek Koltunski
    {
254
    super();
255
256 d456b075 Leszek Koltunski
    mPolygonVertices   = verticesXY;
257
    mPolygonBands      = bands;
258
    mNumPolygonVertices= mPolygonVertices.length /2;
259
    mNumPolygonBands   = mPolygonBands.length /2;
260
    extraIndex         = exIndex;
261
    extraVertices      = exVertices;
262 808ef3aa Leszek Koltunski
263 0b732630 Leszek Koltunski
    if( centerX!=0.0f || centerY!=0.0f )
264
      {
265
      for(int v=0; v<mNumPolygonVertices; v++)
266
        {
267
        mPolygonVertices[2*v  ] -= centerX;
268
        mPolygonVertices[2*v+1] -= centerY;
269
        }
270
      }
271
272 d456b075 Leszek Koltunski
    computeNumberOfVertices();
273 eeb5d115 Leszek Koltunski
    computeCache();
274 808ef3aa Leszek Koltunski
275
    float[] attribs1= new float[VERT1_ATTRIBS*numVertices];
276
    float[] attribs2= new float[VERT2_ATTRIBS*numVertices];
277
278
    buildGrid(attribs1,attribs2);
279
280
    if( remainingVert!=0 )
281
      android.util.Log.d("MeshPolygon", "remainingVert " +remainingVert );
282
283 0b732630 Leszek Koltunski
    if( centerX!=0.0f || centerY!=0.0f )
284
      {
285
      for(int v=0; v<numVertices; v++)
286
        {
287
        attribs1[VERT1_ATTRIBS*v + POS_ATTRIB  ] += centerX;
288
        attribs1[VERT1_ATTRIBS*v + POS_ATTRIB+1] += centerY;
289
        attribs2[VERT2_ATTRIBS*v + TEX_ATTRIB  ] += centerX;
290
        attribs2[VERT2_ATTRIBS*v + TEX_ATTRIB+1] += centerY;
291
        }
292
      }
293
294 808ef3aa Leszek Koltunski
    setAttribs(attribs1,attribs2);
295
    }
296
297 0b732630 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
298
299
  public MeshPolygon(float[] verticesXY, float[] bands, int exIndex, int exVertices)
300
    {
301
    this(verticesXY,bands,exIndex,exVertices,0.0f,0.0f);
302
    }
303
304 d456b075 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
305
/**
306
 * Create a polygon of any shape and varying elevations from the edges towards the center.
307
 * Equivalent of the previous with exIndex=0 or exVertices=0.
308
 */
309
  public MeshPolygon(float[] verticesXY, float[] bands)
310
    {
311 0b732630 Leszek Koltunski
    this(verticesXY,bands,0,0,0.0f,0.0f);
312 d456b075 Leszek Koltunski
    }
313
314 808ef3aa Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
315
/**
316
 * Copy constructor.
317
 */
318
  public MeshPolygon(MeshPolygon mesh, boolean deep)
319
    {
320
    super(mesh,deep);
321
    }
322
323
///////////////////////////////////////////////////////////////////////////////////////////////////
324
/**
325
 * Copy the Mesh.
326
 *
327
 * @param deep If to be a deep or shallow copy of mVertAttribs1, i.e. the array holding vertices,
328
 *             normals and inflates (the rest, in particular the mVertAttribs2 containing texture
329
 *             coordinates and effect associations, is always deep copied)
330
 */
331
  public MeshPolygon copy(boolean deep)
332
    {
333
    return new MeshPolygon(this,deep);
334
    }
335
 }