Project

General

Profile

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

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

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2020 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Distorted.                                                               //
5
//                                                                                               //
6
// Distorted 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
// Distorted 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 Distorted.  If not, see <http://www.gnu.org/licenses/>.                            //
18
///////////////////////////////////////////////////////////////////////////////////////////////////
19

    
20
package org.distorted.library.mesh;
21

    
22
///////////////////////////////////////////////////////////////////////////////////////////////////
23
/**
24
 * Create a polygon of any shape and varying elevations from the edges towards the center.
25
 * <p>
26
 * Specify a list of vertices. Any two adjacent vertices + the center (0,0,0) form a triangle. The
27
 * polygon is going to be split into such triangles, and each triangle is split into adjustable number
28
 * of 'bands' form the outer edge towards the center. Edges of each band can can at any elevation.
29
 */
30
public class MeshPolygon extends MeshBase
31
  {
32
  private float[] mPolygonVertices;
33
  private int mNumPolygonVertices;
34
  private float[] mPolygonBands;
35
  private int mNumPolygonBands;
36

    
37
  private int remainingVert;
38
  private int numVertices;
39
  private int extraIndex, extraVertices;
40

    
41
  private float[] mBandQuot;
42

    
43
///////////////////////////////////////////////////////////////////////////////////////////////////
44
// polygonVertices>=3 , polygonBands>=2
45

    
46
  private void computeNumberOfVertices()
47
     {
48
     if( mNumPolygonBands==2 && extraIndex>0 )
49
       {
50
       numVertices = 1 + 2*mNumPolygonVertices*(1+extraIndex+2*extraVertices);
51
       }
52
     else
53
       {
54
       numVertices = (mNumPolygonVertices*mNumPolygonBands+2)*(mNumPolygonBands-1) - 1;
55
       numVertices+= 2*mNumPolygonVertices*(2*extraIndex*extraVertices);
56
       }
57

    
58
     remainingVert = numVertices;
59
     }
60

    
61
///////////////////////////////////////////////////////////////////////////////////////////////////
62

    
63
  private void computeCache()
64
    {
65
    mBandQuot = new float[mNumPolygonBands];
66

    
67
    int next, prev;
68

    
69
    for(int band=0; band<mNumPolygonBands; band++)
70
      {
71
      next = (band==mNumPolygonBands-1 ? band : band+1);
72
      prev = (band==                 0 ? band : band-1);
73

    
74
      mBandQuot[band] = (mPolygonBands[2*prev+1]-mPolygonBands[2*next+1]) / (mPolygonBands[2*next]-mPolygonBands[2*prev]);
75
      }
76
    }
77

    
78
///////////////////////////////////////////////////////////////////////////////////////////////////
79

    
80
  private float getSpecialQuot(int index)
81
    {
82
    int num = 1 + extraIndex + 2*extraVertices;
83
    int change1 = extraVertices+1;
84
    int change2 = num-change1;
85
    float quot = 1.0f/(extraIndex+1);
86

    
87
    if( index<change1 )      return index*quot/change1;
88
    else if( index>change2 ) return 1-quot + (index-change2)*quot/change1;
89
    else                     return (index-change1+1)*quot;
90
    }
91

    
92
///////////////////////////////////////////////////////////////////////////////////////////////////
93

    
94
  private float getQuot(int index, int band, boolean isExtra)
95
    {
96
    int num = mNumPolygonBands-1-band;
97

    
98
    if( num>0 )
99
      {
100
      if( isExtra )
101
        {
102
        int extra = extraIndex-band+extraVertices;
103

    
104
        if( index < extra )
105
          {
106
          float quot = ((float)extraIndex-band)/(extra*num);
107
          return index*quot;
108
          }
109
        else if( index > num+2*extraVertices-extra )
110
          {
111
          float quot = ((float)extraIndex-band)/(extra*num);
112
          return (1.0f-((float)extraIndex-band)/num) + (index-num-2*extraVertices+extra)*quot;
113
          }
114
        else
115
          {
116
          return ((float)(index-extraVertices))/num;
117
          }
118
        }
119

    
120
      return (float)index/num;
121
      }
122

    
123
    return 1.0f;
124
    }
125

    
126
///////////////////////////////////////////////////////////////////////////////////////////////////
127

    
128
  private int addVertex(int vertex, int polyBand, int polyVertex, int polyEndVer, float quot, float[] attribs1, float[] attribs2)
129
    {
130
    remainingVert--;
131

    
132
    float vx,vy,vz;
133
    float Xfirst= mPolygonVertices[2*polyVertex  ];
134
    float Yfirst= mPolygonVertices[2*polyVertex+1];
135
    float Xlast = mPolygonVertices[2*polyEndVer  ];
136
    float Ylast = mPolygonVertices[2*polyEndVer+1];
137

    
138
    float xEdge = Xfirst + quot*(Xlast-Xfirst);
139
    float yEdge = Yfirst + quot*(Ylast-Yfirst);
140

    
141
    float x = mPolygonBands[2*polyBand]*xEdge;
142
    float y = mPolygonBands[2*polyBand]*yEdge;
143

    
144
    if( quot==0.0f || quot==1.0f )
145
      {
146
      vx = mBandQuot[polyBand]*xEdge;
147
      vy = mBandQuot[polyBand]*yEdge;
148
      vz = xEdge*xEdge + yEdge*yEdge;
149
      }
150
    else
151
      {
152
      vx = mBandQuot[polyBand]*(Ylast-Yfirst);
153
      vy = mBandQuot[polyBand]*(Xfirst-Xlast);
154
      float tmp = Xfirst*Ylast - Xlast*Yfirst;
155
      vz = (tmp<0 ? -tmp:tmp);
156
      }
157

    
158
    float len = (float)Math.sqrt(vx*vx + vy*vy + vz*vz);
159

    
160
    attribs1[VERT1_ATTRIBS*vertex + POS_ATTRIB  ] = x;
161
    attribs1[VERT1_ATTRIBS*vertex + POS_ATTRIB+1] = y;
162
    attribs1[VERT1_ATTRIBS*vertex + POS_ATTRIB+2] = mPolygonBands[2*polyBand+1];
163

    
164
    attribs1[VERT1_ATTRIBS*vertex + NOR_ATTRIB  ] = vx/len;
165
    attribs1[VERT1_ATTRIBS*vertex + NOR_ATTRIB+1] = vy/len;
166
    attribs1[VERT1_ATTRIBS*vertex + NOR_ATTRIB+2] = vz/len;
167

    
168
    attribs2[VERT2_ATTRIBS*vertex + TEX_ATTRIB  ] = x+0.5f;
169
    attribs2[VERT2_ATTRIBS*vertex + TEX_ATTRIB+1] = y+0.5f;
170

    
171
    return vertex+1;
172
    }
173

    
174
///////////////////////////////////////////////////////////////////////////////////////////////////
175

    
176
  private int createBandStrip(int vertex, int polyBand, int polyVertex, float[] attribs1, float[] attribs2)
177
    {
178
    if( polyVertex==0 )
179
      {
180
      vertex = addVertex(vertex,polyBand,0,1,0,attribs1,attribs2);
181

    
182
      if( polyBand>0 )
183
        {
184
        vertex = addVertex(vertex,polyBand,0,1,0,attribs1,attribs2);
185
        }
186
      }
187

    
188
    boolean specialCase = mNumPolygonBands==2 && polyBand==0 && extraIndex>0;
189
    boolean isExtra = polyBand<extraIndex;
190
    int numPairs = specialCase ? extraIndex+1 : mNumPolygonBands-1-polyBand;
191
    if( isExtra ) numPairs += 2*extraVertices;
192

    
193
    int polyEndVer = polyVertex==mNumPolygonVertices-1 ? 0 : polyVertex+1;
194
    float quot1, quot2;
195

    
196
    for(int index=0; index<numPairs; index++)
197
      {
198
      if( specialCase )
199
        {
200
        quot1 = 1.0f;
201
        quot2 = getSpecialQuot(index+1);
202
        }
203
      else
204
        {
205
        quot1 = getQuot(index  ,polyBand+1, isExtra);
206
        quot2 = getQuot(index+1,polyBand  , isExtra);
207
        }
208

    
209
      vertex = addVertex(vertex,polyBand+1,polyVertex,polyEndVer,quot1,attribs1,attribs2);
210
      vertex = addVertex(vertex,polyBand  ,polyVertex,polyEndVer,quot2,attribs1,attribs2);
211
      }
212

    
213
    return vertex;
214
    }
215

    
216
///////////////////////////////////////////////////////////////////////////////////////////////////
217

    
218
  private void buildGrid(float[] attribs1, float[] attribs2)
219
    {
220
    int vertex=0;
221

    
222
    for(int polyBand=0; polyBand<mNumPolygonBands-1; polyBand++)
223
      for(int polyVertex=0; polyVertex<mNumPolygonVertices; polyVertex++)
224
        {
225
        vertex = createBandStrip(vertex,polyBand,polyVertex,attribs1,attribs2);
226
        }
227
    }
228

    
229
///////////////////////////////////////////////////////////////////////////////////////////////////
230
// PUBLIC API
231
///////////////////////////////////////////////////////////////////////////////////////////////////
232
/**
233
 * Create a polygon of any shape and varying elevations from the edges towards the center.
234
 * Optionally make it more dense at the vertices.
235
 *
236
 * @param verticesXY 2N floats - packed description of polygon vertices. N pairs (x,y).
237
 *                   Vertices HAVE TO be specified in a COUNTERCLOCKWISE order (starting from any).
238
 * @param bands      2K floats; K pairs of two floats each describing a single band.
239
 *                   From (1.0,Z[0]) (outer edge, its Z elevation) to (0.0,Z[K]) (the center,
240
 *                   its elevation). The polygon is split into such concentric bands.
241
 *                   Must be band[2*i] > band[2*(i+1)] !
242
 * @param exIndex    This and the next parameter describe how to make the mesh denser at the
243
 *                   polyVertices. If e.g. exIndex=3 and exVertices=2, then 3 triangles of the
244
 *                   outermost band (and 2 triangles of the next band, and 1 triangle of the third
245
 *                   band) get denser - the 3 triangles become 3+2 = 5.
246
 * @param exVertices See above.
247
 * @param centerX    the X coordinate of the 'center' of the Polygon, i.e. point of the mesh
248
 *                   all bands go to.
249
 * @param centerY    Y coordinate of the center.
250
 */
251
  public MeshPolygon(float[] verticesXY, float[] bands, int exIndex, int exVertices, float centerX, float centerY)
252
    {
253
    super();
254

    
255
    mPolygonVertices   = verticesXY;
256
    mPolygonBands      = bands;
257
    mNumPolygonVertices= mPolygonVertices.length /2;
258
    mNumPolygonBands   = mPolygonBands.length /2;
259
    extraIndex         = exIndex;
260
    extraVertices      = exVertices;
261

    
262
    if( centerX!=0.0f || centerY!=0.0f )
263
      {
264
      for(int v=0; v<mNumPolygonVertices; v++)
265
        {
266
        mPolygonVertices[2*v  ] -= centerX;
267
        mPolygonVertices[2*v+1] -= centerY;
268
        }
269
      }
270

    
271
    computeNumberOfVertices();
272
    computeCache();
273

    
274
    float[] attribs1= new float[VERT1_ATTRIBS*numVertices];
275
    float[] attribs2= new float[VERT2_ATTRIBS*numVertices];
276

    
277
    buildGrid(attribs1,attribs2);
278

    
279
    if( remainingVert!=0 )
280
      android.util.Log.d("MeshPolygon", "remainingVert " +remainingVert );
281

    
282
    if( centerX!=0.0f || centerY!=0.0f )
283
      {
284
      for(int v=0; v<numVertices; v++)
285
        {
286
        attribs1[VERT1_ATTRIBS*v + POS_ATTRIB  ] += centerX;
287
        attribs1[VERT1_ATTRIBS*v + POS_ATTRIB+1] += centerY;
288
        attribs2[VERT2_ATTRIBS*v + TEX_ATTRIB  ] += centerX;
289
        attribs2[VERT2_ATTRIBS*v + TEX_ATTRIB+1] += centerY;
290
        }
291
      }
292

    
293
    setAttribs(attribs1,attribs2);
294
    }
295

    
296
///////////////////////////////////////////////////////////////////////////////////////////////////
297

    
298
  public MeshPolygon(float[] verticesXY, float[] bands, int exIndex, int exVertices)
299
    {
300
    this(verticesXY,bands,exIndex,exVertices,0.0f,0.0f);
301
    }
302

    
303
///////////////////////////////////////////////////////////////////////////////////////////////////
304
/**
305
 * Create a polygon of any shape and varying elevations from the edges towards the center.
306
 * Equivalent of the previous with exIndex=0 or exVertices=0.
307
 */
308
  public MeshPolygon(float[] verticesXY, float[] bands)
309
    {
310
    this(verticesXY,bands,0,0,0.0f,0.0f);
311
    }
312

    
313
///////////////////////////////////////////////////////////////////////////////////////////////////
314
/**
315
 * Copy constructor.
316
 */
317
  public MeshPolygon(MeshPolygon mesh, boolean deep)
318
    {
319
    super(mesh,deep);
320
    }
321

    
322
///////////////////////////////////////////////////////////////////////////////////////////////////
323
/**
324
 * Copy the Mesh.
325
 *
326
 * @param deep If to be a deep or shallow copy of mVertAttribs1, i.e. the array holding vertices,
327
 *             normals and inflates (the rest, in particular the mVertAttribs2 containing texture
328
 *             coordinates and effect associations, is always deep copied)
329
 */
330
  public MeshPolygon copy(boolean deep)
331
    {
332
    return new MeshPolygon(this,deep);
333
    }
334
 }
(6-6/10)