Project

General

Profile

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

library / src / main / java / org / distorted / library / mesh / MeshBandedTriangle.java @ ef4a9bab

1 33dbf30b Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
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
 * Creator a triangular mesh divided into 'bands' i.e. strips parallel to one of the sides and
29
 * and of different elevations.
30
 * <p>
31
 * This is a building block for MeshMultigon.
32
 */
33
public class MeshBandedTriangle extends MeshBase
34
  {
35 f19d533d leszek
  public static final int MODE_NORMAL  = 0;
36
  public static final int MODE_INVERTED= 1;
37
  public static final int MODE_FLAT    = 2;
38
39 33dbf30b Leszek Koltunski
  private static final int NUM_CACHE = 20;
40
41
  private float mLeftX, mLeftY;
42
  private float mRightX, mRightY;
43
  private float mTopX, mTopY;
44
45
  private float[] mNormL, mNormR;
46
  private int mMode;
47
48
  private float[] mBands;
49
  private int mNumBands;
50
51
  private int remainingVert;
52
  private int numVertices;
53 f19d533d leszek
  private int extraBands, extraVertices;
54 33dbf30b Leszek Koltunski
55
  private float[] mCurveCache;
56
  private float mVecX, mVecY;
57
58
///////////////////////////////////////////////////////////////////////////////////////////////////
59
60
  private void computeNumberOfVertices()
61 f19d533d leszek
    {
62
    if( mMode==MODE_FLAT )
63
      {
64
      numVertices = 3;
65
      }
66
    else if( mMode==MODE_NORMAL )
67
      {
68
      numVertices = mNumBands*(mNumBands+2) + 4*extraVertices*extraBands;
69
      }
70
    else
71
      {
72
      numVertices = mNumBands*(mNumBands+2);
73
      }
74
75
    remainingVert = numVertices;
76
    }
77 33dbf30b Leszek Koltunski
78
///////////////////////////////////////////////////////////////////////////////////////////////////
79
80
  private void computeCache()
81
    {
82
    mCurveCache = new float[NUM_CACHE];
83 f19d533d leszek
    float[] tmpD = new float[mNumBands+1];
84
    float[] tmpX = new float[mNumBands+1];
85 33dbf30b Leszek Koltunski
86 f19d533d leszek
    for(int i=1; i<mNumBands; i++)
87 33dbf30b Leszek Koltunski
      {
88 f19d533d leszek
      tmpD[i] = (mBands[2*i-1]-mBands[2*i+1]) / (mBands[2*i]-mBands[2*i-2]);
89
      tmpX[i] = 1.0f - (mBands[2*i]+mBands[2*i-2])/2;
90 33dbf30b Leszek Koltunski
      }
91
92
    tmpD[0] = tmpD[1];
93 f19d533d leszek
    tmpD[mNumBands] = tmpD[mNumBands-1];
94 33dbf30b Leszek Koltunski
    tmpX[0] = 0.0f;
95 f19d533d leszek
    tmpX[mNumBands] = 1.0f;
96 33dbf30b Leszek Koltunski
97
    int prev = 0;
98
    int next = 0;
99
100
    for(int i=0; i<NUM_CACHE-1; i++)
101
      {
102
      float x = i/(NUM_CACHE-1.0f);
103
104
      if( x>=tmpX[next] )
105
        {
106
        prev = next;
107 f19d533d leszek
        while( next<=mNumBands && x>=tmpX[next] ) next++;
108 33dbf30b Leszek Koltunski
        }
109
110
      if( next>prev )
111
        {
112
        float t = (x-tmpX[prev]) / (tmpX[next]-tmpX[prev]);
113
        mCurveCache[i] = t*(tmpD[next]-tmpD[prev]) + tmpD[prev];
114
        }
115
      else
116
        {
117
        mCurveCache[i] = tmpD[next];
118
        }
119
      }
120
121 f19d533d leszek
    mCurveCache[NUM_CACHE-1] = tmpD[mNumBands];
122 33dbf30b Leszek Koltunski
    }
123
124
///////////////////////////////////////////////////////////////////////////////////////////////////
125
126
  private float derivative(float x)
127
    {
128
    if( x>=1.0f )
129
      {
130
      return 0.0f;
131
      }
132
    else
133
      {
134
      float tmp = x*(NUM_CACHE-1);
135
      int i1 = (int)tmp;
136
      int i2 = i1+1;
137
138
      // why 0.5? Arbitrarily; this way the cubit faces of Twisty Puzzles
139
      // [the main and only user of this class] look better.
140
      return 0.5f*((tmp-i1)*(mCurveCache[i2]-mCurveCache[i1]) + mCurveCache[i1]);
141
      }
142
    }
143
144
///////////////////////////////////////////////////////////////////////////////////////////////////
145
146 f19d533d leszek
  private void figureOutNormalVector2D(float qx)
147 33dbf30b Leszek Koltunski
    {
148 f19d533d leszek
    mVecX = mNormL[0] + qx*(mNormR[0]-mNormL[0]);
149
    mVecY = mNormL[1] + qx*(mNormR[1]-mNormL[1]);
150 33dbf30b Leszek Koltunski
    }
151
152
///////////////////////////////////////////////////////////////////////////////////////////////////
153
154 f19d533d leszek
  private float figureOutDerivative(float qy)
155 33dbf30b Leszek Koltunski
    {
156 f19d533d leszek
    switch(mMode)
157 33dbf30b Leszek Koltunski
      {
158 f19d533d leszek
      case MODE_NORMAL  : return derivative(1-qy);
159
      case MODE_INVERTED: return -derivative(qy);
160
      default           : return 0;
161 33dbf30b Leszek Koltunski
      }
162 f19d533d leszek
    }
163
164
///////////////////////////////////////////////////////////////////////////////////////////////////
165
166
  private float computeElevation(int band)
167
    {
168
    switch(mMode)
169 33dbf30b Leszek Koltunski
      {
170 f19d533d leszek
      case MODE_NORMAL  : return mBands[2*band+1];
171
      case MODE_INVERTED: return mBands[2*(mNumBands-band)+1];
172
      default           : return mBands[2*mNumBands+1];
173 33dbf30b Leszek Koltunski
      }
174
    }
175
176
///////////////////////////////////////////////////////////////////////////////////////////////////
177
178 f19d533d leszek
  private int addStripVertex(int vertex, float qx, float qy, int band, float[] attribs1, float[] attribs2)
179 33dbf30b Leszek Koltunski
    {
180
    remainingVert--;
181
182 f19d533d leszek
    // android.util.Log.e("D", "new v: qx="+qx+" band="+band);
183 33dbf30b Leszek Koltunski
184 f19d533d leszek
    float bx = mLeftX + qx*(mRightX-mLeftX);
185
    float by = mLeftY + qx*(mRightY-mLeftY);
186 33dbf30b Leszek Koltunski
187 f19d533d leszek
    float q = 1-qy;
188
    float x = bx + q*(mTopX-bx);
189
    float y = by + q*(mTopY-by);
190
    float z = computeElevation(band);
191 33dbf30b Leszek Koltunski
192 f19d533d leszek
    figureOutNormalVector2D(band<mNumBands ? qx : 0.5f);
193
    float d = figureOutDerivative(qy);
194 33dbf30b Leszek Koltunski
195
    attribs1[VERT1_ATTRIBS*vertex + POS_ATTRIB  ] = x;
196
    attribs1[VERT1_ATTRIBS*vertex + POS_ATTRIB+1] = y;
197
    attribs1[VERT1_ATTRIBS*vertex + POS_ATTRIB+2] = z;
198
199
    float vx = d*mVecX;
200
    float vy = d*mVecY;
201
    float vz = mVecX*mVecX + mVecY*mVecY;
202
    float len = (float)Math.sqrt(vx*vx + vy*vy + vz*vz);
203
204
    int index = VERT1_ATTRIBS*vertex + NOR_ATTRIB;
205
    attribs1[index  ] = vx/len;
206
    attribs1[index+1] = vy/len;
207
    attribs1[index+2] = vz/len;
208
209
    attribs2[VERT2_ATTRIBS*vertex + TEX_ATTRIB  ] = x+0.5f;
210
    attribs2[VERT2_ATTRIBS*vertex + TEX_ATTRIB+1] = y+0.5f;
211
212
    return vertex+1;
213
    }
214
215
///////////////////////////////////////////////////////////////////////////////////////////////////
216
217 f19d533d leszek
  private int createBand(int vertex, int band, float[] attribs1, float[] attribs2)
218 33dbf30b Leszek Koltunski
    {
219 f19d533d leszek
    boolean fromLeft = (band%2 == 0);
220
    int extra = ((band<extraBands && mMode==MODE_NORMAL) ? extraVertices : 0);
221
    int n = mNumBands-band-1;
222
223
    float b = 1.0f/(mNumBands-band);
224
    float dxb = fromLeft ? b : -b;
225
    float sdx = dxb/(extra+1);
226
227
    float qx = fromLeft ? 0.0f : 1.0f;
228
229
    int bb = mMode==MODE_NORMAL ? band   : mNumBands-band;
230
    int bt = mMode==MODE_NORMAL ? band+1 : mNumBands-(band+1);
231
232
    float qyb = mBands[2*bb];
233
    float qyt = mBands[2*bt];
234
235
    if( mMode!=MODE_NORMAL )
236 33dbf30b Leszek Koltunski
      {
237 f19d533d leszek
      qyb = 1-qyb;
238
      qyt = 1-qyt;
239 33dbf30b Leszek Koltunski
      }
240
241 f19d533d leszek
    vertex = addStripVertex(vertex, qx, qyb, band, attribs1,attribs2);
242 33dbf30b Leszek Koltunski
243 f19d533d leszek
    for(int v=0; v<extra; v++)
244
      {
245
      vertex = addStripVertex(vertex, qx          , qyt, band+1, attribs1,attribs2);
246
      vertex = addStripVertex(vertex, qx+(v+1)*sdx, qyb, band  , attribs1,attribs2);
247
      }
248 33dbf30b Leszek Koltunski
249 f19d533d leszek
    if( n>0 )
250 33dbf30b Leszek Koltunski
      {
251 f19d533d leszek
      float t = 1.0f/n;
252
      float dxt = fromLeft ? t : -t;
253
254
      for(int v=0; v<n; v++)
255 33dbf30b Leszek Koltunski
        {
256 f19d533d leszek
        vertex=addStripVertex(vertex, qx+ v   *dxt, qyt, band+1, attribs1, attribs2);
257
        vertex=addStripVertex(vertex, qx+(v+1)*dxb, qyb, band  , attribs1, attribs2);
258 33dbf30b Leszek Koltunski
        }
259 f19d533d leszek
      }
260 33dbf30b Leszek Koltunski
261 f19d533d leszek
    qx = 1-qx;
262
263
    for(int v=0; v<=extra; v++)
264
      {
265
      vertex = addStripVertex(vertex, qx              , qyt, band+1, attribs1,attribs2);
266
      vertex = addStripVertex(vertex, qx-dxb+(v+1)*sdx, qyb, band  , attribs1,attribs2);
267 33dbf30b Leszek Koltunski
      }
268
269
    return vertex;
270
    }
271
272
///////////////////////////////////////////////////////////////////////////////////////////////////
273
274
  private void buildGrid(float[] attribs1, float[] attribs2)
275
    {
276 f19d533d leszek
    if( mMode==MODE_FLAT )
277
      {
278
      addStripVertex(0, 0, 1, 0, attribs1,attribs2);
279
      addStripVertex(1, 0, 0, 0, attribs1,attribs2);
280
      addStripVertex(2, 1, 1, 0, attribs1,attribs2);
281
      }
282
    else
283
      {
284
      int vertex=0;
285
      for(int b=0; b<mNumBands; b++) vertex=createBand(vertex, b, attribs1, attribs2);
286
      }
287 33dbf30b Leszek Koltunski
    }
288
289
///////////////////////////////////////////////////////////////////////////////////////////////////
290
// PUBLIC API
291
///////////////////////////////////////////////////////////////////////////////////////////////////
292
/**
293
 * Create a triangular mesh split into 'bands' - i.e. strips of triangles - which are parallel to
294
 * a given edge.
295
 *
296
 * @param vL         A pair of floats (x,y) which defines the 'left' vertex of the triangle.
297
 * @param vR         A pair of floats (x,y) which defines the 'right' vertex of the triangle.
298
 * @param vT         A pair of floats (x,y) which defines the 'top' vertex of the triangle.
299
 * @param bands      2K floats; K pairs of two floats each describing a single band.
300
 *                   From (1.0,Z[0]) (the 'left-right' edge, its Z elevation) to (0.0,Z[K])
301
 *                   (the 'top' vertex, its elevation). The polygon is split into such strips.
302
 *                   Must be band[2*i] > band[2*(i+1)] !
303
 *                   The way the bands get interpreted also depends on the 'mode' param.
304
 * @param normL      A pair of floats which define a 2D vector - which is the normal vector of each
305
 *                   mesh vertex which lies on the 'left-top' edge casted to the XY plane.
306
 * @param normR      Same as above but about the vertices which belong to the 'right-top' triangle
307
 *                   edge. This and the previous param define the vector field of normals, as seen
308
 *                   from above, of the whole mesh.
309
 * @param mode       MODE_UP, MODE_DOWN or MODE_FLAT.
310
 *                   This defines how we interpret the bands.
311
 *                   If UP, we interpret them the same as in MeshPolygon - i.e. the first band is
312
 *                   about the 'left-right' edge, then progressively towards the 'top'.
313
 *                   If DOWN, we turn the interpretation of the bands upside-down: it is the last
314
 *                   band which defines the strip aong the 'left-right' edge.
315
 *                   If FLAT, everything is flat anyway, so we disregard the bands and return a mesh
316
 *                   with 3 vertices.
317 f19d533d leszek
 * @param exBands    This and the next parameter describe how to make the mesh denser at the
318
 *                   'left' and 'right' vertices. If e.g. exBands=3 and exVertices=2, then 3 triangles
319 33dbf30b Leszek Koltunski
 *                   of the outermost band (and 2 triangles of the next band, and 1 triangle of the
320
 *                   third band) get denser - the 3 triangles become 3+2 = 5.
321
 * @param exVertices See above.
322
 */
323 f19d533d leszek
  public MeshBandedTriangle(float[] vL, float[] vR, float[] vT, float[] bands, float[] normL, float[] normR, int mode, int exBands, int exVertices)
324 33dbf30b Leszek Koltunski
    {
325
    super();
326
327
    mLeftX   = vL[0];
328
    mLeftY   = vL[1];
329
    mRightX  = vR[0];
330
    mRightY  = vR[1];
331
    mTopX    = vT[0];
332
    mTopY    = vT[1];
333
334
    mMode = mode;
335 ef4a9bab leszek
    mNormL= new float[] { normL[0],normL[1] };
336
    mNormR= new float[] { normR[0],normR[1] };
337 33dbf30b Leszek Koltunski
338
    mBands        = bands;
339 f19d533d leszek
    mNumBands     = mBands.length/2 -1;
340
    extraBands    = exBands;
341 33dbf30b Leszek Koltunski
    extraVertices = exVertices;
342
343
    computeNumberOfVertices();
344
    computeCache();
345
346
    float[] attribs1= new float[VERT1_ATTRIBS*numVertices];
347
    float[] attribs2= new float[VERT2_ATTRIBS*numVertices];
348
349
    buildGrid(attribs1,attribs2);
350
351
    if( remainingVert!=0 )
352
      DistortedLibrary.logMessage("MeshBandedTriangle: remainingVert " +remainingVert );
353
354
    setAttribs(attribs1,attribs2);
355
    }
356
357
///////////////////////////////////////////////////////////////////////////////////////////////////
358
/**
359
 * Copy constructor.
360
 */
361
  public MeshBandedTriangle(MeshBandedTriangle mesh, boolean deep)
362
    {
363
    super(mesh,deep);
364
    }
365
366
///////////////////////////////////////////////////////////////////////////////////////////////////
367
/**
368
 * Copy the Mesh.
369
 *
370
 * @param deep If to be a deep or shallow copy of mVertAttribs1, i.e. the array holding vertices,
371
 *             normals and inflates (the rest, in particular the mVertAttribs2 containing texture
372
 *             coordinates and effect associations, is always deep copied)
373
 */
374
  public MeshBandedTriangle copy(boolean deep)
375
    {
376
    return new MeshBandedTriangle(this,deep);
377
    }
378
 }