
org.oscim.renderer.MapRenderer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of vtm Show documentation
Show all versions of vtm Show documentation
OpenGL vector map library written in Java - running on Android, iOS, Desktop and within the browser.
The newest version!
/*
* Copyright 2012, 2013 Hannes Janetzek
* Copyright 2016 Longri
* Copyright 2018-2022 devemux86
*
* 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 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 License for more details.
*
* You should have received a copy of the GNU Lesser General License along with
* this program. If not, see .
*/
package org.oscim.renderer;
import org.oscim.backend.GL;
import org.oscim.backend.GLAdapter;
import org.oscim.backend.canvas.Color;
import org.oscim.map.Map;
import org.oscim.renderer.bucket.RenderBuckets;
import org.oscim.renderer.bucket.TextureItem;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.ShortBuffer;
import static org.oscim.backend.GLAdapter.gl;
public class MapRenderer {
private static final Logger log = LoggerFactory.getLogger(MapRenderer.class);
/**
* scale factor used for short vertices
*/
public static float COORD_SCALE = 8.0f;
private final Map mMap;
private final GLViewport mViewport;
private static float[] mClearColor;
private static int mQuadIndicesID;
private static int mQuadVerticesID;
/**
* Number of Quads that can be rendered with bindQuadIndicesVBO()
*/
public static final int MAX_QUADS = 512;
/**
* Number of Indices that can be rendered with bindQuadIndicesVBO()
*/
public static final int MAX_INDICES = MAX_QUADS * 6;
public static long frametime;
private static boolean rerender;
private static NativeBufferPool mBufferPool;
private float viewPortScale = 1;
public MapRenderer(Map map) {
mMap = map;
mViewport = new GLViewport();
mBufferPool = new NativeBufferPool();
/* FIXME should be done in 'destroy' method
* clear all previous vbo refs */
BufferObject.clear();
setBackgroundColor(Color.DKGRAY);
}
public static void setBackgroundColor(int color) {
mClearColor = GLUtils.colorToFloat(color);
}
/**
* Set the scale value for map viewport.
*/
public void setViewPortScale(float scale) {
this.viewPortScale = scale;
}
public void onDrawFrame() {
frametime = System.currentTimeMillis();
rerender = false;
mMap.beginFrame();
try {
draw();
} catch (Throwable t) {
log.error(t.toString(), t);
}
mMap.doneFrame(rerender);
mBufferPool.releaseBuffers();
TextureItem.disposeTextures();
}
private void draw() {
GLState.setClearColor(mClearColor);
gl.depthMask(true);
gl.stencilMask(0xFF);
gl.clear(GL.COLOR_BUFFER_BIT
| GL.DEPTH_BUFFER_BIT
| GL.STENCIL_BUFFER_BIT);
gl.depthMask(false);
gl.stencilMask(0);
GLState.test(false, false);
GLState.blend(false);
GLState.bindTex2D(GLState.DISABLED);
GLState.useProgram(GLState.DISABLED);
GLState.bindElementBuffer(GLState.DISABLED);
GLState.bindVertexBuffer(GLState.DISABLED);
mViewport.setFrom(mMap);
if (GLAdapter.debugView) {
/* modify this to scale only the view, to see
* which tiles are rendered */
mViewport.mvp.setScale(0.5f, 0.5f, 1);
mViewport.viewproj.multiplyLhs(mViewport.mvp);
mViewport.proj.multiplyLhs(mViewport.mvp);
}
if (this.viewPortScale != 1) {
mViewport.mvp.setScale(this.viewPortScale, this.viewPortScale, 1);
mViewport.viewproj.multiplyLhs(mViewport.mvp);
mViewport.proj.multiplyLhs(mViewport.mvp);
}
/* update layers */
LayerRenderer[] layers = mMap.layers().getLayerRenderer();
for (int i = 0, n = layers.length; i < n; i++) {
LayerRenderer renderer = layers[i];
if (renderer == null)
continue;
if (!renderer.isInitialized) {
renderer.setup();
renderer.isInitialized = true;
}
renderer.update(mViewport);
if (renderer.isReady)
renderer.render(mViewport);
if (GLAdapter.debug)
GLUtils.checkGlError(renderer.getClass().getName());
}
if (GLUtils.checkGlError(getClass().getName() + ": finish", GL.OUT_OF_MEMORY)) {
BufferObject.checkBufferUsage(true);
// FIXME also throw out some textures etc
}
}
public void onSurfaceChanged(int width, int height) {
//log.debug("onSurfaceChanged: new={}, {}x{}", mNewSurface, width, height);
if (width <= 0 || height <= 0)
return;
GLState.viewport(width, height);
//GL.scissor(0, 0, width, height);
//GL.enable(GL20.SCISSOR_TEST);
gl.clearStencil(0x00);
gl.disable(GL.CULL_FACE);
gl.blendFunc(GL.ONE, GL.ONE_MINUS_SRC_ALPHA);
gl.frontFace(GL.CW);
gl.cullFace(GL.BACK);
if (!mNewSurface) {
mMap.updateMap(false);
return;
}
mNewSurface = false;
/* initialize quad indices used by Texture- and LineTexRenderer */
int[] vboIds = GLUtils.glGenBuffers(2);
mQuadIndicesID = vboIds[0];
short[] indices = new short[MAX_INDICES];
for (int i = 0, j = 0; i < MAX_INDICES; i += 6, j += 4) {
indices[i + 0] = (short) (j + 0);
indices[i + 1] = (short) (j + 1);
indices[i + 2] = (short) (j + 2);
indices[i + 3] = (short) (j + 2);
indices[i + 4] = (short) (j + 1);
indices[i + 5] = (short) (j + 3);
}
ShortBuffer buf = MapRenderer.getShortBuffer(indices.length);
buf.put(indices);
buf.flip();
GLState.bindElementBuffer(mQuadIndicesID);
gl.bufferData(GL.ELEMENT_ARRAY_BUFFER,
indices.length * 2, buf,
GL.STATIC_DRAW);
GLState.bindElementBuffer(GLState.UNBIND);
/* initialize default quad */
FloatBuffer floatBuffer = MapRenderer.getFloatBuffer(8);
float[] quad = new float[]{-1, -1, -1, 1, 1, -1, 1, 1};
floatBuffer.put(quad);
floatBuffer.flip();
mQuadVerticesID = vboIds[1];
GLState.bindVertexBuffer(mQuadVerticesID);
gl.bufferData(GL.ARRAY_BUFFER,
quad.length * 4, floatBuffer,
GL.STATIC_DRAW);
GLState.bindVertexBuffer(GLState.UNBIND);
GLState.init();
mMap.updateMap(true);
}
public void onSurfaceCreated() {
// log.debug(GL.getString(GL20.EXTENSIONS));
String vendor = gl.getString(GL.VENDOR);
String renderer = gl.getString(GL.RENDERER);
String version = gl.getString(GL.VERSION);
log.debug("{}/{}/{}", vendor, renderer, version);
// Prevent issue with Adreno 3xx series
if (renderer != null && renderer.startsWith("Adreno (TM) 3")) {
log.debug("==> not using glBufferSubData");
GLAdapter.NO_BUFFER_SUB_DATA = true;
}
GLState.init();
// Set up some vertex buffer objects
BufferObject.init(200);
// classes that require GL context for initialization
RenderBuckets.initRenderer();
mNewSurface = true;
}
private boolean mNewSurface;
/**
* Bind VBO for a simple quad. Handy for simple custom RenderLayers
* Vertices: float[]{ -1, -1, -1, 1, 1, -1, 1, 1 }
*
* GL.drawArrays(GL20.TRIANGLE_STRIP, 0, 4);
*/
public static void bindQuadVertexVBO(int location) {
if (location >= 0) {
GLState.bindVertexBuffer(mQuadVerticesID);
GLState.enableVertexArrays(location, GLState.DISABLED);
gl.vertexAttribPointer(location, 2, GL.FLOAT, false, 0, 0);
}
}
/**
* Bind indices for rendering up to MAX_QUADS (512),
* ie. MAX_INDICES (512*6) in one draw call.
* Vertex order is 0-1-2 2-1-3
*/
public static void bindQuadIndicesVBO() {
GLState.bindElementBuffer(mQuadIndicesID);
}
/**
* Trigger next redraw from GL-Thread. This should be used to animate
* LayerRenderers instead of calling Map.render().
*/
public static void animate() {
rerender = true;
}
public static FloatBuffer getFloatBuffer(int size) {
return mBufferPool.getFloatBuffer(size);
}
public static ShortBuffer getShortBuffer(int size) {
return mBufferPool.getShortBuffer(size);
}
public static IntBuffer getIntBuffer(int size) {
return mBufferPool.getIntBuffer(size);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy