📄 ebsrectangulartessellator.java
字号:
double exaggeratedMinElevation = makeSkirts ? globe.getMinElevation() * verticalExaggeration : 0; LatLon centroid = tile.sector.averageOfCorners(); Vec4 refCenter = globe.computePointFromPosition(centroid.getLatitude(), centroid.getLongitude(), 0d); int ie = 0; Iterator<LatLon> latLonIter = latlons.iterator(); int densityThisRow = density, numVerticesDroppedPerRow = 0; if (railEdges[2] == 2) { // see comments below in computeLocationsBetweenRailEdges numVerticesDroppedPerRow = 2; densityThisRow = 2 * density + numVerticesDroppedPerRow; } for (int j = 0; j <= density + 2; j++) { int i = 0; while (i <= densityThisRow + 2) { LatLon latlon = latLonIter.next(); double elevation = verticalExaggeration * elevations[ie++]; if (j == 0 || j >= tile.density + 2 || i == 0 || i >= densityThisRow + 2) { // use abs to account for negative elevation. elevation -= exaggeratedMinElevation >= 0 ? exaggeratedMinElevation : -exaggeratedMinElevation; } Vec4 p = globe.computePointFromPosition(latlon.getLatitude(), latlon.getLongitude(), elevation); verts.put(iv++, p.x - refCenter.x).put(iv++, p.y - refCenter.y).put(iv++, p.z - refCenter.z); i++; } densityThisRow -= numVerticesDroppedPerRow; } /* FOR RAIL EDGE TEXTURE COORDINATE LOGGING: curSectorPW.print("=====================================\n\n"); curSectorPW.flush(); */ return new RenderInfo(density, numVerticesDroppedPerRow, verts,// getPolarRegionTextureCoordinates(density,s,verts), texCoords, refCenter); } private ArrayList<LatLon> computeLocationsBetweenRailEdges(RectTile tile, int [] railEdges, double nominal_delta_t, DoubleBuffer texCoords) // Build vertices and texture coordinates along GreatEllipseEdges between railEdges[0] // and railEdges[1] { boolean sectorBordersLatLimit = (railEdges[2] > 0); boolean sectorHasLatLatBottom = (railEdges[2] == 2); // effectively a triangular patch. See below. int density = tile.density; int numVertices = (density + 3) * (density + 3); if (sectorHasLatLatBottom) // see comments below numVertices = (2*density)*(2*density)/4 + 3*(2*density) + 9; // Hmm. actually same as (d+3)^2... // One notable special case arises from the original LatLatLonLon case. As stated in analyzeEdgeBoundedSector, // a sector of this type appears only at the coarsest subdivision. However, subsequent subdivisions "push" this // special case out towards the midpoints of the original 8 vertices via LatLatGEGE sectors. The original // LatLatLonLon and LatLatGEGE sectors have in common (i) a degeneracy at the top since the two rail edges // will share a vertex there, and (ii) while the sector is technically 4-sided, the "LatLat" part of it // forms one geometrically continuous edge, making the sector geometrically triangular. There are two // relevant implications of this: (ii.a) we want to generate a triangular array of vertices to better match // the sector shape, and (ii.b) we need to blend between great ellipse transverse arcs near the vertex // shared by the two rail edges and the line of constant latitude (which is not a great ellipse) at the bottom // (LatLat) portion of the sector. Issue (ii.a) is handled in part by the use of "numVerticesDroppedPerRow" and // in part by "getTriangularIndices" (as called from "getIndices"). Issue (ii.b) is handled in the loop below: See // the use of "sectorBordersLatLimit". EdgeBoundedSector s = tile.getSector(); Edge re0 = s.getEdge(railEdges[0]); Edge re1 = s.getEdge(railEdges[1]); double rail_t = 1.0; double rail_delta_t = -nominal_delta_t; int densityThisRow = density, numVerticesDroppedPerRow = 0; if (sectorHasLatLatBottom) { // this sector has a triangular shape. It is either LatLatLonLon at coarsest // subdivision, or LatLatGEGE after one or more additional levels of subdivision. // We need to match the triangle pattern along the bottom (LatLat) end so that // it matches the triangle density of the same subdivision level immediately // below. But we want to drop off triangles from row to row, leaving a single // triangle at the top so that we get better triangle aspect ratios throughout. // we double the number of points on the bottom row so that it will correctly meet // the two sectors below it. But we need to drop vertices from row to row so that // we are left with a single vertex att he top. Since this needs to be done in // "density" (not 2*density) steps, we need to drop two vertices per row: numVerticesDroppedPerRow = 2; // "+ numVerticesDroppedPerRow" makes the skirt while allowing the density of the first // "real" row to be what it needs to be (2*density) so that it matches the sectors below. densityThisRow = 2 * density + numVerticesDroppedPerRow; } double sectorLonDelta = s.getDeltaLonRadians(); double sectorLatDelta = s.getDeltaLatRadians(); double sectorLonMin = s.getMinLongitude().radians; double sectorLatMin = s.getMinLatitude().radians; int ivTexCoords = 0; ArrayList<LatLon> latlons = new ArrayList<LatLon>(numVertices); for (int j = 0; j <= density + 2; j++) { LatLon re0Point = re0.arcLengthPointOnEdge(rail_t); LatLon re1Point = re1.arcLengthPointOnEdge(1.0-rail_t); GreatEllipseEdge ge = new GreatEllipseEdge(globe,re0Point,re1Point); double transverse_t = 0.0; double transverse_delta_t = 1.0 / densityThisRow; int i = 0; while (i <= densityThisRow + 2) { LatLon transverse_pnt = ge.arcLengthPointOnEdge(transverse_t); if (sectorBordersLatLimit) { // blend with point computed based on linear blend in lat-lon // space of two rail points. This converges to a line of constant // latitude where the sector meets the latitude cutoff point. double re0LatRadians = re0Point.getLatitude().getRadians(); double re0LonRadians = re0Point.getLongitude().getRadians(); double re1LatRadians = re1Point.getLatitude().getRadians(); double re1LonRadians = re1Point.getLongitude().getRadians(); double LinBlendPointLat = (1.0-transverse_t)*re0LatRadians + transverse_t*re1LatRadians; double LinBlendPointLon = (1.0-transverse_t)*re0LonRadians + transverse_t*re1LonRadians; double tpLat = transverse_pnt.getLatitude().getRadians(); double tpLon = transverse_pnt.getLongitude().getRadians(); double alpha = 1.0 - rail_t; double bLat = (1.0 - alpha)*LinBlendPointLat + alpha*tpLat; double bLon = (1.0 - alpha)*LinBlendPointLon + alpha*tpLon; transverse_pnt = LatLon.fromRadians(bLat,bLon); } Angle lat = transverse_pnt.getLatitude(); Angle lon = transverse_pnt.getLongitude(); latlons.add( new LatLon(lat,lon) ); double sTexCoord = (lon.radians - sectorLonMin)/sectorLonDelta; double tTexCoord = (lat.radians - sectorLatMin)/sectorLatDelta; // avoid bad numerical roundoff if (sTexCoord < 0.0) sTexCoord = 0.0; else if (sTexCoord > 1.0) sTexCoord = 1.0; if (tTexCoord < 0.0) tTexCoord = 0.0; else if (tTexCoord > 1.0) tTexCoord = 1.0; /* FOR RAIL EDGE TEXTURE COORDINATE LOGGING: curSectorPW.print(sTexCoord + " , " + tTexCoord + "\n"); */ texCoords.put(ivTexCoords++, sTexCoord); texCoords.put(ivTexCoords++, tTexCoord); if (i >= densityThisRow) transverse_t = 1.0; else if (i != 0) transverse_t += transverse_delta_t; i++; } densityThisRow -= numVerticesDroppedPerRow; if (j >= density) rail_t = 0.0; else if (j != 0) rail_t += rail_delta_t; } /* FOR RAIL EDGE TEXTURE COORDINATE LOGGING: curSectorPW.print("=====================================\n\n"); curSectorPW.flush(); */ return latlons; } // The following is the original RectangularTessellator.buildVerts: public RenderInfo buildVertsOnLateralTile(DrawContext dc, RectTile tile, boolean makeSkirts) { int density = tile.density; int numVertices = (density + 3) * (density + 3); DoubleBuffer verts = BufferUtil.newDoubleBuffer(numVertices * 3); ArrayList<LatLon> latlons = this.computeLocationsOnLateralTile(tile); double[] elevations = new double[latlons.size()]; dc.getGlobe().getElevations(tile.sector, latlons, tile.getResolution(), elevations); int iv = 0; double verticalExaggeration = dc.getVerticalExaggeration(); double exaggeratedMinElevation = makeSkirts ? globe.getMinElevation() * verticalExaggeration : 0; LatLon centroid = tile.sector.getCentroid(); Vec4 refCenter = globe.computePointFromPosition(centroid.getLatitude(), centroid.getLongitude(), 0d); int ie = 0; Iterator<LatLon> latLonIter = latlons.iterator(); for (int j = 0; j <= density + 2; j++) { for (int i = 0; i <= density + 2; i++) { LatLon latlon = latLonIter.next(); double elevation = verticalExaggeration * elevations[ie++]; if (j == 0 || j >= tile.density + 2 || i == 0 || i >= tile.density + 2) { // use abs to account for negative elevation. elevation -= exaggeratedMinElevation >= 0 ? exaggeratedMinElevation : -exaggeratedMinElevation; } Vec4 p = globe.computePointFromPosition(latlon.getLatitude(), latlon.getLongitude(), elevation); verts.put(iv++, p.x - refCenter.x).put(iv++, p.y - refCenter.y).put(iv++, p.z - refCenter.z); } } return new RenderInfo(density, 0, verts, getLateralSideTextureCoordinates(density), refCenter); } // The following is the original RectangularTessellator.computeLocations: private ArrayList<LatLon> computeLocationsOnLateralTile(RectTile tile) { int density = tile.density; int numVertices = (density + 3) * (density + 3); Angle latMax = tile.sector.getMaxLatitude(); Angle dLat = tile.sector.getDeltaLat().divide(density); Angle lat = tile.sector.getMinLatitude(); Angle lonMin = tile.sector.getMinLongitude(); Angle lonMax = tile.sector.getMaxLongitude(); Angle dLon = tile.sector.getDeltaLon().divide(density); ArrayList<LatLon> latlons = new ArrayList<LatLon>(numVertices); for (int j = 0; j <= density + 2; j++) { Angle lon = lonMin; for (int i = 0; i <= density + 2; i++) { latlons.add(new LatLon(lat, lon)); if (i > density) lon = lonMax; else if (i != 0) lon = lon.add(dLon); if (lon.degrees < -180) lon = Angle.NEG180; else if (lon.degrees > 180) lon = Angle.POS180; } if (j > density) lat = latMax; else if (j != 0) lat = lat.add(dLat); } return latlons; } private void renderMultiTexture(DrawContext dc, RectTile tile, int numTextureUnits) { if (dc == null) { String msg = Logging.getMessage("nullValue.DrawContextIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } if (numTextureUnits < 1) { String msg = Logging.getMessage("generic.NumTextureUnitsLessThanOne"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } this.render(dc, tile, numTextureUnits); } private void render(DrawContext dc, RectTile tile) { if (dc == null) { String msg = Logging.getMessage("nullValue.DrawContextIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } this.render(dc, tile, 1); } private long render(DrawContext dc, RectTile tile, int numTextureUnits) { if (tile.ri == null) { String msg = Logging.getMessage("nullValue.RenderInfoIsNull"); Logging.logger().severe(msg); throw new IllegalStateException(msg); } dc.getView().pushReferenceCenter(dc, tile.ri.referenceCenter); GL gl = dc.getGL(); gl.glPushClientAttrib(GL.GL_CLIENT_VERTEX_ARRAY_BIT); gl.glEnableClientState(GL.GL_VERTEX_ARRAY); gl.glVertexPointer(3, GL.GL_DOUBLE, 0, tile.ri.vertices.rewind()); for (int i = 0; i < numTextureUnits; i++) { gl.glClientActiveTexture(GL.GL_TEXTURE0 + i); gl.glEnableClientState(GL.GL_TEXTURE_COORD_ARRAY); gl.glTexCoordPointer(2, GL.GL_DOUBLE, 0, tile.ri.texCoords.rewind()); } gl.glDrawElements(javax.media.opengl.GL.GL_TRIANGLE_STRIP, tile.ri.indices.limit(), javax.media.opengl.GL.GL_UNSIGNED_INT, tile.ri.indices.rewind()); gl.glPopClientAttrib(); dc.getView().popReferenceCenter(dc); return tile.ri.indices.limit() - 2; // return number of triangles rendered } private void renderWireframe(DrawContext dc, RectTile tile, boolean showTriangles, boolean showTileBoundary) { if (dc == null) { String msg = Logging.getMessage("nullValue.DrawContextIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } if (tile.ri == null) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -