?? rectangularnormaltessellator.java
字號:
private void selectVisibleTiles(DrawContext dc, RectTile tile)
{
Extent extent = tile.getExtent();
if (extent != null && !extent.intersects(this.currentFrustum))
return;
if (this.currentLevel < this.maxLevel - 1 && this.needToSplit(dc, tile))
{
++this.currentLevel;
RectTile[] subtiles = this.split(dc, tile);
for (RectTile child : subtiles)
{
this.selectVisibleTiles(dc, child);
}
--this.currentLevel;
return;
}
this.currentCoverage = tile.getSector().union(this.currentCoverage);
this.currentTiles.add(tile);
}
private boolean needToSplit(DrawContext dc, RectTile tile)
{
Vec4[] corners = tile.sector.computeCornerPoints(dc.getGlobe(), dc.getVerticalExaggeration());
Vec4 centerPoint = tile.sector.computeCenterPoint(dc.getGlobe(), dc.getVerticalExaggeration());
View view = dc.getView();
double d1 = view.getEyePoint().distanceTo3(corners[0]);
double d2 = view.getEyePoint().distanceTo3(corners[1]);
double d3 = view.getEyePoint().distanceTo3(corners[2]);
double d4 = view.getEyePoint().distanceTo3(corners[3]);
double d5 = view.getEyePoint().distanceTo3(centerPoint);
double minDistance = d1;
if (d2 < minDistance)
minDistance = d2;
if (d3 < minDistance)
minDistance = d3;
if (d4 < minDistance)
minDistance = d4;
if (d5 < minDistance)
minDistance = d5;
double logDist = Math.log10(minDistance);
boolean useTile = tile.log10CellSize <= (logDist - DEFAULT_LOG10_RESOLUTION_TARGET);
return !useTile;
}
private RectTile[] split(DrawContext dc, RectTile tile)
{
Sector[] sectors = tile.sector.subdivide();
RectTile[] subTiles = new RectTile[4];
subTiles[0] = this.createTile(dc, sectors[0], tile.level + 1);
subTiles[1] = this.createTile(dc, sectors[1], tile.level + 1);
subTiles[2] = this.createTile(dc, sectors[2], tile.level + 1);
subTiles[3] = this.createTile(dc, sectors[3], tile.level + 1);
return subTiles;
}
private RectangularNormalTessellator.CacheKey createCacheKey(DrawContext dc, RectTile tile)
{
return new CacheKey(dc, tile.sector, tile.density);
}
private void makeVerts(DrawContext dc, RectTile tile)
{
// First see if the vertices have been previously computed and are in the cache. Since the elevation model
// can change between frames, regenerate and re-cache vertices every second.
MemoryCache cache = WorldWind.getMemoryCache(CACHE_ID);
CacheKey cacheKey = this.createCacheKey(dc, tile);
tile.ri = (RenderInfo) cache.getObject(cacheKey);
if (tile.ri != null && tile.ri.time >= System.currentTimeMillis() - 1000) // Regenerate cache after one second
return;
tile.ri = this.buildVerts(dc, tile, this.makeTileSkirts);
if (tile.ri != null)
{
cacheKey = this.createCacheKey(dc, tile);
cache.add(cacheKey, tile.ri, tile.ri.getSizeInBytes());
}
}
public RenderInfo buildVerts(DrawContext dc, RectTile tile, boolean makeSkirts)
{
int density = tile.density;
int side = density + 3;
int numVertices = side * side;
java.nio.DoubleBuffer verts = BufferUtil.newDoubleBuffer(numVertices * 3);
ArrayList<LatLon> latlons = this.computeLocations(tile);
double[] elevations = new double[latlons.size()];
dc.getGlobe().getElevations(tile.sector, latlons, tile.getResolution(), elevations);
Globe globe = dc.getGlobe();
Angle dLat = tile.sector.getDeltaLat().divide(density);
Angle latMin = tile.sector.getMinLatitude();
Angle latMax = tile.sector.getMaxLatitude();
Angle dLon = tile.sector.getDeltaLon().divide(density);
Angle lonMin = tile.sector.getMinLongitude();
Angle lonMax = tile.sector.getMaxLongitude();
Angle lat, lon;
int iv = 0;
double elevation, verticalExaggeration = dc.getVerticalExaggeration();
Vec4 p;
LatLon centroid = tile.sector.getCentroid();
Vec4 refCenter = globe.computePointFromPosition(centroid.getLatitude(), centroid.getLongitude(), 0d);
int ie = 0;
Iterator<LatLon> latLonIter = latlons.iterator();
// Compute verts without skirts
for (int j = 0; j < side; j++)
{
for (int i = 0; i < side; i++)
{
LatLon latlon = latLonIter.next();
elevation = verticalExaggeration * elevations[ie++];
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);
}
}
// Compute indices and normals
java.nio.IntBuffer indices = getIndices(density);
java.nio.DoubleBuffer norms = getNormals(density, verts, indices, refCenter);
// Fold down the sides as skirts
double exaggeratedMinElevation = makeSkirts ? Math.abs(globe.getMinElevation() * verticalExaggeration) : 0;
lat = latMin;
for (int j = 0; j < side; j++)
{
//min longitude side
ie = j * side + 1;
elevation = verticalExaggeration * elevations[ie];
elevation -= exaggeratedMinElevation >= 0 ? exaggeratedMinElevation : -exaggeratedMinElevation;
p = globe.computePointFromPosition(lat, lonMin, elevation);
iv = (j * side) * 3;
verts.put(iv++, p.x - refCenter.x).put(iv++, p.y - refCenter.y)
.put(iv++, p.z - refCenter.z);
//max longitude side
ie += side - 2;
elevation = verticalExaggeration * elevations[ie];
elevation -= exaggeratedMinElevation >= 0 ? exaggeratedMinElevation : -exaggeratedMinElevation;
p = globe.computePointFromPosition(lat, lonMax, elevation);
iv = ((j + 1) * side - 1) * 3;
verts.put(iv++, p.x - refCenter.x).put(iv++, p.y - refCenter.y)
.put(iv++, p.z - refCenter.z);
if (j > density)
lat = latMax;
else if (j != 0)
lat = lat.add(dLat);
}
lon = lonMin;
for (int i = 0; i < side; i++)
{
//min latitude side
ie = i + side;
elevation = verticalExaggeration * elevations[ie];
elevation -= exaggeratedMinElevation >= 0 ? exaggeratedMinElevation : -exaggeratedMinElevation;
p = globe.computePointFromPosition(latMin, lon, elevation);
iv = i * 3;
verts.put(iv++, p.x - refCenter.x).put(iv++, p.y - refCenter.y)
.put(iv++, p.z - refCenter.z);
//max latitude side
ie += (side - 2) * side;
elevation = verticalExaggeration * elevations[ie];
elevation -= exaggeratedMinElevation >= 0 ? exaggeratedMinElevation : -exaggeratedMinElevation;
p = globe.computePointFromPosition(latMax, lon, elevation);
iv = (side * (side - 1) + i) * 3;
verts.put(iv++, p.x - refCenter.x).put(iv++, p.y - refCenter.y)
.put(iv++, p.z - refCenter.z);
if (i > density)
lon = lonMax;
else if (i != 0)
lon = lon.add(dLon);
}
return new RenderInfo(density, verts, getTextureCoordinates(density), norms, refCenter);
}
private ArrayList<LatLon> computeLocations(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().subtract(dLat);
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.subtract(dLon);
for (int i = 0; i <= density + 2; i++)
{
latlons.add(new LatLon(lat, lon));
lon = lon.add(dLon);
if (lon.degrees < -180)
lon = Angle.NEG180;
else if (lon.degrees > 180)
lon = Angle.POS180;
}
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);
if (!dc.isPickingMode() && this.lightDirection != null)
beginLighting(dc);
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());
gl.glEnableClientState(GL.GL_NORMAL_ARRAY);
gl.glNormalPointer(GL.GL_DOUBLE, 0, tile.ri.normals.rewind());
for (int i = 0; i < numTextureUnits; i++)
{
gl.glClientActiveTexture(GL.GL_TEXTURE0 + i);
gl.glEnableClientState(GL.GL_TEXTURE_COORD_ARRAY);
Object texCoords = dc.getValue(AVKey.TEXTURE_COORDINATES);
if (texCoords != null && texCoords instanceof DoubleBuffer)
gl.glTexCoordPointer(2, GL.GL_DOUBLE, 0, ((DoubleBuffer) texCoords).rewind());
else
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.glDisableClientState(GL.GL_NORMAL_ARRAY);
gl.glPopClientAttrib();
if (!dc.isPickingMode() && this.lightDirection != null)
endLighting(dc);
dc.getView().popReferenceCenter(dc);
return tile.ri.indices.limit() - 2; // return number of triangles rendered
}
private void beginLighting(DrawContext dc)
{
GL gl = dc.getGL();
gl.glPushAttrib(GL.GL_ENABLE_BIT | GL.GL_CURRENT_BIT | GL.GL_LIGHTING_BIT);
this.material.apply(gl, GL.GL_FRONT);
gl.glDisable(GL.GL_COLOR_MATERIAL);
float[] lightPosition = {(float)-lightDirection.x, (float)-lightDirection.y, (float)-lightDirection.z, 0.0f};
float[] lightDiffuse = new float[4];
float[] lightAmbient = new float[4];
lightColor.getRGBComponents(lightDiffuse);
ambientColor.getRGBComponents(lightAmbient);
gl.glLightfv(GL.GL_LIGHT1, GL.GL_POSITION, lightPosition, 0);
gl.glLightfv(GL.GL_LIGHT1, GL.GL_DIFFUSE, lightDiffuse, 0);
gl.glLightfv(GL.GL_LIGHT1, GL.GL_AMBIENT, lightAmbient, 0);
gl.glDisable(GL.GL_LIGHT0);
gl.glEnable(GL.GL_LIGHT1);
gl.glEnable(GL.GL_LIGHTING);
}
private void endLighting(DrawContext dc)
{
GL gl = dc.getGL();
gl.glDisable(GL.GL_LIGHT1);
gl.glEnable(GL.GL_LIGHT0);
gl.glDisable(GL.GL_LIGHTING);
gl.glPopAttrib();
}
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)
{
String msg = Logging.getMessage("nullValue.RenderInfoIsNull");
Logging.logger().severe(msg);
throw new IllegalStateException(msg);
}
java.nio.IntBuffer indices = getIndices(tile.ri.density);
indices.rewind();
dc.getView().pushReferenceCenter(dc, tile.ri.referenceCenter);
javax.media.opengl.GL gl = dc.getGL();
gl.glPushAttrib(GL.GL_DEPTH_BUFFER_BIT | GL.GL_POLYGON_BIT
| GL.GL_TEXTURE_BIT | GL.GL_ENABLE_BIT | GL.GL_CURRENT_BIT);
gl.glEnable(GL.GL_BLEND);
gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE);
gl.glDisable(javax.media.opengl.GL.GL_DEPTH_TEST);
gl.glEnable(javax.media.opengl.GL.GL_CULL_FACE);
gl.glCullFace(javax.media.opengl.GL.GL_BACK);
gl.glDisable(javax.media.opengl.GL.GL_TEXTURE_2D);
gl.glColor4d(1d, 1d, 1d, 0.2);
gl.glPolygonMode(javax.media.opengl.GL.GL_FRONT,
javax.media.opengl.GL.GL_LINE);
if (showTriangles)
{
gl.glPushClientAttrib(GL.GL_CLIENT_VERTEX_ARRAY_BIT);
gl.glEnableClientState(GL.GL_VERTEX_ARRAY);
gl.glVertexPointer(3, GL.GL_DOUBLE, 0, tile.ri.vertices);
gl.glDrawElements(javax.media.opengl.GL.GL_TRIANGLE_STRIP, indices
.limit(), javax.media.opengl.GL.GL_UNSIGNED_INT, indices);
gl.glPopClientAttrib();
}
dc.getView().popReferenceCenter(dc);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -