Project

General

Profile

« Previous | Next » 

Revision b72b8a3b

Added by Leszek Koltunski over 5 years ago

Fix (hopefully the last!) probelm with texturing the Sphere: the seam in the back.

View differences:

src/main/java/org/distorted/library/mesh/MeshSphere.java
75 75
// (level*level +4*level) because there are level*level little triangles, each requiring new vertex,
76 76
// plus 2 extra vertices to start off a row and 2 to move to the next row (or the next face in case
77 77
// of the last row) and there are 'level' rows.
78
//
79
// Now to this we need to add 6*(level-1) vertices for the internal seams in the three triangles
80
// in the back ( 2,7,16 in the list above ): 3 triangles, level-1 rows of more than 1 triangle in
81
// each, 2 extra seam vertices in each row.
78 82

  
79 83
  private void computeNumberOfVertices(int level)
80 84
    {
81
    numVertices = NUMFACES*level*(level+4) -2;
85
    numVertices = NUMFACES*level*(level+4) -2  + 6*(level-1);
82 86
    currentVert = 0;
83 87
    }
84 88

  
85 89
///////////////////////////////////////////////////////////////////////////////////////////////////
86
// (longitude,latitude) - spherical coordinates of a point on a unit sphere.
87
// Cartesian (0,0,1) - i.e. the point of the sphere closest to the camera - is spherical (0,0).
88 90

  
89
  private void addVertex( double longitude, double latitude, float[] attribs)
91
  private int convertAng(double radian)
90 92
    {
91
    double sinLON = Math.sin(longitude);
92
    double cosLON = Math.cos(longitude);
93
    double sinLAT = Math.sin(latitude);
94
    double cosLAT = Math.cos(latitude);
95

  
96
    float x = (float)(cosLAT*sinLON / sqrt2);
97
    float y = (float)(sinLAT        / sqrt2);
98
    float z = (float)(cosLAT*cosLON / sqrt2);
99

  
100
    double texX = 0.5 + longitude/(2*P);
101
    if( texX>=1.0 ) texX-=1.0;
102

  
103
    //android.util.Log.e("tex", "longitude = "+((int)(180.0*longitude/P))+" texX="+texX );
104

  
105
    double texY = 0.5 + latitude/P;
106

  
107
    attribs[VERT_ATTRIBS*currentVert + POS_ATTRIB  ] = x;  //
108
    attribs[VERT_ATTRIBS*currentVert + POS_ATTRIB+1] = y;  //
109
    attribs[VERT_ATTRIBS*currentVert + POS_ATTRIB+2] = z;  //
110
                                                           //  In case of this Mesh so it happens that
111
    attribs[VERT_ATTRIBS*currentVert + NOR_ATTRIB  ] = x;  //  the vertex coords, normal vector, and
112
    attribs[VERT_ATTRIBS*currentVert + NOR_ATTRIB+1] = y;  //  inflate vector have identical (x,y,z).
113
    attribs[VERT_ATTRIBS*currentVert + NOR_ATTRIB+2] = z;  //
114
                                                           //  TODO: think about some more efficient
115
    attribs[VERT_ATTRIBS*currentVert + INF_ATTRIB  ] = x;  //  representation.
116
    attribs[VERT_ATTRIBS*currentVert + INF_ATTRIB+1] = y;  //
117
    attribs[VERT_ATTRIBS*currentVert + INF_ATTRIB+2] = z;  //
118

  
119
    attribs[VERT_ATTRIBS*currentVert + TEX_ATTRIB  ] = (float)texX;
120
    attribs[VERT_ATTRIBS*currentVert + TEX_ATTRIB+1] = (float)texY;
121

  
122
    currentVert++;
93
    return (int)(radian*180.0/P);
123 94
    }
124 95

  
125

  
126 96
///////////////////////////////////////////////////////////////////////////////////////////////////
127 97

  
128
  private void repeatLast(float[] attribs)
98
  private void repeatVertex(float[] attribs, int diff)
129 99
    {
130 100
    //android.util.Log.e("sphere", "repeat last!");
131 101

  
132 102
    if( currentVert>0 )
133 103
      {
134
      attribs[VERT_ATTRIBS*currentVert + POS_ATTRIB  ] = attribs[VERT_ATTRIBS*(currentVert-1) + POS_ATTRIB  ];
135
      attribs[VERT_ATTRIBS*currentVert + POS_ATTRIB+1] = attribs[VERT_ATTRIBS*(currentVert-1) + POS_ATTRIB+1];
136
      attribs[VERT_ATTRIBS*currentVert + POS_ATTRIB+2] = attribs[VERT_ATTRIBS*(currentVert-1) + POS_ATTRIB+2];
104
      attribs[VERT_ATTRIBS*currentVert + POS_ATTRIB  ] = attribs[VERT_ATTRIBS*(currentVert-diff) + POS_ATTRIB  ];
105
      attribs[VERT_ATTRIBS*currentVert + POS_ATTRIB+1] = attribs[VERT_ATTRIBS*(currentVert-diff) + POS_ATTRIB+1];
106
      attribs[VERT_ATTRIBS*currentVert + POS_ATTRIB+2] = attribs[VERT_ATTRIBS*(currentVert-diff) + POS_ATTRIB+2];
137 107

  
138
      attribs[VERT_ATTRIBS*currentVert + NOR_ATTRIB  ] = attribs[VERT_ATTRIBS*(currentVert-1) + NOR_ATTRIB  ];
139
      attribs[VERT_ATTRIBS*currentVert + NOR_ATTRIB+1] = attribs[VERT_ATTRIBS*(currentVert-1) + NOR_ATTRIB+1];
140
      attribs[VERT_ATTRIBS*currentVert + NOR_ATTRIB+2] = attribs[VERT_ATTRIBS*(currentVert-1) + NOR_ATTRIB+2];
108
      attribs[VERT_ATTRIBS*currentVert + NOR_ATTRIB  ] = attribs[VERT_ATTRIBS*(currentVert-diff) + NOR_ATTRIB  ];
109
      attribs[VERT_ATTRIBS*currentVert + NOR_ATTRIB+1] = attribs[VERT_ATTRIBS*(currentVert-diff) + NOR_ATTRIB+1];
110
      attribs[VERT_ATTRIBS*currentVert + NOR_ATTRIB+2] = attribs[VERT_ATTRIBS*(currentVert-diff) + NOR_ATTRIB+2];
141 111

  
142
      attribs[VERT_ATTRIBS*currentVert + INF_ATTRIB  ] = attribs[VERT_ATTRIBS*(currentVert-1) + INF_ATTRIB  ];
143
      attribs[VERT_ATTRIBS*currentVert + INF_ATTRIB+1] = attribs[VERT_ATTRIBS*(currentVert-1) + INF_ATTRIB+1];
144
      attribs[VERT_ATTRIBS*currentVert + INF_ATTRIB+2] = attribs[VERT_ATTRIBS*(currentVert-1) + INF_ATTRIB+2];
112
      attribs[VERT_ATTRIBS*currentVert + INF_ATTRIB  ] = attribs[VERT_ATTRIBS*(currentVert-diff) + INF_ATTRIB  ];
113
      attribs[VERT_ATTRIBS*currentVert + INF_ATTRIB+1] = attribs[VERT_ATTRIBS*(currentVert-diff) + INF_ATTRIB+1];
114
      attribs[VERT_ATTRIBS*currentVert + INF_ATTRIB+2] = attribs[VERT_ATTRIBS*(currentVert-diff) + INF_ATTRIB+2];
145 115

  
146
      attribs[VERT_ATTRIBS*currentVert + TEX_ATTRIB  ] = attribs[VERT_ATTRIBS*(currentVert-1) + TEX_ATTRIB  ];
147
      attribs[VERT_ATTRIBS*currentVert + TEX_ATTRIB+1] = attribs[VERT_ATTRIBS*(currentVert-1) + TEX_ATTRIB+1];
116
      attribs[VERT_ATTRIBS*currentVert + TEX_ATTRIB  ] = attribs[VERT_ATTRIBS*(currentVert-diff) + TEX_ATTRIB  ];
117
      attribs[VERT_ATTRIBS*currentVert + TEX_ATTRIB+1] = attribs[VERT_ATTRIBS*(currentVert-diff) + TEX_ATTRIB+1];
148 118

  
149 119
      currentVert++;
150 120
      }
......
201 171
// (      0, level-1, level) -> (lonV3,latV3 )
202 172
// (level-1,       0, level) -> (lonV2,latV12)
203 173

  
204
  private void newVertex(float[] attribs, int column, int row, int level,
205
                         double lonV1, double lonV2, double latV12, double latV3)
174
  private void addVertex(float[] attribs, int column, int row, int level,
175
                         double lonV1, double lonV2, double latV12, double latV3, boolean lastInRow)
206 176
    {
207 177
    double quotX = (double)column/level;
208 178
    double quotY = (double)row   /level;
......
217 187
      quotZ = (quotY==1.0 ? 0.0 : quotX / (1.0-quotY));
218 188
      }
219 189

  
220
    double lonPoint = midLongitude(lonV1, lonV2, quotZ );
221
    double latPoint = midLatitude(latV12, latV3, quotY );
190
    double longitude = midLongitude(lonV1, lonV2, quotZ );
191
    double latitude  = midLatitude(latV12, latV3, quotY );
222 192

  
223 193
    //android.util.Log.e("sphere", "newVertex: long:"+lonPoint+" lat:"+latPoint+" column="+column+" row="+row);
224 194

  
225
    addVertex(lonPoint,latPoint,attribs);
195
    double sinLON = Math.sin(longitude);
196
    double cosLON = Math.cos(longitude);
197
    double sinLAT = Math.sin(latitude);
198
    double cosLAT = Math.cos(latitude);
199

  
200
    float x = (float)(cosLAT*sinLON / sqrt2);
201
    float y = (float)(sinLAT        / sqrt2);
202
    float z = (float)(cosLAT*cosLON / sqrt2);
203

  
204
    double texX = 0.5 + longitude/(2*P);
205
    if( texX>=1.0 ) texX-=1.0;
206

  
207
    //android.util.Log.e("tex", "longitude = "+((int)(180.0*longitude/P))+" texX="+texX );
208

  
209
    double texY = 0.5 + latitude/P;
210

  
211
    attribs[VERT_ATTRIBS*currentVert + POS_ATTRIB  ] = x;  //
212
    attribs[VERT_ATTRIBS*currentVert + POS_ATTRIB+1] = y;  //
213
    attribs[VERT_ATTRIBS*currentVert + POS_ATTRIB+2] = z;  //
214
                                                           //  In case of this Mesh so it happens that
215
    attribs[VERT_ATTRIBS*currentVert + NOR_ATTRIB  ] = x;  //  the vertex coords, normal vector, and
216
    attribs[VERT_ATTRIBS*currentVert + NOR_ATTRIB+1] = y;  //  inflate vector have identical (x,y,z).
217
    attribs[VERT_ATTRIBS*currentVert + NOR_ATTRIB+2] = z;  //
218
                                                           //  TODO: think about some more efficient
219
    attribs[VERT_ATTRIBS*currentVert + INF_ATTRIB  ] = x;  //  representation.
220
    attribs[VERT_ATTRIBS*currentVert + INF_ATTRIB+1] = y;  //
221
    attribs[VERT_ATTRIBS*currentVert + INF_ATTRIB+2] = z;  //
222

  
223
    attribs[VERT_ATTRIBS*currentVert + TEX_ATTRIB  ] = (float)texX;
224
    attribs[VERT_ATTRIBS*currentVert + TEX_ATTRIB+1] = (float)texY;
225

  
226
    currentVert++;
227

  
228
    ////////////////////////////////////////////////////////////////////////////////////////////////
229
    // Problem: on the 'change of date' line in the back of the sphere, some triangles see texX
230
    // coords suddenly jump from 1-epsilon to 0+epsilon, which looks like a seam with a narrow copy
231
    // of the whole texture there.
232
    // Solution: each such 'jump' triangle, if it is the last in a row, should have the texX of its
233
    // last (and maybe forelast as well) vertex remapped to 1.0.
234
    // If such triangle is not the last in its row, we need to add two extra vertices between it and
235
    // the next one, remap the old ones' texX to 1.0, and set the two new ones' texX to 0.0.
236
    ////////////////////////////////////////////////////////////////////////////////////////////////
237

  
238
    if( currentVert>=3 )
239
      {
240
      double tex1 = attribs[VERT_ATTRIBS*(currentVert-2) + TEX_ATTRIB];
241
      double tex2 = attribs[VERT_ATTRIBS*(currentVert-3) + TEX_ATTRIB];
242
      double y1   = attribs[VERT_ATTRIBS*(currentVert-2) + INF_ATTRIB + 1];
243
      double y2   = attribs[VERT_ATTRIBS*(currentVert-3) + INF_ATTRIB + 1];
244

  
245
      if( tex1!=tex2 || y1!=y2 )  // if the triangle is not degenerate
246
        {
247
        double diff1 = Math.abs(texX-tex1);
248
        double diff2 = Math.abs(texX-tex2);
249

  
250
        if( diff1>0.5 || diff2>0.5 )    // a jump in texture coords which can only happen along the
251
          {                             // 'date change' line. Have to correct!
252
          if( lastInRow )
253
            {
254
                            attribs[VERT_ATTRIBS*(currentVert-1) + TEX_ATTRIB] = 1.0f;
255
            if( tex1<tex2 ) attribs[VERT_ATTRIBS*(currentVert-2) + TEX_ATTRIB] = 1.0f;
256
            }
257
          else
258
            {
259
            if( latitude> -A )  // top two triangles being corrected
260
              {
261
              if (2*column+row-1 == level)  // last such triangle in a row; have to introduce extra 2 vertices.
262
                {
263
                /*
264
                android.util.Log.e("sphere", "LAST max diff exceeded: " + convertAng(longitude) + " " + convertAng(latitude) + " texX=" + texX);
265
                android.util.Log.d("sphere", " tex1=" + tex1 + " tex2=" + tex2 + " y1=" + y1 + " y2=" + y2);
266
                android.util.Log.d("sphere", " latV12=" + latV12 + " latV3=" + latV3);
267
                */
268
                repeatVertex(attribs, 2);
269
                repeatVertex(attribs, 2);
270

  
271
                attribs[VERT_ATTRIBS*(currentVert-1) + TEX_ATTRIB] = 0.0f;
272
                attribs[VERT_ATTRIBS*(currentVert-2) + TEX_ATTRIB] = 0.0f;
273
                attribs[VERT_ATTRIBS*(currentVert-3) + TEX_ATTRIB] = 1.0f;
274

  
275
                if (tex1 < tex2) attribs[VERT_ATTRIBS*(currentVert-4) + TEX_ATTRIB] = 1.0f;
276
                }
277
              if (2*column+row == level)    // not the last; just remap current vertex' texX to 1.0.
278
                {
279
                /*
280
                android.util.Log.e("sphere", "NOT LAST max diff exceeded: " + convertAng(longitude) + " " + convertAng(latitude) + " texX=" + texX);
281
                android.util.Log.d("sphere", " tex1=" + tex1 + " tex2=" + tex2 + " y1=" + y1 + " y2=" + y2);
282
                android.util.Log.d("sphere", " latV12=" + latV12 + " latV3=" + latV3);
283
                */
284
                attribs[VERT_ATTRIBS*(currentVert-1) + TEX_ATTRIB] = 1.0f;
285
                }
286
              }
287
            else // bottom triangle
288
              {
289
              /*
290
              android.util.Log.e("sphere", "BOTTOM LAST max diff exceeded: " + convertAng(longitude) + " " + convertAng(latitude) + " texX=" + texX);
291
              android.util.Log.d("sphere", " tex1=" + tex1 + " tex2=" + tex2 + " y1=" + y1 + " y2=" + y2);
292
              android.util.Log.d("sphere", " latV12=" + latV12 + " latV3=" + latV3);
293
              */
294
              repeatVertex(attribs, 2);
295
              repeatVertex(attribs, 2);
296

  
297
              attribs[VERT_ATTRIBS*(currentVert-3) + TEX_ATTRIB] = 1.0f;
298
              }
299
            }
300
          }
301
        }
302
      }
303

  
304
    ////////////////////////////////////////////////////////////////////////////////////////////////
305
    // End problem
306
    ////////////////////////////////////////////////////////////////////////////////////////////////
226 307
    }
227 308

  
228 309
///////////////////////////////////////////////////////////////////////////////////////////////////
......
233 314
      {
234 315
      for (int column=0; column<level-row; column++)
235 316
        {
236
        newVertex(attribs, column, row  , level, lonV1, lonV2, latV12, latV3);
237
        if (column==0 && !(face==0 && row==0 ) ) repeatLast(attribs);
238
        newVertex(attribs, column, row+1, level, lonV1, lonV2, latV12, latV3);
317
        addVertex(attribs, column, row  , level, lonV1, lonV2, latV12, latV3, false);
318
        if (column==0 && !(face==0 && row==0 ) ) repeatVertex(attribs,1);
319
        addVertex(attribs, column, row+1, level, lonV1, lonV2, latV12, latV3, false);
239 320
        }
240 321

  
241
      newVertex(attribs, level-row, row , level, lonV1, lonV2, latV12, latV3);
242
      if( row!=level-1 || face!=NUMFACES-1 ) repeatLast(attribs);
322
      addVertex(attribs, level-row, row , level, lonV1, lonV2, latV12, latV3, true);
323
      if( row!=level-1 || face!=NUMFACES-1 ) repeatVertex(attribs,1);
243 324
      }
244 325
    }
245 326

  

Also available in: Unified diff