org.oscim.layers.tile.buildings.BuildingRenderer Maven / Gradle / Ivy
/*
* Copyright 2013 Hannes Janetzek
* Copyright 2018 devemux86
* Copyright 2018 Gustl22
*
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see .
*/
package org.oscim.layers.tile.buildings;
import org.oscim.layers.tile.MapTile;
import org.oscim.layers.tile.TileDistanceSort;
import org.oscim.layers.tile.TileRenderer;
import org.oscim.layers.tile.TileSet;
import org.oscim.layers.tile.ZoomLimiter;
import org.oscim.renderer.ExtrusionRenderer;
import org.oscim.renderer.GLViewport;
import org.oscim.renderer.MapRenderer;
import org.oscim.renderer.bucket.ExtrusionBuckets;
import org.oscim.renderer.bucket.RenderBuckets;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.HashSet;
import java.util.Set;
import static java.lang.System.currentTimeMillis;
import static org.oscim.layers.tile.MapTile.State.NEW_DATA;
import static org.oscim.layers.tile.MapTile.State.READY;
import static org.oscim.utils.FastMath.clamp;
public class BuildingRenderer extends ExtrusionRenderer {
static final Logger log = LoggerFactory.getLogger(BuildingRenderer.class);
private final TileRenderer mTileRenderer;
private final TileSet mTileSet;
private final ZoomLimiter mZoomLimiter;
private final float mFadeInTime = 250;
private final float mFadeOutTime = 400;
private long mAnimTime;
private boolean mShow;
public BuildingRenderer(TileRenderer tileRenderer, ZoomLimiter zoomLimiter,
boolean mesh, boolean translucent) {
super(mesh, translucent);
mZoomLimiter = zoomLimiter;
mTileRenderer = tileRenderer;
mTileSet = new TileSet();
}
@Override
public boolean setup() {
mAlpha = 0;
return super.setup();
}
@Override
public void update(GLViewport v) {
super.update(v);
int diff = (v.pos.zoomLevel - mZoomLimiter.getMinZoom());
/* if below min zoom or already faded out */
if (diff < -1) {
mAlpha = 0;
mShow = false;
setReady(false);
return;
}
if (diff >= 0) {
if (mAlpha < 1) {
long now = currentTimeMillis();
if (!mShow)
mAnimTime = now - (long) (mAlpha * mFadeInTime);
mShow = true;
mAlpha = clamp((now - mAnimTime) / mFadeInTime, 0, 1);
MapRenderer.animate();
}
} else {
if (mAlpha > 0) {
long now = currentTimeMillis();
if (mShow)
mAnimTime = now - (long) ((1 - mAlpha) * mFadeOutTime);
mShow = false;
mAlpha = clamp(1 - (now - mAnimTime) / mFadeOutTime, 0, 1);
MapRenderer.animate();
}
}
if (mAlpha == 0) {
setReady(false);
return;
}
Integer zoom = mTileRenderer.getVisibleTiles(mTileSet, true);
if (mTileSet.cnt == 0 || zoom == null) {
mTileRenderer.releaseTiles(mTileSet);
setReady(false);
return;
}
MapTile[] tiles = mTileSet.tiles;
TileDistanceSort.sort(tiles, 0, mTileSet.cnt);
/* keep a list of tiles available for rendering */
int maxTiles = mTileSet.cnt * 4;
if (mExtrusionBucketSet.length < maxTiles)
mExtrusionBucketSet = new ExtrusionBuckets[maxTiles];
/* compile one tile max per frame */
boolean compiled = false;
int activeTiles = 0;
if (zoom >= mZoomLimiter.getMinZoom() && zoom <= mZoomLimiter.getZoomLimit()) {
/* TODO - if tile is not available try parent or children */
for (int i = 0; i < mTileSet.cnt; i++) {
ExtrusionBuckets ebs = getBuckets(tiles[i]);
if (ebs == null)
continue;
if (ebs.compiled)
mExtrusionBucketSet[activeTiles++] = ebs;
else if (!compiled && ebs.compile()) {
mExtrusionBucketSet[activeTiles++] = ebs;
compiled = true;
}
}
} else if (zoom > mZoomLimiter.getZoomLimit() && zoom <= mZoomLimiter.getMaxZoom()) {
// render from zoom limit tiles (avoid duplicates and null)
Set hashTiles = new HashSet<>();
for (int i = 0; i < mTileSet.cnt; i++) {
MapTile t = mZoomLimiter.getTile(tiles[i]);
if (t == null)
continue;
if (!hashTiles.add(t))
continue;
ExtrusionBuckets ebs = getBuckets(t);
if (ebs == null)
continue;
if (ebs.compiled)
mExtrusionBucketSet[activeTiles++] = ebs;
else if (!compiled && ebs.compile()) {
mExtrusionBucketSet[activeTiles++] = ebs;
compiled = true;
}
}
} else if (zoom == mZoomLimiter.getMinZoom() - 1) {
/* check if proxy children are ready */
for (int i = 0; i < mTileSet.cnt; i++) {
MapTile t = tiles[i];
for (byte j = 0; j < 4; j++) {
if (!t.hasProxy(1 << j))
continue;
MapTile c = t.node.child(j);
ExtrusionBuckets eb = getBuckets(c);
if (eb == null || !eb.compiled)
continue;
mExtrusionBucketSet[activeTiles++] = eb;
}
}
}
/* load more tiles on next frame */
if (compiled)
MapRenderer.animate();
mBucketsCnt = activeTiles;
//log.debug("active tiles: {}", mExtrusionLayerCnt);
if (activeTiles == 0) {
mTileRenderer.releaseTiles(mTileSet);
setReady(false);
return;
}
setReady(true);
}
@Override
public void render(GLViewport v) {
super.render(v);
/* release lock on tile data */
mTileRenderer.releaseTiles(mTileSet);
}
private static ExtrusionBuckets getBuckets(MapTile t) {
RenderBuckets buckets = t.getBuckets();
if (buckets != null && !t.state(READY | NEW_DATA))
return null;
return BuildingLayer.get(t);
}
}