259 lines
6.2 KiB
Java
259 lines
6.2 KiB
Java
/*
|
|
* Copyright 2012 Hannes Janetzek
|
|
*
|
|
* 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 <http://www.gnu.org/licenses/>.
|
|
*/
|
|
package org.oscim.renderer.bucket;
|
|
|
|
import org.oscim.renderer.bucket.VertexData.Chunk;
|
|
import org.oscim.utils.FastMath;
|
|
import org.oscim.utils.pool.Inlist;
|
|
import org.oscim.utils.pool.SyncPool;
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
import java.nio.ShortBuffer;
|
|
|
|
/**
|
|
* A linked list of array chunks to hold temporary vertex data.
|
|
* <p/>
|
|
* TODO override append() etc to update internal (cur) state.
|
|
*/
|
|
public class VertexData extends Inlist.List<Chunk> {
|
|
static final Logger log = LoggerFactory.getLogger(VertexData.class);
|
|
|
|
/**
|
|
* Size of array chunks. Must be multiple of:
|
|
* 4 (LineLayer/PolygonLayer),
|
|
* 24 (TexLineLayer - one block, i.e. two segments)
|
|
* 24 (TextureLayer)
|
|
*/
|
|
public static final int SIZE = 360;
|
|
|
|
/**
|
|
* Shared chunk pool size.
|
|
*/
|
|
private static final int MAX_POOL = 500;
|
|
|
|
public static class Chunk extends Inlist<Chunk> {
|
|
public final short[] vertices = new short[SIZE];
|
|
public int used;
|
|
}
|
|
|
|
private static class Pool extends SyncPool<Chunk> {
|
|
public Pool() {
|
|
super(MAX_POOL);
|
|
}
|
|
|
|
@Override
|
|
protected Chunk createItem() {
|
|
return new Chunk();
|
|
}
|
|
|
|
@Override
|
|
protected boolean clearItem(Chunk it) {
|
|
it.used = 0;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
public int countSize() {
|
|
if (cur == null)
|
|
return 0;
|
|
|
|
cur.used = used;
|
|
|
|
int size = 0;
|
|
for (Chunk it = head(); it != null; it = it.next)
|
|
size += it.used;
|
|
|
|
return size;
|
|
}
|
|
|
|
@Override
|
|
public Chunk clear() {
|
|
if (cur == null)
|
|
return null;
|
|
|
|
cur.used = used;
|
|
used = SIZE; /* set SIZE to get new item on add */
|
|
cur = null;
|
|
vertices = null;
|
|
|
|
return super.clear();
|
|
}
|
|
|
|
private static final Pool pool = new Pool();
|
|
|
|
public void dispose() {
|
|
pool.releaseAll(super.clear());
|
|
used = SIZE; /* set SIZE to get new item on add */
|
|
cur = null;
|
|
vertices = null;
|
|
}
|
|
|
|
/**
|
|
* @return sum of elements added
|
|
*/
|
|
public int compile(ShortBuffer sbuf) {
|
|
if (cur == null)
|
|
return 0;
|
|
|
|
cur.used = used;
|
|
|
|
int size = 0;
|
|
for (Chunk it = head(); it != null; it = it.next) {
|
|
size += it.used;
|
|
sbuf.put(it.vertices, 0, it.used);
|
|
}
|
|
dispose();
|
|
return size;
|
|
}
|
|
|
|
private Chunk cur;
|
|
|
|
/* set SIZE to get new item on add */
|
|
private int used = SIZE;
|
|
|
|
private short[] vertices;
|
|
|
|
private void getNext() {
|
|
if (cur == null) {
|
|
cur = pool.get();
|
|
push(cur);
|
|
} else {
|
|
if (cur.next != null)
|
|
throw new IllegalStateException("seeeked...");
|
|
|
|
cur.used = SIZE;
|
|
cur.next = pool.get();
|
|
cur = cur.next;
|
|
}
|
|
vertices = cur.vertices;
|
|
used = 0;
|
|
}
|
|
|
|
public void add(float a) {
|
|
add(toShort(a));
|
|
}
|
|
|
|
public void add(short a) {
|
|
if (used == SIZE)
|
|
getNext();
|
|
|
|
vertices[used++] = a;
|
|
}
|
|
|
|
public void add(float a, float b) {
|
|
add(toShort(a), toShort(b));
|
|
}
|
|
|
|
public void add(short a, short b) {
|
|
if (used == SIZE)
|
|
getNext();
|
|
|
|
vertices[used + 0] = a;
|
|
vertices[used + 1] = b;
|
|
used += 2;
|
|
}
|
|
|
|
public void add(float a, float b, float c) {
|
|
add(toShort(a), toShort(b), toShort(c));
|
|
}
|
|
|
|
public void add(short a, short b, short c) {
|
|
if (used == SIZE)
|
|
getNext();
|
|
|
|
vertices[used + 0] = a;
|
|
vertices[used + 1] = b;
|
|
vertices[used + 2] = c;
|
|
used += 3;
|
|
}
|
|
|
|
public void add(float a, float b, float c, float d) {
|
|
add(toShort(a), toShort(b), toShort(c), toShort(d));
|
|
}
|
|
|
|
public void add(short a, short b, short c, short d) {
|
|
if (used == SIZE)
|
|
getNext();
|
|
|
|
vertices[used + 0] = a;
|
|
vertices[used + 1] = b;
|
|
vertices[used + 2] = c;
|
|
vertices[used + 3] = d;
|
|
used += 4;
|
|
}
|
|
|
|
public void add(float a, float b, float c, float d, float e, float f) {
|
|
add(toShort(a), toShort(b), toShort(c), toShort(d), toShort(e), toShort(f));
|
|
}
|
|
|
|
public void add(short a, short b, short c, short d, short e, short f) {
|
|
if (used == SIZE)
|
|
getNext();
|
|
|
|
vertices[used + 0] = a;
|
|
vertices[used + 1] = b;
|
|
vertices[used + 2] = c;
|
|
vertices[used + 3] = d;
|
|
vertices[used + 4] = e;
|
|
vertices[used + 5] = f;
|
|
used += 6;
|
|
}
|
|
|
|
public boolean empty() {
|
|
return cur == null;
|
|
}
|
|
|
|
/**
|
|
* Direct access to the current chunk of VertexData. Use with care!
|
|
* <p/>
|
|
* When changing the position use releaseChunk to update internal state
|
|
*/
|
|
public Chunk obtainChunk() {
|
|
if (used == SIZE)
|
|
getNext();
|
|
|
|
cur.used = used;
|
|
|
|
return cur;
|
|
}
|
|
|
|
public void releaseChunk() {
|
|
used = cur.used;
|
|
}
|
|
|
|
public void releaseChunk(int size) {
|
|
cur.used = size;
|
|
used = size;
|
|
}
|
|
|
|
/**
|
|
* Do not use!
|
|
*/
|
|
public void seek(int offset) {
|
|
used += offset;
|
|
cur.used = used;
|
|
|
|
if (used > SIZE || used < 0)
|
|
throw new IllegalStateException("seeked too far: " + offset + "/" + used);
|
|
}
|
|
|
|
static final short toShort(float v) {
|
|
return (short) FastMath.clamp(v, Short.MIN_VALUE, Short.MAX_VALUE);
|
|
}
|
|
}
|