start of TextureAtlas
This commit is contained in:
parent
a1e9efbe5a
commit
47ad1d3617
212
src/org/oscim/renderer/TextureAtlas.java
Normal file
212
src/org/oscim/renderer/TextureAtlas.java
Normal file
@ -0,0 +1,212 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013 Hannes Janetzek
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// ported from:
|
||||||
|
/* ============================================================================
|
||||||
|
* Freetype GL - A C OpenGL Freetype engine
|
||||||
|
* Platform: Any
|
||||||
|
* WWW: http://code.google.com/p/freetype-gl/
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
* Copyright 2011,2012 Nicolas P. Rougier. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY NICOLAS P. ROUGIER ''AS IS'' AND ANY EXPRESS OR
|
||||||
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||||
|
* EVENT SHALL NICOLAS P. ROUGIER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||||
|
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* The views and conclusions contained in the software and documentation are
|
||||||
|
* those of the authors and should not be interpreted as representing official
|
||||||
|
* policies, either expressed or implied, of Nicolas P. Rougier.
|
||||||
|
* ============================================================================
|
||||||
|
*
|
||||||
|
* This source is based on the article by Jukka Jylanki :
|
||||||
|
* "A Thousand Ways to Pack the Bin - A Practical Approach to
|
||||||
|
* Two-Dimensional Rectangle Bin Packing", February 27, 2010.
|
||||||
|
*
|
||||||
|
* More precisely, this is an implementation of the Skyline Bottom-Left
|
||||||
|
* algorithm based on C++ sources provided by Jukka Jylanki at:
|
||||||
|
* http://clb.demon.fi/files/RectangleBinPack/
|
||||||
|
*
|
||||||
|
* ============================================================================
|
||||||
|
*/
|
||||||
|
package org.oscim.renderer;
|
||||||
|
|
||||||
|
import org.oscim.utils.pool.Inlist;
|
||||||
|
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
|
||||||
|
public class TextureAtlas {
|
||||||
|
/** Allocated slots */
|
||||||
|
Slot mSlots;
|
||||||
|
Rect mRects;
|
||||||
|
|
||||||
|
/** Width (in pixels) of the underlying texture */
|
||||||
|
final int mWidth;
|
||||||
|
|
||||||
|
/** Height (in pixels) of the underlying texture */
|
||||||
|
final int mHeight;
|
||||||
|
|
||||||
|
/** Depth (in bytes) of the underlying texture */
|
||||||
|
final int mDepth;
|
||||||
|
|
||||||
|
/** Allocated surface size */
|
||||||
|
int mUsed;
|
||||||
|
|
||||||
|
/** Texture identity (OpenGL) */
|
||||||
|
int mId;
|
||||||
|
|
||||||
|
/** Atlas data */
|
||||||
|
Bitmap mData;
|
||||||
|
|
||||||
|
class Slot extends Inlist<Slot> {
|
||||||
|
int x, y, w;
|
||||||
|
|
||||||
|
public Slot(int x, int y, int w) {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
this.w = w;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Rect extends Inlist<Rect> {
|
||||||
|
public int x, y, w, h;
|
||||||
|
}
|
||||||
|
|
||||||
|
private TextureAtlas(int width, int height, int depth) {
|
||||||
|
mWidth = width;
|
||||||
|
mHeight = height;
|
||||||
|
mDepth = depth;
|
||||||
|
mSlots = new Slot(1, 1, width - 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Rect getRegion(int width, int height) {
|
||||||
|
int y, bestHeight, bestWidth;
|
||||||
|
Slot slot, prev;
|
||||||
|
Rect r = new Rect();
|
||||||
|
r.w = width;
|
||||||
|
r.h = height;
|
||||||
|
|
||||||
|
bestHeight = Integer.MAX_VALUE;
|
||||||
|
bestWidth = Integer.MAX_VALUE;
|
||||||
|
|
||||||
|
Slot bestSlot = null;
|
||||||
|
|
||||||
|
for (slot = mSlots; slot != null; slot = slot.next) {
|
||||||
|
// fit width
|
||||||
|
if ((slot.x + width) > (mWidth - 1))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// fit height
|
||||||
|
y = slot.y;
|
||||||
|
int widthLeft = width;
|
||||||
|
|
||||||
|
Slot fit = slot;
|
||||||
|
while (widthLeft > 0) {
|
||||||
|
if (fit.y > y)
|
||||||
|
y = fit.y;
|
||||||
|
|
||||||
|
if ((y + height) > (mHeight - 1)) {
|
||||||
|
y = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
widthLeft -= fit.w;
|
||||||
|
|
||||||
|
fit = fit.next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (y < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int h = y + height;
|
||||||
|
if ((h < bestHeight) || ((h == bestHeight) && (slot.w < bestWidth))) {
|
||||||
|
bestHeight = h;
|
||||||
|
bestSlot = slot;
|
||||||
|
bestWidth = slot.w;
|
||||||
|
r.x = slot.x;
|
||||||
|
r.y = y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bestSlot == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
Slot curSlot = new Slot(r.x, r.y + height, width);
|
||||||
|
mSlots = Inlist.prependRelative(mSlots, curSlot, bestSlot);
|
||||||
|
|
||||||
|
for (prev = curSlot; prev.next != null;) {
|
||||||
|
slot = prev.next;
|
||||||
|
|
||||||
|
int shrink = (prev.x + prev.w) - slot.x;
|
||||||
|
|
||||||
|
if (shrink <= 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
slot.x += shrink;
|
||||||
|
slot.w -= shrink;
|
||||||
|
if (slot.w > 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// erease slot
|
||||||
|
prev.next = slot.next;
|
||||||
|
}
|
||||||
|
|
||||||
|
// merge
|
||||||
|
for (slot = mSlots; slot.next != null;) {
|
||||||
|
Slot next = slot.next;
|
||||||
|
|
||||||
|
if (slot.y == next.y) {
|
||||||
|
slot.w += next.w;
|
||||||
|
|
||||||
|
// erease 'next' slot
|
||||||
|
slot.next = next.next;
|
||||||
|
} else {
|
||||||
|
slot = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mUsed += width * height;
|
||||||
|
|
||||||
|
mRects = Inlist.push(mRects, r);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear() {
|
||||||
|
mRects = null;
|
||||||
|
mSlots = new Slot(1, 1, mWidth - 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TextureAtlas create(int width, int height, int depth) {
|
||||||
|
if (!(depth == 1 || depth == 3 || depth == 4))
|
||||||
|
throw new IllegalArgumentException("invalid depth");
|
||||||
|
|
||||||
|
return new TextureAtlas(width, height, depth);
|
||||||
|
}
|
||||||
|
}
|
||||||
86
src/org/oscim/renderer/overlays/AtlasTest.java
Normal file
86
src/org/oscim/renderer/overlays/AtlasTest.java
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
package org.oscim.renderer.overlays;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import org.oscim.core.MapPosition;
|
||||||
|
import org.oscim.graphics.Color;
|
||||||
|
import org.oscim.graphics.Paint.Cap;
|
||||||
|
import org.oscim.renderer.GLRenderer.Matrices;
|
||||||
|
import org.oscim.renderer.TextureAtlas;
|
||||||
|
import org.oscim.renderer.TextureAtlas.Rect;
|
||||||
|
import org.oscim.renderer.layer.LineLayer;
|
||||||
|
import org.oscim.theme.renderinstruction.Line;
|
||||||
|
import org.oscim.view.MapView;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
public class AtlasTest extends BasicOverlay {
|
||||||
|
|
||||||
|
public AtlasTest(MapView mapView) {
|
||||||
|
super(mapView);
|
||||||
|
|
||||||
|
TextureAtlas mAtlas = TextureAtlas.create(2048, 2048, 1);
|
||||||
|
|
||||||
|
LineLayer ll = layers.getLineLayer(0);
|
||||||
|
ll.line = new Line(Color.BLUE, 3, Cap.BUTT);
|
||||||
|
ll.width = 1.5f;
|
||||||
|
|
||||||
|
LineLayer ll2 = layers.getLineLayer(1);
|
||||||
|
ll2.line = new Line(Color.RED, 3, Cap.BUTT);
|
||||||
|
ll2.width = 1.5f;
|
||||||
|
|
||||||
|
float[] points = new float[10];
|
||||||
|
|
||||||
|
for (int i = 0; i < 400; i++) {
|
||||||
|
int w = (int) (20 + Math.random() * 256);
|
||||||
|
int h = (int) (20 + Math.random() * 56);
|
||||||
|
Rect r = mAtlas.getRegion(w, h);
|
||||||
|
if (r == null) {
|
||||||
|
Log.d("...", "no space left");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
points[0] = r.x;
|
||||||
|
points[1] = r.y;
|
||||||
|
points[2] = r.x + r.w;
|
||||||
|
points[3] = r.y;
|
||||||
|
points[4] = r.x + r.w;
|
||||||
|
points[5] = r.y + r.h;
|
||||||
|
points[6] = r.x;
|
||||||
|
points[7] = r.y + r.h;
|
||||||
|
points[8] = r.x;
|
||||||
|
points[9] = r.y;
|
||||||
|
ll.addLine(points, 10, false);
|
||||||
|
|
||||||
|
r.x += 2;
|
||||||
|
r.y += 2;
|
||||||
|
points[0] = r.x;
|
||||||
|
points[1] = r.y;
|
||||||
|
points[2] = r.x + w;
|
||||||
|
points[3] = r.y;
|
||||||
|
points[4] = r.x + w;
|
||||||
|
points[5] = r.y + h;
|
||||||
|
points[6] = r.x;
|
||||||
|
points[7] = r.y + h;
|
||||||
|
points[8] = r.x;
|
||||||
|
points[9] = r.y;
|
||||||
|
|
||||||
|
Log.d("...", "add region: " + Arrays.toString(points));
|
||||||
|
|
||||||
|
ll2.addLine(points, 10, false);
|
||||||
|
|
||||||
|
}
|
||||||
|
this.newData = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean initial = true;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update(MapPosition pos, boolean positionChanged,
|
||||||
|
boolean tilesChanged, Matrices m) {
|
||||||
|
|
||||||
|
if (initial) {
|
||||||
|
mMapPosition.copy(pos);
|
||||||
|
initial = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user