Project

General

Profile

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

library / src / main / java / org / distorted / library / mesh / MeshMultigon.java @ d45273cd

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2023 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
import java.util.ArrayList;
24

    
25
///////////////////////////////////////////////////////////////////////////////////////////////////
26

    
27
/**
28
 * Create a 'multigon' mesh - a union of several polygons.
29
 *
30
 * <p>
31
 * Specify several lists of vertices. Each list defines one polygon. (@see MeshPolygon).
32
 * If two such polygons share an edge (or several edges) then the edge in both of them is
33
 * marked 'up'.
34
 */
35
public class MeshMultigon extends MeshBase
36
  {
37
  private static final float MAX_ERROR = 0.0001f;
38
  private float[][] mOuterVertices;
39

    
40
///////////////////////////////////////////////////////////////////////////////////////////////////
41

    
42
  private boolean isSame(float dx, float dy)
43
    {
44
    return (dx*dx + dy*dy < MAX_ERROR);
45
    }
46

    
47
///////////////////////////////////////////////////////////////////////////////////////////////////
48

    
49
  private boolean isUp(float[][] vertices, int polygon, int edge)
50
    {
51
    //android.util.Log.e("D", "checking polygon "+polygon+" edge "+edge);
52

    
53
    float[] p= vertices[polygon];
54
    int lenP = p.length/2;
55
    int len  = vertices.length;
56
    int next = (edge==lenP-1 ? 0 : edge+1);
57

    
58
    float v1x = p[2*edge  ];
59
    float v1y = p[2*edge+1];
60
    float v2x = p[2*next  ];
61
    float v2y = p[2*next+1];
62

    
63
    //android.util.Log.e("D", " v1="+v1x+" "+v1y+"  v2="+v2x+" "+v2y);
64

    
65
    for(int i=0; i<len; i++)
66
      if( i!=polygon )
67
        {
68
        int num = vertices[i].length/2;
69

    
70
        for(int j=0; j<num; j++)
71
          {
72
          int n = (j==num-1 ? 0 : j+1);
73
          float[] v = vertices[i];
74
          float x1 = v[2*j  ];
75
          float y1 = v[2*j+1];
76
          float x2 = v[2*n  ];
77
          float y2 = v[2*n+1];
78

    
79
          //android.util.Log.e("D", "comparing v2 to "+x1+" "+y1);
80
          //android.util.Log.e("D", "comparing v1 to "+x2+" "+y2);
81

    
82
          if( isSame(v2x-x1,v2y-y1) && isSame(v1x-x2,v1y-y2) ) return true;
83
          }
84
        }
85

    
86
    //android.util.Log.e("D", "FALSE");
87

    
88
    return false;
89
    }
90

    
91
///////////////////////////////////////////////////////////////////////////////////////////////////
92

    
93
  private boolean[][] computeEdgesUp(float[][] vertices)
94
    {
95
    int num = vertices.length;
96
    boolean[][] up = new boolean[num][];
97

    
98
    for(int i=0; i<num; i++)
99
      {
100
      int len = vertices[i].length/2;
101
      up[i] = new boolean[len];
102
      for(int j=0; j<len; j++)
103
        {
104
        up[i][j] = isUp(vertices,i,j);
105
        //android.util.Log.e("D", "polygon "+i+" edge "+j+" up: "+up[i][j]);
106
        }
107
      }
108

    
109
    return up;
110
    }
111

    
112
///////////////////////////////////////////////////////////////////////////////////////////////////
113

    
114
  private float[] detectFirstOuterVertex(float[][] vertices)
115
    {
116
    float X = -Float.MAX_VALUE;
117
    int I=0,J=0, len = vertices.length;
118

    
119
    for(int i=0; i<len; i++ )
120
      {
121
      float[] v = vertices[i];
122
      int num = v.length/2;
123

    
124
      for(int j=0; j<num; j++)
125
        if(v[2*j]>X)
126
          {
127
          X = v[2*j];
128
          I = i;
129
          J = j;
130
          }
131
      }
132

    
133
    float[] v = vertices[I];
134
    return new float[] {v[2*J],v[2*J+1]};
135
    }
136

    
137
///////////////////////////////////////////////////////////////////////////////////////////////////
138

    
139
  private double computeAngle(float x1,float y1, float x2, float y2)
140
    {
141
    double diff = Math.atan2(y2,x2)-Math.atan2(y1,x1);
142
    return diff<0 ? diff+(2*Math.PI) : diff;
143
    }
144

    
145
///////////////////////////////////////////////////////////////////////////////////////////////////
146

    
147
  private float[] detectNextOuterVertex(float[][] vertices, float[] curr, float[] vect)
148
    {
149
    double minAngle = 2*Math.PI;
150
    float x=0, y=0;
151

    
152
    for( float[] v : vertices )
153
      {
154
      int num = v.length/2;
155

    
156
      for( int j=0; j<num; j++)
157
        {
158
        float xc = v[2*j];
159
        float yc = v[2*j+1];
160

    
161
        if( xc==curr[0] && yc==curr[1])
162
          {
163
          int n = (j==num-1 ? 0 : j+1);
164
          float xn = v[2*n];
165
          float yn = v[2*n+1];
166

    
167
          double angle = computeAngle(vect[0], vect[1], xn-xc, yn-yc);
168

    
169
          if (angle < minAngle)
170
            {
171
            minAngle = angle;
172
            x = xn;
173
            y = yn;
174
            }
175

    
176
          break;
177
          }
178
        }
179
      }
180

    
181
    return new float[] {x,y};
182
    }
183

    
184
///////////////////////////////////////////////////////////////////////////////////////////////////
185

    
186
  private void computeOuter(float[][] vertices)
187
    {
188
    ArrayList<float[]> tmp = new ArrayList<>();
189

    
190
    float[] vect = new float[] {1,0};
191
    float[] first= detectFirstOuterVertex(vertices);
192
    float[] next = first;
193

    
194
    do
195
      {
196
      float[] prev = next;
197
      next = detectNextOuterVertex(vertices,next,vect);
198
      vect[0] = prev[0]-next[0];
199
      vect[1] = prev[1]-next[1];
200
      tmp.add(next);
201
      }
202
    while( next[0]!=first[0] || next[1]!=first[1] );
203

    
204
    int num = tmp.size();
205
    mOuterVertices = new float[num][];
206
    for(int i=0; i<num; i++) mOuterVertices[i] = tmp.remove(0);
207
    }
208

    
209
///////////////////////////////////////////////////////////////////////////////////////////////////
210

    
211
  private boolean doesntBelongToOuter(float x, float y)
212
    {
213
    for( float[] v : mOuterVertices )
214
      if( x==v[0] && y==v[1] ) return false;
215

    
216
    return true;
217
    }
218

    
219
///////////////////////////////////////////////////////////////////////////////////////////////////
220

    
221
  private boolean[][] computeVertsUp(float[][] vertices)
222
    {
223
    computeOuter(vertices);
224

    
225
    int num = vertices.length;
226
    boolean[][] up = new boolean[num][];
227

    
228
    for(int i=0; i<num; i++)
229
      {
230
      float[] v = vertices[i];
231
      int len = v.length/2;
232
      up[i] = new boolean[len];
233
      for(int j=0; j<len; j++) up[i][j] = doesntBelongToOuter(v[2*j],v[2*j+1]);
234
      }
235

    
236
    return up;
237
    }
238

    
239
///////////////////////////////////////////////////////////////////////////////////////////////////
240
// PUBLIC API
241
///////////////////////////////////////////////////////////////////////////////////////////////////
242
/**
243
 * Specify several lists of vertices. Each list defines one polygon. (@see MeshPolygon).
244
 * If two such polygons share an edge (or several edges) then the edge in both of them is
245
 * marked 'up'.
246
 *
247
 * @param vertices   an array of arrays, each specifying vertices of a single polygon.
248
 * @param band       see MeshPolygon. Shared among all polygons.
249
 * @param exIndex    see MeshPolygon. Shared among all polygons.
250
 * @param exVertices see MeshPolygon. Shared among all polygons.
251
 * @param centers    for each polygon, coordinates of its center.
252
 */
253
  public MeshMultigon(float[][] vertices, float[] band, int exIndex, int exVertices, float[][] centers)
254
    {
255
    super();
256

    
257
    int numPolygons = vertices.length;
258
    MeshPolygon[] meshes = new MeshPolygon[numPolygons];
259
    boolean[][] edgesUp = computeEdgesUp(vertices);
260
    boolean[][] vertsUp = computeVertsUp(vertices);
261

    
262
    for(int i=0; i<numPolygons; i++)
263
      meshes[i] = new MeshPolygon(vertices[i],band,edgesUp[i],vertsUp[i],exIndex,exVertices,centers[i][0],centers[i][1]);
264

    
265
    join(meshes);
266
    mergeEffComponents();
267
    mergeTexComponents();
268
    }
269

    
270
///////////////////////////////////////////////////////////////////////////////////////////////////
271
/**
272
 * Auto-create the centers to be the centers of gravity of each polygon.
273
 */
274

    
275
  public MeshMultigon(float[][] vertices, float[] band, int exIndex, int exVertices)
276
    {
277
    super();
278

    
279
    int numPolygons = vertices.length;
280
    MeshPolygon[] meshes = new MeshPolygon[numPolygons];
281
    boolean[][] edgesUp = computeEdgesUp(vertices);
282
    boolean[][] vertsUp = computeVertsUp(vertices);
283

    
284
    for(int i=0; i<numPolygons; i++)
285
      {
286
      float[] v = vertices[i];
287
      int num = v.length/2;
288
      float xsum=0, ysum = 0;
289

    
290
      for(int j=0; j<num; j++)
291
        {
292
        xsum += v[2*j];
293
        ysum += v[2*j+1];
294
        }
295

    
296
      meshes[i] = new MeshPolygon(v,band,edgesUp[i],vertsUp[i],exIndex,exVertices,xsum/num,ysum/num);
297
      }
298

    
299
    join(meshes);
300
    mergeEffComponents();
301
    mergeTexComponents();
302
    }
303

    
304
///////////////////////////////////////////////////////////////////////////////////////////////////
305
/**
306
 * Copy constructor.
307
 */
308
  public MeshMultigon(MeshMultigon mesh, boolean deep)
309
    {
310
    super(mesh,deep);
311
    }
312

    
313
///////////////////////////////////////////////////////////////////////////////////////////////////
314
/**
315
 * Copy the Mesh.
316
 *
317
 * @param deep If to be a deep or shallow copy of mVertAttribs1, i.e. the array holding vertices,
318
 *             normals and inflates (the rest, in particular the mVertAttribs2 containing texture
319
 *             coordinates and effect associations, is always deep copied)
320
 */
321
  public MeshMultigon copy(boolean deep)
322
    {
323
    return new MeshMultigon(this,deep);
324
    }
325
 }
(6-6/11)