Project

General

Profile

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

library / src / main / java / org / distorted / library / mesh / MeshPolygon.java @ 8c57d77b

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2020 Leszek Koltunski  leszek@koltunski.pl                                          //
3
//                                                                                               //
4
// This file is part of Distorted.                                                               //
5
//                                                                                               //
6
// 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
//                                                                                               //
11
// This library 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 GNU                             //
14
// Lesser General Public License for more details.                                               //
15
//                                                                                               //
16
// 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
///////////////////////////////////////////////////////////////////////////////////////////////////
20

    
21
package org.distorted.library.mesh;
22

    
23
///////////////////////////////////////////////////////////////////////////////////////////////////
24

    
25
import org.distorted.library.main.DistortedLibrary;
26

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

    
41
  private int remainingVert;
42
  private int numVertices;
43
  private int extraIndex, extraVertices;
44

    
45
  private float[] mBandQuot;
46

    
47
///////////////////////////////////////////////////////////////////////////////////////////////////
48
// polygonVertices>=3 , polygonBands>=2
49

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

    
62
     remainingVert = numVertices;
63
     }
64

    
65
///////////////////////////////////////////////////////////////////////////////////////////////////
66

    
67
  private void computeCache()
68
    {
69
    mBandQuot = new float[mNumPolygonBands];
70

    
71
    int next, prev;
72

    
73
    for(int band=0; band<mNumPolygonBands; band++)
74
      {
75
      next = (band==mNumPolygonBands-1 ? band : band+1);
76
      prev = (band==                 0 ? band : band-1);
77

    
78
      mBandQuot[band] = (mPolygonBands[2*prev+1]-mPolygonBands[2*next+1]) / (mPolygonBands[2*next]-mPolygonBands[2*prev]);
79
      }
80
    }
81

    
82
///////////////////////////////////////////////////////////////////////////////////////////////////
83

    
84
  private float getSpecialQuot(int index)
85
    {
86
    int num = 1 + extraIndex + 2*extraVertices;
87
    int change1 = extraVertices+1;
88
    int change2 = num-change1;
89
    float quot = 1.0f/(extraIndex+1);
90

    
91
    if( index<change1 )      return index*quot/change1;
92
    else if( index>change2 ) return 1-quot + (index-change2)*quot/change1;
93
    else                     return (index-change1+1)*quot;
94
    }
95

    
96
///////////////////////////////////////////////////////////////////////////////////////////////////
97

    
98
  private float getQuot(int index, int band, boolean isExtra)
99
    {
100
    int num = mNumPolygonBands-1-band;
101

    
102
    if( num>0 )
103
      {
104
      if( isExtra )
105
        {
106
        int extra = extraIndex-band+extraVertices;
107

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

    
124
      return (float)index/num;
125
      }
126

    
127
    return 1.0f;
128
    }
129

    
130
///////////////////////////////////////////////////////////////////////////////////////////////////
131

    
132
  private int addVertex(int vertex, int polyBand, int polyVertex, int polyEndVer, float quot, float[] attribs1, float[] attribs2)
133
    {
134
    remainingVert--;
135

    
136
    float vx,vy,vz;
137
    float Xfirst= mPolygonVertices[2*polyVertex  ];
138
    float Yfirst= mPolygonVertices[2*polyVertex+1];
139
    float Xlast = mPolygonVertices[2*polyEndVer  ];
140
    float Ylast = mPolygonVertices[2*polyEndVer+1];
141

    
142
    float xEdge = Xfirst + quot*(Xlast-Xfirst);
143
    float yEdge = Yfirst + quot*(Ylast-Yfirst);
144

    
145
    float x = mPolygonBands[2*polyBand]*xEdge;
146
    float y = mPolygonBands[2*polyBand]*yEdge;
147

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

    
162
    float len = (float)Math.sqrt(vx*vx + vy*vy + vz*vz);
163

    
164
    attribs1[VERT1_ATTRIBS*vertex + POS_ATTRIB  ] = x;
165
    attribs1[VERT1_ATTRIBS*vertex + POS_ATTRIB+1] = y;
166
    attribs1[VERT1_ATTRIBS*vertex + POS_ATTRIB+2] = mPolygonBands[2*polyBand+1];
167

    
168
    attribs1[VERT1_ATTRIBS*vertex + NOR_ATTRIB  ] = vx/len;
169
    attribs1[VERT1_ATTRIBS*vertex + NOR_ATTRIB+1] = vy/len;
170
    attribs1[VERT1_ATTRIBS*vertex + NOR_ATTRIB+2] = vz/len;
171

    
172
    attribs2[VERT2_ATTRIBS*vertex + TEX_ATTRIB  ] = x+0.5f;
173
    attribs2[VERT2_ATTRIBS*vertex + TEX_ATTRIB+1] = y+0.5f;
174

    
175
    return vertex+1;
176
    }
177

    
178
///////////////////////////////////////////////////////////////////////////////////////////////////
179

    
180
  private int createBandStrip(int vertex, int polyBand, int polyVertex, float[] attribs1, float[] attribs2)
181
    {
182
    if( polyVertex==0 )
183
      {
184
      vertex = addVertex(vertex,polyBand,0,1,0,attribs1,attribs2);
185

    
186
      if( polyBand>0 )
187
        {
188
        vertex = addVertex(vertex,polyBand,0,1,0,attribs1,attribs2);
189
        }
190
      }
191

    
192
    boolean specialCase = mNumPolygonBands==2 && polyBand==0 && extraIndex>0;
193
    boolean isExtra = polyBand<extraIndex;
194
    int numPairs = specialCase ? extraIndex+1 : mNumPolygonBands-1-polyBand;
195
    if( isExtra ) numPairs += 2*extraVertices;
196

    
197
    int polyEndVer = polyVertex==mNumPolygonVertices-1 ? 0 : polyVertex+1;
198
    float quot1, quot2;
199

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

    
213
      vertex = addVertex(vertex,polyBand+1,polyVertex,polyEndVer,quot1,attribs1,attribs2);
214
      vertex = addVertex(vertex,polyBand  ,polyVertex,polyEndVer,quot2,attribs1,attribs2);
215
      }
216

    
217
    return vertex;
218
    }
219

    
220
///////////////////////////////////////////////////////////////////////////////////////////////////
221

    
222
  private void buildGrid(float[] attribs1, float[] attribs2)
223
    {
224
    int vertex=0;
225

    
226
    for(int polyBand=0; polyBand<mNumPolygonBands-1; polyBand++)
227
      for(int polyVertex=0; polyVertex<mNumPolygonVertices; polyVertex++)
228
        {
229
        vertex = createBandStrip(vertex,polyBand,polyVertex,attribs1,attribs2);
230
        }
231
    }
232

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

    
259
    mPolygonVertices   = verticesXY;
260
    mPolygonBands      = bands;
261
    mNumPolygonVertices= mPolygonVertices.length /2;
262
    mNumPolygonBands   = mPolygonBands.length /2;
263
    extraIndex         = exIndex;
264
    extraVertices      = exVertices;
265

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

    
275
    computeNumberOfVertices();
276
    computeCache();
277

    
278
    float[] attribs1= new float[VERT1_ATTRIBS*numVertices];
279
    float[] attribs2= new float[VERT2_ATTRIBS*numVertices];
280

    
281
    buildGrid(attribs1,attribs2);
282

    
283
    if( remainingVert!=0 )
284
      DistortedLibrary.logMessage("MeshPolygon: remainingVert " +remainingVert );
285

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

    
297
    setAttribs(attribs1,attribs2);
298
    }
299

    
300
///////////////////////////////////////////////////////////////////////////////////////////////////
301

    
302
  public MeshPolygon(float[] verticesXY, float[] bands, int exIndex, int exVertices)
303
    {
304
    this(verticesXY,bands,exIndex,exVertices,0.0f,0.0f);
305
    }
306

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

    
317
///////////////////////////////////////////////////////////////////////////////////////////////////
318
/**
319
 * Copy constructor.
320
 */
321
  public MeshPolygon(MeshPolygon mesh, boolean deep)
322
    {
323
    super(mesh,deep);
324
    }
325

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