Revision b72b8a3b
Added by Leszek Koltunski almost 7 years ago
| 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
Fix (hopefully the last!) probelm with texturing the Sphere: the seam in the back.