- started to move Matrices to MapViewPosition as these can be shared with
MapRenderer(TileLoader) and GLRenderer. - using inverse projection to determine visible tiles and mapping screen-coordinates to model - making MapPosition not final, reuse instance to get Position in Map-/GLRender added: ScanBox scanline fill used for calculating visible tiles rename: - ShortPool -> VertexPool - tile.isActive -> isLocked
This commit is contained in:
parent
8ec405cf5c
commit
c5e3be9d2b
@ -15,7 +15,7 @@
|
|||||||
package org.oscim.app;
|
package org.oscim.app;
|
||||||
|
|
||||||
import org.oscim.core.GeoPoint;
|
import org.oscim.core.GeoPoint;
|
||||||
import org.oscim.core.MapPosition;
|
import org.oscim.view.MapPosition;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.location.Criteria;
|
import android.location.Criteria;
|
||||||
|
@ -9,12 +9,12 @@ import org.oscim.app.filefilter.ValidRenderTheme;
|
|||||||
import org.oscim.app.filepicker.FilePicker;
|
import org.oscim.app.filepicker.FilePicker;
|
||||||
import org.oscim.app.preferences.EditPreferences;
|
import org.oscim.app.preferences.EditPreferences;
|
||||||
import org.oscim.core.GeoPoint;
|
import org.oscim.core.GeoPoint;
|
||||||
import org.oscim.core.MapPosition;
|
|
||||||
import org.oscim.database.MapDatabases;
|
import org.oscim.database.MapDatabases;
|
||||||
import org.oscim.theme.InternalRenderTheme;
|
import org.oscim.theme.InternalRenderTheme;
|
||||||
import org.oscim.utils.AndroidUtils;
|
import org.oscim.utils.AndroidUtils;
|
||||||
import org.oscim.view.DebugSettings;
|
import org.oscim.view.DebugSettings;
|
||||||
import org.oscim.view.MapActivity;
|
import org.oscim.view.MapActivity;
|
||||||
|
import org.oscim.view.MapPosition;
|
||||||
import org.oscim.view.MapView;
|
import org.oscim.view.MapView;
|
||||||
|
|
||||||
import android.annotation.TargetApi;
|
import android.annotation.TargetApi;
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.oscim.core;
|
package org.oscim.core;
|
||||||
|
|
||||||
|
import org.oscim.view.MapPosition;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An implementation of the spherical Mercator projection.
|
* An implementation of the spherical Mercator projection.
|
||||||
*/
|
*/
|
||||||
|
@ -17,6 +17,9 @@ package org.oscim.core;
|
|||||||
/**
|
/**
|
||||||
* A tag represents an immutable key-value pair.
|
* A tag represents an immutable key-value pair.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// TODO: use own stringshare method instead of internalized strings
|
||||||
|
|
||||||
public class Tag {
|
public class Tag {
|
||||||
private static final char KEY_VALUE_SEPARATOR = '=';
|
private static final char KEY_VALUE_SEPARATOR = '=';
|
||||||
/**
|
/**
|
||||||
|
@ -65,8 +65,8 @@ public class MapDatabase implements IMapDatabase {
|
|||||||
private static final String CACHE_FILE = "%d-%d-%d.tile";
|
private static final String CACHE_FILE = "%d-%d-%d.tile";
|
||||||
|
|
||||||
private static final String SERVER_ADDR = "city.informatik.uni-bremen.de";
|
private static final String SERVER_ADDR = "city.informatik.uni-bremen.de";
|
||||||
// private static final String URL = "/osci/map-live/";
|
private static final String URL = "/osci/map-live/";
|
||||||
private static final String URL = "/osci/oscim/";
|
// private static final String URL = "/osci/oscim/";
|
||||||
|
|
||||||
private final static float REF_TILE_SIZE = 4096.0f;
|
private final static float REF_TILE_SIZE = 4096.0f;
|
||||||
|
|
||||||
|
@ -1,17 +1,3 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010, 2011, 2012 mapsforge.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.utils;
|
package org.oscim.utils;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -53,17 +39,21 @@ import android.view.SurfaceHolder;
|
|||||||
import android.view.SurfaceView;
|
import android.view.SurfaceView;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An implementation of SurfaceView that uses the dedicated surface for displaying OpenGL rendering.
|
* An implementation of SurfaceView that uses the dedicated surface for
|
||||||
|
* displaying OpenGL rendering.
|
||||||
* <p>
|
* <p>
|
||||||
* A GLSurfaceView provides the following features:
|
* A GLSurfaceView provides the following features:
|
||||||
* <p>
|
* <p>
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>Manages a surface, which is a special piece of memory that can be composited into the Android view system.
|
* <li>Manages a surface, which is a special piece of memory that can be
|
||||||
|
* composited into the Android view system.
|
||||||
* <li>Manages an EGL display, which enables OpenGL to render into a surface.
|
* <li>Manages an EGL display, which enables OpenGL to render into a surface.
|
||||||
* <li>Accepts a user-provided Renderer object that does the actual rendering.
|
* <li>Accepts a user-provided Renderer object that does the actual rendering.
|
||||||
* <li>Renders on a dedicated thread to decouple rendering performance from the UI thread.
|
* <li>Renders on a dedicated thread to decouple rendering performance from the
|
||||||
|
* UI thread.
|
||||||
* <li>Supports both on-demand and continuous rendering.
|
* <li>Supports both on-demand and continuous rendering.
|
||||||
* <li>Optionally wraps, traces, and/or error-checks the renderer's OpenGL calls.
|
* <li>Optionally wraps, traces, and/or error-checks the renderer's OpenGL
|
||||||
|
* calls.
|
||||||
* </ul>
|
* </ul>
|
||||||
* <div class="special reference">
|
* <div class="special reference">
|
||||||
* <h3>Developer Guides</h3>
|
* <h3>Developer Guides</h3>
|
||||||
@ -73,15 +63,18 @@ import android.view.SurfaceView;
|
|||||||
* </p>
|
* </p>
|
||||||
* </div> <h3>Using GLSurfaceView</h3>
|
* </div> <h3>Using GLSurfaceView</h3>
|
||||||
* <p>
|
* <p>
|
||||||
* Typically you use GLSurfaceView by subclassing it and overriding one or more of the View system input event methods.
|
* Typically you use GLSurfaceView by subclassing it and overriding one or more
|
||||||
* If your application does not need to override event methods then GLSurfaceView can be used as-is. For the most part
|
* of the View system input event methods. If your application does not need to
|
||||||
* GLSurfaceView behavior is customized by calling "set" methods rather than by subclassing. For example, unlike a
|
* override event methods then GLSurfaceView can be used as-is. For the most
|
||||||
* regular View, drawing is delegated to a separate Renderer object which is registered with the GLSurfaceView using the
|
* part GLSurfaceView behavior is customized by calling "set" methods rather
|
||||||
* {@link #setRenderer(Renderer)} call.
|
* than by subclassing. For example, unlike a regular View, drawing is delegated
|
||||||
|
* to a separate Renderer object which is registered with the GLSurfaceView
|
||||||
|
* using the {@link #setRenderer(Renderer)} call.
|
||||||
* <p>
|
* <p>
|
||||||
* <h3>Initializing GLSurfaceView</h3> All you have to do to initialize a GLSurfaceView is call
|
* <h3>Initializing GLSurfaceView</h3> All you have to do to initialize a
|
||||||
* {@link #setRenderer(Renderer)}. However, if desired, you can modify the default behavior of GLSurfaceView by calling
|
* GLSurfaceView is call {@link #setRenderer(Renderer)}. However, if desired,
|
||||||
* one or more of these methods before calling setRenderer:
|
* you can modify the default behavior of GLSurfaceView by calling one or more
|
||||||
|
* of these methods before calling setRenderer:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>{@link #setDebugFlags(int)}
|
* <li>{@link #setDebugFlags(int)}
|
||||||
* <li>{@link #setEGLConfigChooser(boolean)}
|
* <li>{@link #setEGLConfigChooser(boolean)}
|
||||||
@ -90,43 +83,54 @@ import android.view.SurfaceView;
|
|||||||
* <li>{@link #setGLWrapper(GLWrapper)}
|
* <li>{@link #setGLWrapper(GLWrapper)}
|
||||||
* </ul>
|
* </ul>
|
||||||
* <p>
|
* <p>
|
||||||
* <h4>Specifying the android.view.Surface</h4> By default GLSurfaceView will create a PixelFormat.RGB_565 format
|
* <h4>Specifying the android.view.Surface</h4> By default GLSurfaceView will
|
||||||
* surface. If a translucent surface is required, call getHolder().setFormat(PixelFormat.TRANSLUCENT). The exact format
|
* create a PixelFormat.RGB_565 format surface. If a translucent surface is
|
||||||
* of a TRANSLUCENT surface is device dependent, but it will be a 32-bit-per-pixel surface with 8 bits per component.
|
* required, call getHolder().setFormat(PixelFormat.TRANSLUCENT). The exact
|
||||||
|
* format of a TRANSLUCENT surface is device dependent, but it will be a
|
||||||
|
* 32-bit-per-pixel surface with 8 bits per component.
|
||||||
* <p>
|
* <p>
|
||||||
* <h4>Choosing an EGL Configuration</h4> A given Android device may support multiple EGLConfig rendering
|
* <h4>Choosing an EGL Configuration</h4> A given Android device may support
|
||||||
* configurations. The available configurations may differ in how may channels of data are present, as well as how many
|
* multiple EGLConfig rendering configurations. The available configurations may
|
||||||
* bits are allocated to each channel. Therefore, the first thing GLSurfaceView has to do when starting to render is
|
* differ in how may channels of data are present, as well as how many bits are
|
||||||
* choose what EGLConfig to use.
|
* allocated to each channel. Therefore, the first thing GLSurfaceView has to do
|
||||||
|
* when starting to render is choose what EGLConfig to use.
|
||||||
* <p>
|
* <p>
|
||||||
* By default GLSurfaceView chooses a EGLConfig that has an RGB_565 pixel format, with at least a 16-bit depth buffer
|
* By default GLSurfaceView chooses a EGLConfig that has an RGB_565 pixel
|
||||||
* and no stencil.
|
* format, with at least a 16-bit depth buffer and no stencil.
|
||||||
* <p>
|
* <p>
|
||||||
* If you would prefer a different EGLConfig you can override the default behavior by calling one of the
|
* If you would prefer a different EGLConfig you can override the default
|
||||||
* setEGLConfigChooser methods.
|
* behavior by calling one of the setEGLConfigChooser methods.
|
||||||
* <p>
|
* <p>
|
||||||
* <h4>Debug Behavior</h4> You can optionally modify the behavior of GLSurfaceView by calling one or more of the
|
* <h4>Debug Behavior</h4> You can optionally modify the behavior of
|
||||||
* debugging methods {@link #setDebugFlags(int)}, and {@link #setGLWrapper}. These methods may be called before and/or
|
* GLSurfaceView by calling one or more of the debugging methods
|
||||||
* after setRenderer, but typically they are called before setRenderer so that they take effect immediately.
|
* {@link #setDebugFlags(int)}, and {@link #setGLWrapper}. These methods may be
|
||||||
|
* called before and/or after setRenderer, but typically they are called before
|
||||||
|
* setRenderer so that they take effect immediately.
|
||||||
* <p>
|
* <p>
|
||||||
* <h4>Setting a Renderer</h4> Finally, you must call {@link #setRenderer} to register a {@link Renderer}. The renderer
|
* <h4>Setting a Renderer</h4> Finally, you must call {@link #setRenderer} to
|
||||||
* is responsible for doing the actual OpenGL rendering.
|
* register a {@link Renderer}. The renderer is responsible for doing the actual
|
||||||
|
* OpenGL rendering.
|
||||||
* <p>
|
* <p>
|
||||||
* <h3>Rendering Mode</h3> Once the renderer is set, you can control whether the renderer draws continuously or
|
* <h3>Rendering Mode</h3> Once the renderer is set, you can control whether the
|
||||||
* on-demand by calling {@link #setRenderMode}. The default is continuous rendering.
|
* renderer draws continuously or on-demand by calling {@link #setRenderMode}.
|
||||||
|
* The default is continuous rendering.
|
||||||
* <p>
|
* <p>
|
||||||
* <h3>Activity Life-cycle</h3> A GLSurfaceView must be notified when the activity is paused and resumed. GLSurfaceView
|
* <h3>Activity Life-cycle</h3> A GLSurfaceView must be notified when the
|
||||||
* clients are required to call {@link #onPause()} when the activity pauses and {@link #onResume()} when the activity
|
* activity is paused and resumed. GLSurfaceView clients are required to call
|
||||||
* resumes. These calls allow GLSurfaceView to pause and resume the rendering thread, and also allow GLSurfaceView to
|
* {@link #onPause()} when the activity pauses and {@link #onResume()} when the
|
||||||
* release and recreate the OpenGL display.
|
* activity resumes. These calls allow GLSurfaceView to pause and resume the
|
||||||
|
* rendering thread, and also allow GLSurfaceView to release and recreate the
|
||||||
|
* OpenGL display.
|
||||||
* <p>
|
* <p>
|
||||||
* <h3>Handling events</h3>
|
* <h3>Handling events</h3>
|
||||||
* <p>
|
* <p>
|
||||||
* To handle an event you will typically subclass GLSurfaceView and override the appropriate method, just as you would
|
* To handle an event you will typically subclass GLSurfaceView and override the
|
||||||
* with any other View. However, when handling the event, you may need to communicate with the Renderer object that's
|
* appropriate method, just as you would with any other View. However, when
|
||||||
* running in the rendering thread. You can do this using any standard Java cross-thread communication mechanism. In
|
* handling the event, you may need to communicate with the Renderer object
|
||||||
* addition, one relatively easy way to communicate with your renderer is to call {@link #queueEvent(Runnable)}. For
|
* that's running in the rendering thread. You can do this using any standard
|
||||||
* example:
|
* Java cross-thread communication mechanism. In addition, one relatively easy
|
||||||
|
* way to communicate with your renderer is to call
|
||||||
|
* {@link #queueEvent(Runnable)}. For example:
|
||||||
*
|
*
|
||||||
* <pre class="prettyprint">
|
* <pre class="prettyprint">
|
||||||
* class MyGLSurfaceView extends GLSurfaceView {
|
* class MyGLSurfaceView extends GLSurfaceView {
|
||||||
@ -154,9 +158,6 @@ import android.view.SurfaceView;
|
|||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* </pre>
|
* </pre>
|
||||||
*/
|
*/
|
||||||
public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
|
public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
|
||||||
@ -169,7 +170,8 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
|||||||
private final static boolean LOG_RENDERER_DRAW_FRAME = false;
|
private final static boolean LOG_RENDERER_DRAW_FRAME = false;
|
||||||
private final static boolean LOG_EGL = false;
|
private final static boolean LOG_EGL = false;
|
||||||
/**
|
/**
|
||||||
* The renderer only renders when the surface is created, or when {@link #requestRender} is called.
|
* The renderer only renders when the surface is created, or when
|
||||||
|
* {@link #requestRender} is called.
|
||||||
*
|
*
|
||||||
* @see #getRenderMode()
|
* @see #getRenderMode()
|
||||||
* @see #setRenderMode(int)
|
* @see #setRenderMode(int)
|
||||||
@ -185,8 +187,9 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
|||||||
public final static int RENDERMODE_CONTINUOUSLY = 1;
|
public final static int RENDERMODE_CONTINUOUSLY = 1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check glError() after every GL call and throw an exception if glError indicates that an error has occurred. This
|
* Check glError() after every GL call and throw an exception if glError
|
||||||
* can be used to help track down which OpenGL ES call is causing an error.
|
* indicates that an error has occurred. This can be used to help track down
|
||||||
|
* which OpenGL ES call is causing an error.
|
||||||
*
|
*
|
||||||
* @see #getDebugFlags
|
* @see #getDebugFlags
|
||||||
* @see #setDebugFlags
|
* @see #setDebugFlags
|
||||||
@ -194,7 +197,8 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
|||||||
public final static int DEBUG_CHECK_GL_ERROR = 1;
|
public final static int DEBUG_CHECK_GL_ERROR = 1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Log GL calls to the system log at "verbose" level with tag "GLSurfaceView".
|
* Log GL calls to the system log at "verbose" level with tag
|
||||||
|
* "GLSurfaceView".
|
||||||
*
|
*
|
||||||
* @see #getDebugFlags
|
* @see #getDebugFlags
|
||||||
* @see #setDebugFlags
|
* @see #setDebugFlags
|
||||||
@ -202,8 +206,11 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
|||||||
public final static int DEBUG_LOG_GL_CALLS = 2;
|
public final static int DEBUG_LOG_GL_CALLS = 2;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Standard View constructor. In order to render something, you must call {@link #setRenderer} to register a
|
* Standard View constructor. In order to render something, you must call
|
||||||
* renderer.
|
* {@link #setRenderer} to register a renderer.
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* ...
|
||||||
*/
|
*/
|
||||||
public GLSurfaceView(Context context) {
|
public GLSurfaceView(Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
@ -211,8 +218,13 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Standard View constructor. In order to render something, you must call {@link #setRenderer} to register a
|
* Standard View constructor. In order to render something, you must call
|
||||||
* renderer.
|
* {@link #setRenderer} to register a renderer.
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* ....
|
||||||
|
* @param attrs
|
||||||
|
* ...
|
||||||
*/
|
*/
|
||||||
public GLSurfaceView(Context context, AttributeSet attrs) {
|
public GLSurfaceView(Context context, AttributeSet attrs) {
|
||||||
super(context, attrs);
|
super(context, attrs);
|
||||||
@ -247,9 +259,11 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the glWrapper. If the glWrapper is not null, its {@link GLWrapper#wrap(GL)} method is called whenever a
|
* Set the glWrapper. If the glWrapper is not null, its
|
||||||
* surface is created. A GLWrapper can be used to wrap the GL object that's passed to the renderer. Wrapping a GL
|
* {@link GLWrapper#wrap(GL)} method is called whenever a surface is
|
||||||
* object enables examining and modifying the behavior of the GL calls made by the renderer.
|
* created. A GLWrapper can be used to wrap the GL object that's passed to
|
||||||
|
* the renderer. Wrapping a GL object enables examining and modifying the
|
||||||
|
* behavior of the GL calls made by the renderer.
|
||||||
* <p>
|
* <p>
|
||||||
* Wrapping is typically used for debugging purposes.
|
* Wrapping is typically used for debugging purposes.
|
||||||
* <p>
|
* <p>
|
||||||
@ -263,8 +277,9 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the debug flags to a new value. The value is constructed by OR-together zero or more of the DEBUG_CHECK_*
|
* Set the debug flags to a new value. The value is constructed by
|
||||||
* constants. The debug flags take effect whenever a surface is created. The default value is zero.
|
* OR-together zero or more of the DEBUG_CHECK_* constants. The debug flags
|
||||||
|
* take effect whenever a surface is created. The default value is zero.
|
||||||
*
|
*
|
||||||
* @param debugFlags
|
* @param debugFlags
|
||||||
* the new debug flags
|
* the new debug flags
|
||||||
@ -285,15 +300,18 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Control whether the EGL context is preserved when the GLSurfaceView is paused and resumed.
|
* Control whether the EGL context is preserved when the GLSurfaceView is
|
||||||
|
* paused and resumed.
|
||||||
* <p>
|
* <p>
|
||||||
* If set to true, then the EGL context may be preserved when the GLSurfaceView is paused. Whether the EGL context
|
* If set to true, then the EGL context may be preserved when the
|
||||||
* is actually preserved or not depends upon whether the Android device that the program is running on can support
|
* GLSurfaceView is paused. Whether the EGL context is actually preserved or
|
||||||
* an arbitrary number of EGL contexts or not. Devices that can only support a limited number of EGL contexts must
|
* not depends upon whether the Android device that the program is running
|
||||||
* release the EGL context in order to allow multiple applications to share the GPU.
|
* on can support an arbitrary number of EGL contexts or not. Devices that
|
||||||
|
* can only support a limited number of EGL contexts must release the EGL
|
||||||
|
* context in order to allow multiple applications to share the GPU.
|
||||||
* <p>
|
* <p>
|
||||||
* If set to false, the EGL context will be released when the GLSurfaceView is paused, and recreated when the
|
* If set to false, the EGL context will be released when the GLSurfaceView
|
||||||
* GLSurfaceView is resumed.
|
* is paused, and recreated when the GLSurfaceView is resumed.
|
||||||
* <p>
|
* <p>
|
||||||
* The default is false.
|
* The default is false.
|
||||||
*
|
*
|
||||||
@ -312,19 +330,22 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the renderer associated with this view. Also starts the thread that will call the renderer, which in turn
|
* Set the renderer associated with this view. Also starts the thread that
|
||||||
* causes the rendering to start.
|
* will call the renderer, which in turn causes the rendering to start.
|
||||||
* <p>
|
* <p>
|
||||||
* This method should be called once and only once in the life-cycle of a GLSurfaceView.
|
* This method should be called once and only once in the life-cycle of a
|
||||||
|
* GLSurfaceView.
|
||||||
* <p>
|
* <p>
|
||||||
* The following GLSurfaceView methods can only be called <em>before</em> setRenderer is called:
|
* The following GLSurfaceView methods can only be called <em>before</em>
|
||||||
|
* setRenderer is called:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>{@link #setEGLConfigChooser(boolean)}
|
* <li>{@link #setEGLConfigChooser(boolean)}
|
||||||
* <li>{@link #setEGLConfigChooser(EGLConfigChooser)}
|
* <li>{@link #setEGLConfigChooser(EGLConfigChooser)}
|
||||||
* <li>{@link #setEGLConfigChooser(int, int, int, int, int, int)}
|
* <li>{@link #setEGLConfigChooser(int, int, int, int, int, int)}
|
||||||
* </ul>
|
* </ul>
|
||||||
* <p>
|
* <p>
|
||||||
* The following GLSurfaceView methods can only be called <em>after</em> setRenderer is called:
|
* The following GLSurfaceView methods can only be called <em>after</em>
|
||||||
|
* setRenderer is called:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>{@link #getRenderMode()}
|
* <li>{@link #getRenderMode()}
|
||||||
* <li>{@link #onPause()}
|
* <li>{@link #onPause()}
|
||||||
@ -356,10 +377,11 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
|||||||
/**
|
/**
|
||||||
* Install a custom EGLContextFactory.
|
* Install a custom EGLContextFactory.
|
||||||
* <p>
|
* <p>
|
||||||
* If this method is called, it must be called before {@link #setRenderer(Renderer)} is called.
|
* If this method is called, it must be called before
|
||||||
|
* {@link #setRenderer(Renderer)} is called.
|
||||||
* <p>
|
* <p>
|
||||||
* If this method is not called, then by default a context will be created with no shared context and with a null
|
* If this method is not called, then by default a context will be created
|
||||||
* attribute list.
|
* with no shared context and with a null attribute list.
|
||||||
*/
|
*/
|
||||||
public void setEGLContextFactory(EGLContextFactory factory) {
|
public void setEGLContextFactory(EGLContextFactory factory) {
|
||||||
checkRenderThreadState();
|
checkRenderThreadState();
|
||||||
@ -369,9 +391,11 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
|||||||
/**
|
/**
|
||||||
* Install a custom EGLWindowSurfaceFactory.
|
* Install a custom EGLWindowSurfaceFactory.
|
||||||
* <p>
|
* <p>
|
||||||
* If this method is called, it must be called before {@link #setRenderer(Renderer)} is called.
|
* If this method is called, it must be called before
|
||||||
|
* {@link #setRenderer(Renderer)} is called.
|
||||||
* <p>
|
* <p>
|
||||||
* If this method is not called, then by default a window surface will be created with a null attribute list.
|
* If this method is not called, then by default a window surface will be
|
||||||
|
* created with a null attribute list.
|
||||||
*/
|
*/
|
||||||
public void setEGLWindowSurfaceFactory(EGLWindowSurfaceFactory factory) {
|
public void setEGLWindowSurfaceFactory(EGLWindowSurfaceFactory factory) {
|
||||||
checkRenderThreadState();
|
checkRenderThreadState();
|
||||||
@ -381,10 +405,12 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
|||||||
/**
|
/**
|
||||||
* Install a custom EGLConfigChooser.
|
* Install a custom EGLConfigChooser.
|
||||||
* <p>
|
* <p>
|
||||||
* If this method is called, it must be called before {@link #setRenderer(Renderer)} is called.
|
* If this method is called, it must be called before
|
||||||
|
* {@link #setRenderer(Renderer)} is called.
|
||||||
* <p>
|
* <p>
|
||||||
* If no setEGLConfigChooser method is called, then by default the view will choose an EGLConfig that is compatible
|
* If no setEGLConfigChooser method is called, then by default the view will
|
||||||
* with the current android.view.Surface, with a depth buffer depth of at least 16 bits.
|
* choose an EGLConfig that is compatible with the current
|
||||||
|
* android.view.Surface, with a depth buffer depth of at least 16 bits.
|
||||||
*
|
*
|
||||||
* @param configChooser
|
* @param configChooser
|
||||||
*/
|
*/
|
||||||
@ -394,13 +420,15 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Install a config chooser which will choose a config as close to 16-bit RGB as possible, with or without an
|
* Install a config chooser which will choose a config as close to 16-bit
|
||||||
* optional depth buffer as close to 16-bits as possible.
|
* RGB as possible, with or without an optional depth buffer as close to
|
||||||
|
* 16-bits as possible.
|
||||||
* <p>
|
* <p>
|
||||||
* If this method is called, it must be called before {@link #setRenderer(Renderer)} is called.
|
* If this method is called, it must be called before
|
||||||
|
* {@link #setRenderer(Renderer)} is called.
|
||||||
* <p>
|
* <p>
|
||||||
* If no setEGLConfigChooser method is called, then by default the view will choose an RGB_565 surface with a depth
|
* If no setEGLConfigChooser method is called, then by default the view will
|
||||||
* buffer depth of at least 16 bits.
|
* choose an RGB_565 surface with a depth buffer depth of at least 16 bits.
|
||||||
*
|
*
|
||||||
* @param needDepth
|
* @param needDepth
|
||||||
*/
|
*/
|
||||||
@ -409,13 +437,15 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Install a config chooser which will choose a config with at least the specified depthSize and stencilSize, and
|
* Install a config chooser which will choose a config with at least the
|
||||||
* exactly the specified redSize, greenSize, blueSize and alphaSize.
|
* specified depthSize and stencilSize, and exactly the specified redSize,
|
||||||
|
* greenSize, blueSize and alphaSize.
|
||||||
* <p>
|
* <p>
|
||||||
* If this method is called, it must be called before {@link #setRenderer(Renderer)} is called.
|
* If this method is called, it must be called before
|
||||||
|
* {@link #setRenderer(Renderer)} is called.
|
||||||
* <p>
|
* <p>
|
||||||
* If no setEGLConfigChooser method is called, then by default the view will choose an RGB_565 surface with a depth
|
* If no setEGLConfigChooser method is called, then by default the view will
|
||||||
* buffer depth of at least 16 bits.
|
* choose an RGB_565 surface with a depth buffer depth of at least 16 bits.
|
||||||
*/
|
*/
|
||||||
public void setEGLConfigChooser(int redSize, int greenSize, int blueSize,
|
public void setEGLConfigChooser(int redSize, int greenSize, int blueSize,
|
||||||
int alphaSize, int depthSize, int stencilSize) {
|
int alphaSize, int depthSize, int stencilSize) {
|
||||||
@ -424,7 +454,8 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inform the default EGLContextFactory and default EGLConfigChooser which EGLContext client version to pick.
|
* Inform the default EGLContextFactory and default EGLConfigChooser which
|
||||||
|
* EGLContext client version to pick.
|
||||||
* <p>
|
* <p>
|
||||||
* Use this method to create an OpenGL ES 2.0-compatible context. Example:
|
* Use this method to create an OpenGL ES 2.0-compatible context. Example:
|
||||||
*
|
*
|
||||||
@ -436,19 +467,24 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
|||||||
* }
|
* }
|
||||||
* </pre>
|
* </pre>
|
||||||
* <p>
|
* <p>
|
||||||
* Note: Activities which require OpenGL ES 2.0 should indicate this by setting @lt;uses-feature
|
* Note: Activities which require OpenGL ES 2.0 should indicate this by
|
||||||
* android:glEsVersion="0x00020000" /> in the activity's AndroidManifest.xml file.
|
* setting @lt;uses-feature android:glEsVersion="0x00020000" /> in the
|
||||||
|
* activity's AndroidManifest.xml file.
|
||||||
* <p>
|
* <p>
|
||||||
* If this method is called, it must be called before {@link #setRenderer(Renderer)} is called.
|
* If this method is called, it must be called before
|
||||||
|
* {@link #setRenderer(Renderer)} is called.
|
||||||
* <p>
|
* <p>
|
||||||
* This method only affects the behavior of the default EGLContexFactory and the default EGLConfigChooser. If
|
* This method only affects the behavior of the default EGLContexFactory and
|
||||||
* {@link #setEGLContextFactory(EGLContextFactory)} has been called, then the supplied EGLContextFactory is
|
* the default EGLConfigChooser. If
|
||||||
* responsible for creating an OpenGL ES 2.0-compatible context. If {@link #setEGLConfigChooser(EGLConfigChooser)}
|
* {@link #setEGLContextFactory(EGLContextFactory)} has been called, then
|
||||||
* has been called, then the supplied EGLConfigChooser is responsible for choosing an OpenGL ES 2.0-compatible
|
* the supplied EGLContextFactory is responsible for creating an OpenGL ES
|
||||||
* config.
|
* 2.0-compatible context. If {@link #setEGLConfigChooser(EGLConfigChooser)}
|
||||||
|
* has been called, then the supplied EGLConfigChooser is responsible for
|
||||||
|
* choosing an OpenGL ES 2.0-compatible config.
|
||||||
*
|
*
|
||||||
* @param version
|
* @param version
|
||||||
* The EGLContext client version to choose. Use 2 for OpenGL ES 2.0
|
* The EGLContext client version to choose. Use 2 for OpenGL ES
|
||||||
|
* 2.0
|
||||||
*/
|
*/
|
||||||
public void setEGLContextClientVersion(int version) {
|
public void setEGLContextClientVersion(int version) {
|
||||||
checkRenderThreadState();
|
checkRenderThreadState();
|
||||||
@ -456,12 +492,15 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the rendering mode. When renderMode is RENDERMODE_CONTINUOUSLY, the renderer is called repeatedly to
|
* Set the rendering mode. When renderMode is RENDERMODE_CONTINUOUSLY, the
|
||||||
* re-render the scene. When renderMode is RENDERMODE_WHEN_DIRTY, the renderer only rendered when the surface is
|
* renderer is called repeatedly to re-render the scene. When renderMode is
|
||||||
* created, or when {@link #requestRender} is called. Defaults to RENDERMODE_CONTINUOUSLY.
|
* RENDERMODE_WHEN_DIRTY, the renderer only rendered when the surface is
|
||||||
|
* created, or when {@link #requestRender} is called. Defaults to
|
||||||
|
* RENDERMODE_CONTINUOUSLY.
|
||||||
* <p>
|
* <p>
|
||||||
* Using RENDERMODE_WHEN_DIRTY can improve battery life and overall system performance by allowing the GPU and CPU
|
* Using RENDERMODE_WHEN_DIRTY can improve battery life and overall system
|
||||||
* to idle when the view does not need to be updated.
|
* performance by allowing the GPU and CPU to idle when the view does not
|
||||||
|
* need to be updated.
|
||||||
* <p>
|
* <p>
|
||||||
* This method can only be called after {@link #setRenderer(Renderer)}
|
* This method can only be called after {@link #setRenderer(Renderer)}
|
||||||
*
|
*
|
||||||
@ -475,7 +514,8 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the current rendering mode. May be called from any thread. Must not be called before a renderer has been set.
|
* Get the current rendering mode. May be called from any thread. Must not
|
||||||
|
* be called before a renderer has been set.
|
||||||
*
|
*
|
||||||
* @return the current rendering mode.
|
* @return the current rendering mode.
|
||||||
* @see #RENDERMODE_CONTINUOUSLY
|
* @see #RENDERMODE_CONTINUOUSLY
|
||||||
@ -486,25 +526,26 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request that the renderer render a frame. This method is typically used when the render mode has been set to
|
* Request that the renderer render a frame. This method is typically used
|
||||||
* {@link #RENDERMODE_WHEN_DIRTY}, so that frames are only rendered on demand. May be called from any thread. Must
|
* when the render mode has been set to {@link #RENDERMODE_WHEN_DIRTY}, so
|
||||||
* not be called before a renderer has been set.
|
* that frames are only rendered on demand. May be called from any thread.
|
||||||
|
* Must not be called before a renderer has been set.
|
||||||
*/
|
*/
|
||||||
public void requestRender() {
|
public void requestRender() {
|
||||||
mGLThread.requestRender();
|
mGLThread.requestRender();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is part of the SurfaceHolder.Callback interface, and is not normally called or subclassed by clients
|
* This method is part of the SurfaceHolder.Callback interface, and is not
|
||||||
* of GLSurfaceView.
|
* normally called or subclassed by clients of GLSurfaceView.
|
||||||
*/
|
*/
|
||||||
public void surfaceCreated(SurfaceHolder holder) {
|
public void surfaceCreated(SurfaceHolder holder) {
|
||||||
mGLThread.surfaceCreated();
|
mGLThread.surfaceCreated();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is part of the SurfaceHolder.Callback interface, and is not normally called or subclassed by clients
|
* This method is part of the SurfaceHolder.Callback interface, and is not
|
||||||
* of GLSurfaceView.
|
* normally called or subclassed by clients of GLSurfaceView.
|
||||||
*/
|
*/
|
||||||
public void surfaceDestroyed(SurfaceHolder holder) {
|
public void surfaceDestroyed(SurfaceHolder holder) {
|
||||||
// Surface will be destroyed when we return
|
// Surface will be destroyed when we return
|
||||||
@ -512,33 +553,37 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is part of the SurfaceHolder.Callback interface, and is not normally called or subclassed by clients
|
* This method is part of the SurfaceHolder.Callback interface, and is not
|
||||||
* of GLSurfaceView.
|
* normally called or subclassed by clients of GLSurfaceView.
|
||||||
*/
|
*/
|
||||||
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
|
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
|
||||||
mGLThread.onWindowResize(w, h);
|
mGLThread.onWindowResize(w, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inform the view that the activity is paused. The owner of this view must call this method when the activity is
|
* Inform the view that the activity is paused. The owner of this view must
|
||||||
* paused. Calling this method will pause the rendering thread. Must not be called before a renderer has been set.
|
* call this method when the activity is paused. Calling this method will
|
||||||
|
* pause the rendering thread. Must not be called before a renderer has been
|
||||||
|
* set.
|
||||||
*/
|
*/
|
||||||
public void onPause() {
|
public void onPause() {
|
||||||
mGLThread.onPause();
|
mGLThread.onPause();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inform the view that the activity is resumed. The owner of this view must call this method when the activity is
|
* Inform the view that the activity is resumed. The owner of this view must
|
||||||
* resumed. Calling this method will recreate the OpenGL display and resume the rendering thread. Must not be called
|
* call this method when the activity is resumed. Calling this method will
|
||||||
* before a renderer has been set.
|
* recreate the OpenGL display and resume the rendering thread. Must not be
|
||||||
|
* called before a renderer has been set.
|
||||||
*/
|
*/
|
||||||
public void onResume() {
|
public void onResume() {
|
||||||
mGLThread.onResume();
|
mGLThread.onResume();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Queue a runnable to be run on the GL rendering thread. This can be used to communicate with the Renderer on the
|
* Queue a runnable to be run on the GL rendering thread. This can be used
|
||||||
* rendering thread. Must not be called before a renderer has been set.
|
* to communicate with the Renderer on the rendering thread. Must not be
|
||||||
|
* called before a renderer has been set.
|
||||||
*
|
*
|
||||||
* @param r
|
* @param r
|
||||||
* the runnable to be run on the GL rendering thread.
|
* the runnable to be run on the GL rendering thread.
|
||||||
@ -548,8 +593,8 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is used as part of the View class and is not normally called or subclassed by clients of
|
* This method is used as part of the View class and is not normally called
|
||||||
* GLSurfaceView.
|
* or subclassed by clients of GLSurfaceView.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void onAttachedToWindow() {
|
protected void onAttachedToWindow() {
|
||||||
@ -572,8 +617,9 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is used as part of the View class and is not normally called or subclassed by clients of
|
* This method is used as part of the View class and is not normally called
|
||||||
* GLSurfaceView. Must not be called before a renderer has been set.
|
* or subclassed by clients of GLSurfaceView. Must not be called before a
|
||||||
|
* renderer has been set.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void onDetachedFromWindow() {
|
protected void onDetachedFromWindow() {
|
||||||
@ -592,10 +638,12 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
|||||||
/**
|
/**
|
||||||
* An interface used to wrap a GL interface.
|
* An interface used to wrap a GL interface.
|
||||||
* <p>
|
* <p>
|
||||||
* Typically used for implementing debugging and tracing on top of the default GL interface. You would typically use
|
* Typically used for implementing debugging and tracing on top of the
|
||||||
* this by creating your own class that implemented all the GL methods by delegating to another GL instance. Then
|
* default GL interface. You would typically use this by creating your own
|
||||||
* you could add your own behavior before or after calling the delegate. All the GLWrapper would do was instantiate
|
* class that implemented all the GL methods by delegating to another GL
|
||||||
* and return the wrapper GL instance:
|
* instance. Then you could add your own behavior before or after calling
|
||||||
|
* the delegate. All the GLWrapper would do was instantiate and return the
|
||||||
|
* wrapper GL instance:
|
||||||
*
|
*
|
||||||
* <pre class="prettyprint">
|
* <pre class="prettyprint">
|
||||||
* class MyGLWrapper implements GLWrapper {
|
* class MyGLWrapper implements GLWrapper {
|
||||||
@ -616,13 +664,15 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
|||||||
*
|
*
|
||||||
* @param gl
|
* @param gl
|
||||||
* a GL interface that is to be wrapped.
|
* a GL interface that is to be wrapped.
|
||||||
* @return either the input argument or another GL object that wraps the input argument.
|
* @return either the input argument or another GL object that wraps the
|
||||||
|
* input argument.
|
||||||
*/
|
*/
|
||||||
GL wrap(GL gl);
|
GL wrap(GL gl);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An interface for customizing the eglCreateContext and eglDestroyContext calls.
|
* An interface for customizing the eglCreateContext and eglDestroyContext
|
||||||
|
* calls.
|
||||||
* <p>
|
* <p>
|
||||||
* This interface must be implemented by clients wishing to call
|
* This interface must be implemented by clients wishing to call
|
||||||
* {@link GLSurfaceView#setEGLContextFactory(EGLContextFactory)}
|
* {@link GLSurfaceView#setEGLContextFactory(EGLContextFactory)}
|
||||||
@ -633,9 +683,10 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
|||||||
void destroyContext(EGL10 egl, EGLDisplay display, EGLContext context);
|
void destroyContext(EGL10 egl, EGLDisplay display, EGLContext context);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class DefaultContextFactory implements EGLContextFactory {
|
private final class DefaultContextFactory implements EGLContextFactory {
|
||||||
private int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
|
private int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
|
||||||
|
|
||||||
|
@Override
|
||||||
public EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig config) {
|
public EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig config) {
|
||||||
int[] attrib_list = { EGL_CONTEXT_CLIENT_VERSION, mEGLContextClientVersion,
|
int[] attrib_list = { EGL_CONTEXT_CLIENT_VERSION, mEGLContextClientVersion,
|
||||||
EGL10.EGL_NONE };
|
EGL10.EGL_NONE };
|
||||||
@ -644,6 +695,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
|||||||
mEGLContextClientVersion != 0 ? attrib_list : null);
|
mEGLContextClientVersion != 0 ? attrib_list : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void destroyContext(EGL10 egl, EGLDisplay display,
|
public void destroyContext(EGL10 egl, EGLDisplay display,
|
||||||
EGLContext context) {
|
EGLContext context) {
|
||||||
if (!egl.eglDestroyContext(display, context)) {
|
if (!egl.eglDestroyContext(display, context)) {
|
||||||
@ -659,13 +711,22 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An interface for customizing the eglCreateWindowSurface and eglDestroySurface calls.
|
* An interface for customizing the eglCreateWindowSurface and
|
||||||
|
* eglDestroySurface calls.
|
||||||
* <p>
|
* <p>
|
||||||
* This interface must be implemented by clients wishing to call
|
* This interface must be implemented by clients wishing to call
|
||||||
* {@link GLSurfaceView#setEGLWindowSurfaceFactory(EGLWindowSurfaceFactory)}
|
* {@link GLSurfaceView#setEGLWindowSurfaceFactory(EGLWindowSurfaceFactory)}
|
||||||
*/
|
*/
|
||||||
public interface EGLWindowSurfaceFactory {
|
public interface EGLWindowSurfaceFactory {
|
||||||
/**
|
/**
|
||||||
|
* @param egl
|
||||||
|
* ...
|
||||||
|
* @param display
|
||||||
|
* ...
|
||||||
|
* @param config
|
||||||
|
* ...
|
||||||
|
* @param nativeWindow
|
||||||
|
* ...
|
||||||
* @return null if the surface cannot be constructed.
|
* @return null if the surface cannot be constructed.
|
||||||
*/
|
*/
|
||||||
EGLSurface createWindowSurface(EGL10 egl, EGLDisplay display, EGLConfig config,
|
EGLSurface createWindowSurface(EGL10 egl, EGLDisplay display, EGLConfig config,
|
||||||
@ -676,6 +737,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
|||||||
|
|
||||||
private static class DefaultWindowSurfaceFactory implements EGLWindowSurfaceFactory {
|
private static class DefaultWindowSurfaceFactory implements EGLWindowSurfaceFactory {
|
||||||
|
|
||||||
|
@Override
|
||||||
public EGLSurface createWindowSurface(EGL10 egl, EGLDisplay display,
|
public EGLSurface createWindowSurface(EGL10 egl, EGLDisplay display,
|
||||||
EGLConfig config, Object nativeWindow) {
|
EGLConfig config, Object nativeWindow) {
|
||||||
EGLSurface result = null;
|
EGLSurface result = null;
|
||||||
@ -683,7 +745,8 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
|||||||
result = egl.eglCreateWindowSurface(display, config, nativeWindow, null);
|
result = egl.eglCreateWindowSurface(display, config, nativeWindow, null);
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
// This exception indicates that the surface flinger surface
|
// This exception indicates that the surface flinger surface
|
||||||
// is not valid. This can happen if the surface flinger surface has
|
// is not valid. This can happen if the surface flinger surface
|
||||||
|
// has
|
||||||
// been torn down, but the application has not yet been
|
// been torn down, but the application has not yet been
|
||||||
// notified via SurfaceHolder.Callback.surfaceDestroyed.
|
// notified via SurfaceHolder.Callback.surfaceDestroyed.
|
||||||
// In theory the application should be notified first,
|
// In theory the application should be notified first,
|
||||||
@ -693,6 +756,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void destroySurface(EGL10 egl, EGLDisplay display,
|
public void destroySurface(EGL10 egl, EGLDisplay display,
|
||||||
EGLSurface surface) {
|
EGLSurface surface) {
|
||||||
egl.eglDestroySurface(display, surface);
|
egl.eglDestroySurface(display, surface);
|
||||||
@ -705,6 +769,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
|||||||
mConfigSpec = filterConfigSpec(configSpec);
|
mConfigSpec = filterConfigSpec(configSpec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
|
public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
|
||||||
int[] num_config = new int[1];
|
int[] num_config = new int[1];
|
||||||
if (!egl.eglChooseConfig(display, mConfigSpec, null, 0,
|
if (!egl.eglChooseConfig(display, mConfigSpec, null, 0,
|
||||||
@ -741,7 +806,8 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
|||||||
return configSpec;
|
return configSpec;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* We know none of the subclasses define EGL_RENDERABLE_TYPE. And we know the configSpec is well formed.
|
* We know none of the subclasses define EGL_RENDERABLE_TYPE. And we
|
||||||
|
* know the configSpec is well formed.
|
||||||
*/
|
*/
|
||||||
int len = configSpec.length;
|
int len = configSpec.length;
|
||||||
int[] newConfigSpec = new int[len + 2];
|
int[] newConfigSpec = new int[len + 2];
|
||||||
@ -754,8 +820,8 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Choose a configuration with exactly the specified r,g,b,a sizes, and at least the specified depth and stencil
|
* Choose a configuration with exactly the specified r,g,b,a sizes, and at
|
||||||
* sizes.
|
* least the specified depth and stencil sizes.
|
||||||
*/
|
*/
|
||||||
private class ComponentSizeChooser extends BaseConfigChooser {
|
private class ComponentSizeChooser extends BaseConfigChooser {
|
||||||
public ComponentSizeChooser(int redSize, int greenSize, int blueSize,
|
public ComponentSizeChooser(int redSize, int greenSize, int blueSize,
|
||||||
@ -842,8 +908,6 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize EGL for a given configuration spec.
|
* Initialize EGL for a given configuration spec.
|
||||||
*
|
|
||||||
* @param configSpec
|
|
||||||
*/
|
*/
|
||||||
public void start() {
|
public void start() {
|
||||||
if (LOG_EGL) {
|
if (LOG_EGL) {
|
||||||
@ -878,8 +942,8 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
|||||||
mEglConfig = view.mEGLConfigChooser.chooseConfig(mEgl, mEglDisplay);
|
mEglConfig = view.mEGLConfigChooser.chooseConfig(mEgl, mEglDisplay);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create an EGL context. We want to do this as rarely as we can, because an EGL context is a somewhat
|
* Create an EGL context. We want to do this as rarely as we
|
||||||
* heavy object.
|
* can, because an EGL context is a somewhat heavy object.
|
||||||
*/
|
*/
|
||||||
mEglContext = view.mEGLContextFactory.createContext(mEgl, mEglDisplay,
|
mEglContext = view.mEGLContextFactory.createContext(mEgl, mEglDisplay,
|
||||||
mEglConfig);
|
mEglConfig);
|
||||||
@ -897,8 +961,8 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an egl surface for the current SurfaceHolder surface. If a surface already exists, destroy it before
|
* Create an egl surface for the current SurfaceHolder surface. If a
|
||||||
* creating the new surface.
|
* surface already exists, destroy it before creating the new surface.
|
||||||
*
|
*
|
||||||
* @return true if the surface was created successfully.
|
* @return true if the surface was created successfully.
|
||||||
*/
|
*/
|
||||||
@ -946,12 +1010,13 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Before we can issue GL commands, we need to make sure the context is current and bound to a surface.
|
* Before we can issue GL commands, we need to make sure the context
|
||||||
|
* is current and bound to a surface.
|
||||||
*/
|
*/
|
||||||
if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
|
if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
|
||||||
/*
|
/*
|
||||||
* Could not make the context current, probably because the underlying SurfaceView surface has been
|
* Could not make the context current, probably because the
|
||||||
* destroyed.
|
* underlying SurfaceView surface has been destroyed.
|
||||||
*/
|
*/
|
||||||
logEglErrorAsWarning("EGLHelper", "eglMakeCurrent", mEgl.eglGetError());
|
logEglErrorAsWarning("EGLHelper", "eglMakeCurrent", mEgl.eglGetError());
|
||||||
return false;
|
return false;
|
||||||
@ -963,7 +1028,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
|||||||
/**
|
/**
|
||||||
* Create a GL object for the current EGL context.
|
* Create a GL object for the current EGL context.
|
||||||
*
|
*
|
||||||
* @return
|
* @return ...
|
||||||
*/
|
*/
|
||||||
GL createGL() {
|
GL createGL() {
|
||||||
|
|
||||||
@ -1060,7 +1125,8 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static String formatEglError(String function, int error) {
|
public static String formatEglError(String function, int error) {
|
||||||
return function + " failed: "; // + EGLLogWrapper.getErrorString(error);
|
return function + " failed: "; // +
|
||||||
|
// EGLLogWrapper.getErrorString(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
private WeakReference<GLSurfaceView> mGLSurfaceViewWeakRef;
|
private WeakReference<GLSurfaceView> mGLSurfaceViewWeakRef;
|
||||||
@ -1073,9 +1139,11 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A generic GL Thread. Takes care of initializing EGL and GL. Delegates to a Renderer instance to do the actual
|
* A generic GL Thread. Takes care of initializing EGL and GL. Delegates to
|
||||||
* drawing. Can be configured to render continuously or on request. All potentially blocking synchronization is done
|
* a Renderer instance to do the actual drawing. Can be configured to render
|
||||||
* through the sGLThreadManager object. This avoids multiple-lock ordering issues.
|
* continuously or on request. All potentially blocking synchronization is
|
||||||
|
* done through the sGLThreadManager object. This avoids multiple-lock
|
||||||
|
* ordering issues.
|
||||||
*/
|
*/
|
||||||
static class GLThread extends Thread {
|
static class GLThread extends Thread {
|
||||||
GLThread(WeakReference<GLSurfaceView> glSurfaceViewWeakRef) {
|
GLThread(WeakReference<GLSurfaceView> glSurfaceViewWeakRef) {
|
||||||
@ -1104,7 +1172,8 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This private method should only be called inside a synchronized(sGLThreadManager) block.
|
* This private method should only be called inside a
|
||||||
|
* synchronized(sGLThreadManager) block.
|
||||||
*/
|
*/
|
||||||
private void stopEglSurfaceLocked() {
|
private void stopEglSurfaceLocked() {
|
||||||
if (mHaveEglSurface) {
|
if (mHaveEglSurface) {
|
||||||
@ -1114,7 +1183,8 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This private method should only be called inside a synchronized(sGLThreadManager) block.
|
* This private method should only be called inside a
|
||||||
|
* synchronized(sGLThreadManager) block.
|
||||||
*/
|
*/
|
||||||
private void stopEglContextLocked() {
|
private void stopEglContextLocked() {
|
||||||
if (mHaveEglContext) {
|
if (mHaveEglContext) {
|
||||||
@ -1265,7 +1335,8 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
|||||||
// Ready to draw?
|
// Ready to draw?
|
||||||
if (readyToDraw()) {
|
if (readyToDraw()) {
|
||||||
|
|
||||||
// If we don't have an EGL context, try to acquire one.
|
// If we don't have an EGL context, try to
|
||||||
|
// acquire one.
|
||||||
if (!mHaveEglContext) {
|
if (!mHaveEglContext) {
|
||||||
if (askedToReleaseEglContext) {
|
if (askedToReleaseEglContext) {
|
||||||
askedToReleaseEglContext = false;
|
askedToReleaseEglContext = false;
|
||||||
@ -1315,7 +1386,8 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// By design, this is the only place in a GLThread thread where we wait().
|
// By design, this is the only place in a GLThread
|
||||||
|
// thread where we wait().
|
||||||
if (LOG_THREADS) {
|
if (LOG_THREADS) {
|
||||||
Log.i("GLThread", "waiting tid=" + getId()
|
Log.i("GLThread", "waiting tid=" + getId()
|
||||||
+ " mHaveEglContext: " + mHaveEglContext
|
+ " mHaveEglContext: " + mHaveEglContext
|
||||||
@ -1402,10 +1474,13 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
|||||||
lostEglContext = true;
|
lostEglContext = true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
// Other errors typically mean that the current surface is bad,
|
// Other errors typically mean that the current
|
||||||
// probably because the SurfaceView surface has been destroyed,
|
// surface is bad,
|
||||||
|
// probably because the SurfaceView surface has been
|
||||||
|
// destroyed,
|
||||||
// but we haven't been notified yet.
|
// but we haven't been notified yet.
|
||||||
// Log the error to help developers understand why rendering stopped.
|
// Log the error to help developers understand why
|
||||||
|
// rendering stopped.
|
||||||
EglHelper.logEglErrorAsWarning("GLThread", "eglSwapBuffers",
|
EglHelper.logEglErrorAsWarning("GLThread", "eglSwapBuffers",
|
||||||
swapError);
|
swapError);
|
||||||
|
|
||||||
@ -1629,8 +1704,9 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
|||||||
private EglHelper mEglHelper;
|
private EglHelper mEglHelper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set once at thread construction time, nulled out when the parent view is garbage called. This weak reference
|
* Set once at thread construction time, nulled out when the parent view
|
||||||
* allows the GLSurfaceView to be garbage collected while the GLThread is still alive.
|
* is garbage called. This weak reference allows the GLSurfaceView to be
|
||||||
|
* garbage collected while the GLThread is still alive.
|
||||||
*/
|
*/
|
||||||
private WeakReference<GLSurfaceView> mGLSurfaceViewWeakRef;
|
private WeakReference<GLSurfaceView> mGLSurfaceViewWeakRef;
|
||||||
|
|
||||||
@ -1693,8 +1769,9 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Tries once to acquire the right to use an EGL context. Does not block. Requires that we are already in the
|
* Tries once to acquire the right to use an EGL context. Does not
|
||||||
* sGLThreadManager monitor when this is called.
|
* block. Requires that we are already in the sGLThreadManager monitor
|
||||||
|
* when this is called.
|
||||||
* @return true if the right to use an EGL context was acquired.
|
* @return true if the right to use an EGL context was acquired.
|
||||||
*/
|
*/
|
||||||
public boolean tryAcquireEglContextLocked(GLThread thread) {
|
public boolean tryAcquireEglContextLocked(GLThread thread) {
|
||||||
@ -1718,7 +1795,8 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Releases the EGL context. Requires that we are already in the sGLThreadManager monitor when this is called.
|
* Releases the EGL context. Requires that we are already in the
|
||||||
|
* sGLThreadManager monitor when this is called.
|
||||||
*/
|
*/
|
||||||
public void releaseEglContextLocked(GLThread thread) {
|
public void releaseEglContextLocked(GLThread thread) {
|
||||||
if (mEglOwner == thread) {
|
if (mEglOwner == thread) {
|
||||||
@ -1777,8 +1855,9 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This check was required for some pre-Android-3.0 hardware. Android 3.0 provides support for
|
* This check was required for some pre-Android-3.0 hardware. Android
|
||||||
* hardware-accelerated views, therefore multiple EGL contexts are supported on all Android 3.0+ EGL drivers.
|
* 3.0 provides support for hardware-accelerated views, therefore
|
||||||
|
* multiple EGL contexts are supported on all Android 3.0+ EGL drivers.
|
||||||
*/
|
*/
|
||||||
private boolean mGLESVersionCheckComplete;
|
private boolean mGLESVersionCheckComplete;
|
||||||
private int mGLESVersion;
|
private int mGLESVersion;
|
||||||
@ -1791,7 +1870,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
|||||||
private GLThread mEglOwner;
|
private GLThread mEglOwner;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final GLThreadManager sGLThreadManager = new GLThreadManager();
|
/* package */static final GLThreadManager sGLThreadManager = new GLThreadManager();
|
||||||
|
|
||||||
private final WeakReference<GLSurfaceView> mThisWeakRef =
|
private final WeakReference<GLSurfaceView> mThisWeakRef =
|
||||||
new WeakReference<GLSurfaceView>(this);
|
new WeakReference<GLSurfaceView>(this);
|
||||||
|
@ -17,7 +17,6 @@ package org.oscim.view;
|
|||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
|
|
||||||
import org.oscim.core.GeoPoint;
|
import org.oscim.core.GeoPoint;
|
||||||
import org.oscim.core.MapPosition;
|
|
||||||
import org.oscim.theme.InternalRenderTheme;
|
import org.oscim.theme.InternalRenderTheme;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
|
@ -12,34 +12,29 @@
|
|||||||
* You should have received a copy of the GNU Lesser General Public License along with
|
* 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/>.
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.oscim.core;
|
package org.oscim.view;
|
||||||
|
|
||||||
|
import org.oscim.core.GeoPoint;
|
||||||
|
import org.oscim.core.MercatorProjection;
|
||||||
|
|
||||||
|
import android.opengl.Matrix;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A MapPosition represents an immutable pair of {@link GeoPoint} and zoom level.
|
* A MapPosition Container.
|
||||||
*/
|
*/
|
||||||
public class MapPosition {
|
public class MapPosition {
|
||||||
|
|
||||||
/**
|
public double lon;
|
||||||
* The map position.
|
public double lat;
|
||||||
*/
|
|
||||||
// public final GeoPoint geoPoint;
|
|
||||||
public final double lon;
|
|
||||||
public final double lat;
|
|
||||||
|
|
||||||
/**
|
public byte zoomLevel;
|
||||||
* The zoom level.
|
public float scale;
|
||||||
*/
|
public float angle;
|
||||||
public final byte zoomLevel;
|
|
||||||
|
|
||||||
/**
|
public double x;
|
||||||
* 1.0 - 2.0 scale of current zoomlevel
|
public double y;
|
||||||
*/
|
|
||||||
public final float scale;
|
|
||||||
|
|
||||||
public final float angle;
|
public float[] rotation;
|
||||||
|
|
||||||
public final double x;
|
|
||||||
public final double y;
|
|
||||||
|
|
||||||
public MapPosition() {
|
public MapPosition() {
|
||||||
this.zoomLevel = (byte) 1;
|
this.zoomLevel = (byte) 1;
|
||||||
@ -51,6 +46,11 @@ public class MapPosition {
|
|||||||
this.y = MercatorProjection.latitudeToPixelY(this.lat, zoomLevel);
|
this.y = MercatorProjection.latitudeToPixelY(this.lat, zoomLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void init() {
|
||||||
|
rotation = new float[16];
|
||||||
|
Matrix.setIdentityM(rotation, 0);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param geoPoint
|
* @param geoPoint
|
||||||
* the map position.
|
* the map position.
|
@ -17,7 +17,6 @@ package org.oscim.view;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.oscim.core.MapPosition;
|
|
||||||
import org.oscim.core.MercatorProjection;
|
import org.oscim.core.MercatorProjection;
|
||||||
|
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
|
@ -23,7 +23,6 @@ import java.util.Map;
|
|||||||
import javax.xml.parsers.ParserConfigurationException;
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
|
|
||||||
import org.oscim.core.GeoPoint;
|
import org.oscim.core.GeoPoint;
|
||||||
import org.oscim.core.MapPosition;
|
|
||||||
import org.oscim.core.Tile;
|
import org.oscim.core.Tile;
|
||||||
import org.oscim.database.IMapDatabase;
|
import org.oscim.database.IMapDatabase;
|
||||||
import org.oscim.database.MapDatabaseFactory;
|
import org.oscim.database.MapDatabaseFactory;
|
||||||
@ -56,9 +55,9 @@ public class MapView extends FrameLayout {
|
|||||||
|
|
||||||
final static String TAG = "MapView";
|
final static String TAG = "MapView";
|
||||||
|
|
||||||
public final static boolean debugFrameTime = false;
|
public static final boolean debugFrameTime = false;
|
||||||
public final static boolean testRegionZoom = false;
|
public static final boolean testRegionZoom = false;
|
||||||
private final boolean mDebugDatabase = false;
|
private static final boolean debugDatabase = false;
|
||||||
|
|
||||||
RegionLookup mRegionLookup;
|
RegionLookup mRegionLookup;
|
||||||
|
|
||||||
@ -146,7 +145,7 @@ public class MapView extends FrameLayout {
|
|||||||
|
|
||||||
for (int i = 0; i < mNumMapWorkers; i++) {
|
for (int i = 0; i < mNumMapWorkers; i++) {
|
||||||
IMapDatabase mapDatabase;
|
IMapDatabase mapDatabase;
|
||||||
if (mDebugDatabase) {
|
if (debugDatabase) {
|
||||||
// mapDatabase = MapDatabaseFactory
|
// mapDatabase = MapDatabaseFactory
|
||||||
// .createMapDatabase(MapDatabases.TEST_READER);
|
// .createMapDatabase(MapDatabases.TEST_READER);
|
||||||
mapDatabase = MapDatabaseFactory
|
mapDatabase = MapDatabaseFactory
|
||||||
@ -188,7 +187,7 @@ public class MapView extends FrameLayout {
|
|||||||
mMapZoomControls = new MapZoomControls(mapActivity, this);
|
mMapZoomControls = new MapZoomControls(mapActivity, this);
|
||||||
mMapZoomControls.setShowMapZoomControls(true);
|
mMapZoomControls.setShowMapZoomControls(true);
|
||||||
|
|
||||||
// enableRotation = true;
|
enableRotation = true;
|
||||||
|
|
||||||
for (MapWorker worker : mMapWorkers)
|
for (MapWorker worker : mMapWorkers)
|
||||||
worker.start();
|
worker.start();
|
||||||
@ -353,7 +352,7 @@ public class MapView extends FrameLayout {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
public void setMapDatabase(MapDatabases mapDatabaseType) {
|
public void setMapDatabase(MapDatabases mapDatabaseType) {
|
||||||
if (mDebugDatabase)
|
if (debugDatabase)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
TileGenerator tileGenerator;
|
TileGenerator tileGenerator;
|
||||||
@ -470,6 +469,9 @@ public class MapView extends FrameLayout {
|
|||||||
Log.d(TAG, "onSizeChanged" + width + " " + height);
|
Log.d(TAG, "onSizeChanged" + width + " " + height);
|
||||||
super.onSizeChanged(width, height, oldWidth, oldHeight);
|
super.onSizeChanged(width, height, oldWidth, oldHeight);
|
||||||
|
|
||||||
|
if (width != 0 && height != 0)
|
||||||
|
mMapViewPosition.setViewport(width, height);
|
||||||
|
|
||||||
mapWorkersProceed();
|
mapWorkersProceed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010, 2011, 2012 mapsforge.org
|
* Copyright 2010, 2011, 2012 mapsforge.org, 2012 Hannes Janetzek
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify it under the
|
* 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
|
* terms of the GNU Lesser General Public License as published by the Free Software
|
||||||
@ -15,36 +15,36 @@
|
|||||||
package org.oscim.view;
|
package org.oscim.view;
|
||||||
|
|
||||||
import org.oscim.core.GeoPoint;
|
import org.oscim.core.GeoPoint;
|
||||||
import org.oscim.core.MapPosition;
|
|
||||||
import org.oscim.core.MercatorProjection;
|
import org.oscim.core.MercatorProjection;
|
||||||
import org.oscim.utils.FastMath;
|
import org.oscim.utils.FastMath;
|
||||||
|
|
||||||
|
import android.opengl.Matrix;
|
||||||
|
import android.util.FloatMath;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A MapPosition stores the latitude and longitude coordinate of a MapView
|
* A MapPosition stores the latitude and longitude coordinate of a MapView
|
||||||
* together with its zoom level.
|
* together with its zoom level.
|
||||||
*/
|
*/
|
||||||
public class MapViewPosition {
|
public class MapViewPosition {
|
||||||
private static final String TAG = "MapViewPosition";
|
// private static final String TAG = "MapViewPosition";
|
||||||
|
|
||||||
public final static int MAX_ZOOMLEVEL = 16;
|
public final static int MAX_ZOOMLEVEL = 17;
|
||||||
|
|
||||||
private final static float MAX_SCALE = 2.0f;
|
private final static float MAX_ANGLE = 20;
|
||||||
private final static float MIN_SCALE = 1.0f;
|
|
||||||
|
|
||||||
private final MapView mMapView;
|
private final MapView mMapView;
|
||||||
|
|
||||||
private double mLatitude;
|
private double mLatitude;
|
||||||
private double mLongitude;
|
private double mLongitude;
|
||||||
private byte mZoomLevel;
|
private byte mZoomLevel;
|
||||||
|
// 1.0 - 2.0 scale per level
|
||||||
private float mScale;
|
private float mScale;
|
||||||
private float mRotation;
|
|
||||||
public float mTilt;
|
|
||||||
|
|
||||||
// 2^mZoomLevel * mScale;
|
// 2^mZoomLevel * mScale;
|
||||||
private float mMapScale;
|
private float mMapScale;
|
||||||
|
|
||||||
// private final static float MAP_SIZE = 1000000;
|
private float mRotation;
|
||||||
// private final static float MAP_SIZE2 = 1000000 >> 1;
|
public float mTilt;
|
||||||
|
|
||||||
MapViewPosition(MapView mapView) {
|
MapViewPosition(MapView mapView) {
|
||||||
mMapView = mapView;
|
mMapView = mapView;
|
||||||
@ -58,20 +58,158 @@ public class MapViewPosition {
|
|||||||
mMapScale = 1;
|
mMapScale = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// private static double latitudeToMapView(double latitude) {
|
private float[] mProjMatrix = new float[16];
|
||||||
// double sinLatitude = Math.sin(latitude * (Math.PI / 180));
|
private float[] mProjMatrixI = new float[16];
|
||||||
// return (0.5 - Math.log((1 + sinLatitude) / (1 - sinLatitude)) / (4 *
|
private float[] mUnprojMatrix = new float[16];
|
||||||
// Math.PI))
|
private float[] mRotateMatrix = new float[16];
|
||||||
// * MAP_SIZE;
|
private float[] mTmpMatrix = new float[16];
|
||||||
// }
|
|
||||||
//
|
private int mHeight, mWidth;
|
||||||
// public static double longitudeToMapView(double longitude) {
|
|
||||||
// return (longitude + 180) / 360 * MAP_SIZE;
|
void setViewport(int width, int height) {
|
||||||
// }
|
Matrix.frustumM(mProjMatrix, 0, -0.5f * width, 0.5f * width,
|
||||||
//
|
-0.5f * height, 0.5f * height, 1, 2);
|
||||||
// private static double pixelXToLongitude(double pixelX, byte zoomLevel) {
|
|
||||||
// return 360 * ((pixelX / ((long) Tile.TILE_SIZE << zoomLevel)) - 0.5);
|
Matrix.translateM(mProjMatrix, 0, 0, 0, -1);
|
||||||
// }
|
|
||||||
|
Matrix.invertM(mProjMatrixI, 0, mProjMatrix, 0);
|
||||||
|
Matrix.invertM(mUnprojMatrix, 0, mProjMatrix, 0);
|
||||||
|
|
||||||
|
Matrix.setIdentityM(mRotateMatrix, 0);
|
||||||
|
|
||||||
|
mHeight = height;
|
||||||
|
mWidth = width;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized boolean getMapPosition(final MapPosition mapPosition,
|
||||||
|
final float[] coords) {
|
||||||
|
// if (!isValid())
|
||||||
|
// return false;
|
||||||
|
|
||||||
|
// if (mapPosition.lat == mLatitude
|
||||||
|
// && mapPosition.lon == mLongitude
|
||||||
|
// && mapPosition.zoomLevel == mZoomLevel
|
||||||
|
// && mapPosition.scale == mScale
|
||||||
|
// && mapPosition.angle == mRotation)
|
||||||
|
// return false;
|
||||||
|
|
||||||
|
mapPosition.lat = mLatitude;
|
||||||
|
mapPosition.lon = mLongitude;
|
||||||
|
mapPosition.angle = mRotation;
|
||||||
|
mapPosition.zoomLevel = mZoomLevel;
|
||||||
|
mapPosition.scale = mScale;
|
||||||
|
byte z = mZoomLevel;
|
||||||
|
mapPosition.x = MercatorProjection.longitudeToPixelX(mLongitude, z);
|
||||||
|
mapPosition.y = MercatorProjection.latitudeToPixelY(mLatitude, z);
|
||||||
|
|
||||||
|
if (mapPosition.rotation != null) {
|
||||||
|
// updateMatrix();
|
||||||
|
System.arraycopy(mRotateMatrix, 0, mapPosition.rotation, 0, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (coords == null)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// if (mapPosition.rotation == null)
|
||||||
|
// updateMatrix();
|
||||||
|
|
||||||
|
// not so sure about this, but works...
|
||||||
|
float tilt = FloatMath.sin((float) Math.toRadians(mTilt)) * 4;
|
||||||
|
|
||||||
|
unproject(-1, 1, tilt, coords, 0); // top-left
|
||||||
|
unproject(1, 1, tilt, coords, 2); // top-right
|
||||||
|
unproject(1, -1, -tilt, coords, 4); // bottom-right
|
||||||
|
unproject(-1, -1, -tilt, coords, 6); // bottom-left
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private float[] mv = { 0, 0, 0, 1 };
|
||||||
|
private float[] mBBoxCoords = new float[8];
|
||||||
|
|
||||||
|
private void unproject(float x, float y, float z, float[] coords, int position) {
|
||||||
|
mv[0] = x;
|
||||||
|
mv[1] = y;
|
||||||
|
mv[2] = z - 1;
|
||||||
|
mv[3] = 1;
|
||||||
|
|
||||||
|
Matrix.multiplyMV(mv, 0, mUnprojMatrix, 0, mv, 0);
|
||||||
|
|
||||||
|
if (mv[3] != 0) {
|
||||||
|
float w = 1 / mv[3];
|
||||||
|
float xx = mv[0] * w;
|
||||||
|
float yy = mv[1] * w;
|
||||||
|
|
||||||
|
coords[position] = xx;
|
||||||
|
coords[position + 1] = yy;
|
||||||
|
}
|
||||||
|
// else what?
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateMatrix() {
|
||||||
|
Matrix.setRotateM(mRotateMatrix, 0, mRotation, 0, 0, 1);
|
||||||
|
|
||||||
|
// tilt map
|
||||||
|
float tilt = mTilt;
|
||||||
|
Matrix.setRotateM(mTmpMatrix, 0, -tilt / (mHeight / 2), 1, 0, 0);
|
||||||
|
|
||||||
|
// apply first rotation, then tilt
|
||||||
|
Matrix.multiplyMM(mRotateMatrix, 0, mTmpMatrix, 0, mRotateMatrix, 0);
|
||||||
|
|
||||||
|
// get unproject matrix:
|
||||||
|
// (transpose of rotation is its inverse)
|
||||||
|
Matrix.transposeM(mTmpMatrix, 0, mRotateMatrix, 0);
|
||||||
|
// (AB)^-1 = B^-1*A^-1
|
||||||
|
Matrix.multiplyMM(mUnprojMatrix, 0, mTmpMatrix, 0, mProjMatrixI, 0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sets viewBox to visible bounding box, (left,top,right,bottom)
|
||||||
|
*
|
||||||
|
* @param viewBox
|
||||||
|
* ...
|
||||||
|
*/
|
||||||
|
public synchronized void getViewBox(final float[] viewBox) {
|
||||||
|
|
||||||
|
updateMatrix();
|
||||||
|
|
||||||
|
float tilt = FloatMath.sin((float) Math.toRadians(mTilt)) * 4;
|
||||||
|
|
||||||
|
unproject(-1, 1, tilt, mBBoxCoords, 0); // top-left
|
||||||
|
unproject(1, 1, tilt, mBBoxCoords, 2); // top-right
|
||||||
|
unproject(1, -1, -tilt, mBBoxCoords, 4); // bottom-right
|
||||||
|
unproject(-1, -1, -tilt, mBBoxCoords, 6); // bottom-left
|
||||||
|
|
||||||
|
byte z = mZoomLevel;
|
||||||
|
double pixelX = MercatorProjection.longitudeToPixelX(mLongitude, z);
|
||||||
|
double pixelY = MercatorProjection.latitudeToPixelY(mLatitude, z);
|
||||||
|
|
||||||
|
double dx = pixelX - mBBoxCoords[0] / mScale;
|
||||||
|
double dy = pixelY - mBBoxCoords[1] / mScale;
|
||||||
|
double lon = MercatorProjection.pixelXToLongitude(dx, z);
|
||||||
|
double lat = MercatorProjection.pixelYToLatitude(dy, z);
|
||||||
|
Log.d(">>>", "bl:" + lon + " " + lat);
|
||||||
|
|
||||||
|
dx = pixelX - mBBoxCoords[2] / mScale;
|
||||||
|
dy = pixelY - mBBoxCoords[3] / mScale;
|
||||||
|
lon = MercatorProjection.pixelXToLongitude(dx, z);
|
||||||
|
lat = MercatorProjection.pixelYToLatitude(dy, z);
|
||||||
|
Log.d("...", "br:" + lon + " " + lat);
|
||||||
|
|
||||||
|
dx = pixelX - mBBoxCoords[4] / mScale;
|
||||||
|
dy = pixelY - mBBoxCoords[5] / mScale;
|
||||||
|
lon = MercatorProjection.pixelXToLongitude(dx, z);
|
||||||
|
lat = MercatorProjection.pixelYToLatitude(dy, z);
|
||||||
|
Log.d("...", "tl:" + lon + " " + lat);
|
||||||
|
|
||||||
|
dx = pixelX - mBBoxCoords[6] / mScale;
|
||||||
|
dy = pixelY - mBBoxCoords[7] / mScale;
|
||||||
|
lon = MercatorProjection.pixelXToLongitude(dx, z);
|
||||||
|
lat = MercatorProjection.pixelYToLatitude(dy, z);
|
||||||
|
Log.d("...", "tr:" + lon + " " + lat);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the current center point of the MapView.
|
* @return the current center point of the MapView.
|
||||||
@ -168,6 +306,15 @@ public class MapViewPosition {
|
|||||||
return new GeoPoint(latitude, longitude);
|
return new GeoPoint(latitude, longitude);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// public static double pixelXToLongitude(double pixelX, byte zoomLevel) {
|
||||||
|
// return 360 * ((pixelX / ((long) Tile.TILE_SIZE << zoomLevel)) - 0.5);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// public static double pixelYToLatitude(double pixelY, byte zoomLevel) {
|
||||||
|
// double y = 0.5 - (pixelY / ((long) Tile.TILE_SIZE << zoomLevel));
|
||||||
|
// return 90 - 360 * Math.atan(Math.exp(-y * (2 * Math.PI))) / Math.PI;
|
||||||
|
// }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Moves this MapViewPosition by the given amount of pixels.
|
* Moves this MapViewPosition by the given amount of pixels.
|
||||||
*
|
*
|
||||||
@ -187,14 +334,13 @@ public class MapViewPosition {
|
|||||||
double rad = Math.toRadians(mRotation);
|
double rad = Math.toRadians(mRotation);
|
||||||
double x = dx * Math.cos(rad) + dy * -Math.sin(rad);
|
double x = dx * Math.cos(rad) + dy * -Math.sin(rad);
|
||||||
double y = dx * Math.sin(rad) + dy * Math.cos(rad);
|
double y = dx * Math.sin(rad) + dy * Math.cos(rad);
|
||||||
|
dx = x;
|
||||||
dx = pixelX - x;
|
dy = y;
|
||||||
dy = pixelY - y;
|
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
dx = pixelX - dx;
|
dx = pixelX - dx;
|
||||||
dy = pixelY - dy;
|
dy = pixelY - dy;
|
||||||
}
|
|
||||||
mLatitude = MercatorProjection.pixelYToLatitude(dy, mZoomLevel);
|
mLatitude = MercatorProjection.pixelYToLatitude(dy, mZoomLevel);
|
||||||
mLatitude = MercatorProjection.limitLatitude(mLatitude);
|
mLatitude = MercatorProjection.limitLatitude(mLatitude);
|
||||||
|
|
||||||
@ -202,6 +348,8 @@ public class MapViewPosition {
|
|||||||
|
|
||||||
mLongitude = MercatorProjection.wrapLongitude(mLongitude);
|
mLongitude = MercatorProjection.wrapLongitude(mLongitude);
|
||||||
// mLongitude = MercatorProjection.limitLongitude(mLongitude);
|
// mLongitude = MercatorProjection.limitLongitude(mLongitude);
|
||||||
|
|
||||||
|
// getViewBox(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void rotateMap(float angle, float cx, float cy) {
|
public synchronized void rotateMap(float angle, float cx, float cy) {
|
||||||
@ -209,14 +357,17 @@ public class MapViewPosition {
|
|||||||
// Log.d("MapViewPosition", "rotate:" + angle + " " + (mRotation -
|
// Log.d("MapViewPosition", "rotate:" + angle + " " + (mRotation -
|
||||||
// angle));
|
// angle));
|
||||||
mRotation -= angle;
|
mRotation -= angle;
|
||||||
|
updateMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setRotation(float f) {
|
public void setRotation(float f) {
|
||||||
mRotation = f;
|
mRotation = f;
|
||||||
|
updateMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTilt(float f) {
|
public void setTilt(float f) {
|
||||||
mTilt = f;
|
mTilt = f;
|
||||||
|
updateMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized void setMapCenter(GeoPoint geoPoint) {
|
synchronized void setMapCenter(GeoPoint geoPoint) {
|
||||||
@ -251,38 +402,41 @@ public class MapViewPosition {
|
|||||||
* ...
|
* ...
|
||||||
* @param pivotY
|
* @param pivotY
|
||||||
* ...
|
* ...
|
||||||
|
* @return true if scale was changed
|
||||||
*/
|
*/
|
||||||
public synchronized void scaleMap(float scale, float pivotX, float pivotY) {
|
public synchronized boolean scaleMap(float scale, float pivotX, float pivotY) {
|
||||||
if (pivotY != 0 || pivotY != 0)
|
|
||||||
moveMap(pivotX * (1.0f - scale),
|
|
||||||
pivotY * (1.0f - scale));
|
|
||||||
|
|
||||||
float newScale = mMapScale * scale;
|
float newScale = mMapScale * scale;
|
||||||
|
|
||||||
int z = FastMath.log2((int) newScale);
|
int z = FastMath.log2((int) newScale);
|
||||||
|
|
||||||
if (z <= 0 || (z >= MAX_ZOOMLEVEL && mScale >= 8))
|
if (z <= 0 || (z >= MAX_ZOOMLEVEL && mScale >= 8))
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
if (z > MAX_ZOOMLEVEL) {
|
if (z > MAX_ZOOMLEVEL) {
|
||||||
// z16 shows everything, just increase scaling
|
// z16 shows everything, just increase scaling
|
||||||
if (mScale * scale > 8)
|
if (mScale * scale > 8)
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
mScale *= scale;
|
mScale *= scale;
|
||||||
mMapScale = newScale;
|
mMapScale = newScale;
|
||||||
return;
|
} else {
|
||||||
}
|
|
||||||
|
|
||||||
mZoomLevel = (byte) z;
|
mZoomLevel = (byte) z;
|
||||||
mScale = newScale / (1 << z);
|
mScale = newScale / (1 << z);
|
||||||
mMapScale = newScale;
|
mMapScale = newScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pivotY != 0 || pivotY != 0)
|
||||||
|
moveMap(pivotX * (1.0f - scale),
|
||||||
|
pivotY * (1.0f - scale));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean tilt(float moveX) {
|
public boolean tilt(float moveX) {
|
||||||
float tilt = mTilt + moveX;
|
float tilt = mTilt + moveX;
|
||||||
if (tilt > 25)
|
if (tilt > MAX_ANGLE)
|
||||||
tilt = 25;
|
tilt = MAX_ANGLE;
|
||||||
else if (tilt < 0)
|
else if (tilt < 0)
|
||||||
tilt = 0;
|
tilt = 0;
|
||||||
if (mTilt == tilt)
|
if (mTilt == tilt)
|
||||||
|
@ -123,7 +123,7 @@ public class MapZoomControls {
|
|||||||
mShowMapZoomControls = true;
|
mShowMapZoomControls = true;
|
||||||
mZoomLevelMax = DEFAULT_ZOOM_LEVEL_MAX;
|
mZoomLevelMax = DEFAULT_ZOOM_LEVEL_MAX;
|
||||||
mZoomLevelMin = DEFAULT_ZOOM_LEVEL_MIN;
|
mZoomLevelMin = DEFAULT_ZOOM_LEVEL_MIN;
|
||||||
if (!MapView.testRegionZoom)
|
// if (!MapView.testRegionZoom)
|
||||||
mZoomControls.setVisibility(View.GONE);
|
mZoomControls.setVisibility(View.GONE);
|
||||||
mZoomControlsGravity = DEFAULT_ZOOM_CONTROLS_GRAVITY;
|
mZoomControlsGravity = DEFAULT_ZOOM_CONTROLS_GRAVITY;
|
||||||
|
|
||||||
@ -203,12 +203,14 @@ public class MapZoomControls {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the gravity for the placing of the zoom controls. Supported values are {@link Gravity#TOP},
|
* Sets the gravity for the placing of the zoom controls. Supported values
|
||||||
* {@link Gravity#CENTER_VERTICAL}, {@link Gravity#BOTTOM}, {@link Gravity#LEFT}, {@link Gravity#CENTER_HORIZONTAL}
|
* are {@link Gravity#TOP}, {@link Gravity#CENTER_VERTICAL},
|
||||||
* and {@link Gravity#RIGHT}.
|
* {@link Gravity#BOTTOM}, {@link Gravity#LEFT},
|
||||||
|
* {@link Gravity#CENTER_HORIZONTAL} and {@link Gravity#RIGHT}.
|
||||||
*
|
*
|
||||||
* @param zoomControlsGravity
|
* @param zoomControlsGravity
|
||||||
* a combination of {@link Gravity} constants describing the desired placement.
|
* a combination of {@link Gravity} constants describing the
|
||||||
|
* desired placement.
|
||||||
*/
|
*/
|
||||||
public void setZoomControlsGravity(int zoomControlsGravity) {
|
public void setZoomControlsGravity(int zoomControlsGravity) {
|
||||||
if (mZoomControlsGravity != zoomControlsGravity) {
|
if (mZoomControlsGravity != zoomControlsGravity) {
|
||||||
@ -220,14 +222,16 @@ public class MapZoomControls {
|
|||||||
/**
|
/**
|
||||||
* Sets the maximum zoom level of the map.
|
* Sets the maximum zoom level of the map.
|
||||||
* <p>
|
* <p>
|
||||||
* The maximum possible zoom level of the MapView depends also on the current {@link TileGenerator}. For example,
|
* The maximum possible zoom level of the MapView depends also on the
|
||||||
* downloading map tiles may only be possible up to a certain zoom level. Setting a higher maximum zoom level has no
|
* current {@link TileGenerator}. For example, downloading map tiles may
|
||||||
* effect in this case.
|
* only be possible up to a certain zoom level. Setting a higher maximum
|
||||||
|
* zoom level has no effect in this case.
|
||||||
*
|
*
|
||||||
* @param zoomLevelMax
|
* @param zoomLevelMax
|
||||||
* the maximum zoom level.
|
* the maximum zoom level.
|
||||||
* @throws IllegalArgumentException
|
* @throws IllegalArgumentException
|
||||||
* if the maximum zoom level is smaller than the current minimum zoom level.
|
* if the maximum zoom level is smaller than the current minimum
|
||||||
|
* zoom level.
|
||||||
*/
|
*/
|
||||||
public void setZoomLevelMax(byte zoomLevelMax) {
|
public void setZoomLevelMax(byte zoomLevelMax) {
|
||||||
if (zoomLevelMax < mZoomLevelMin) {
|
if (zoomLevelMax < mZoomLevelMin) {
|
||||||
@ -242,7 +246,8 @@ public class MapZoomControls {
|
|||||||
* @param zoomLevelMin
|
* @param zoomLevelMin
|
||||||
* the minimum zoom level.
|
* the minimum zoom level.
|
||||||
* @throws IllegalArgumentException
|
* @throws IllegalArgumentException
|
||||||
* if the minimum zoom level is larger than the current maximum zoom level.
|
* if the minimum zoom level is larger than the current maximum
|
||||||
|
* zoom level.
|
||||||
*/
|
*/
|
||||||
public void setZoomLevelMin(byte zoomLevelMin) {
|
public void setZoomLevelMin(byte zoomLevelMin) {
|
||||||
if (zoomLevelMin > mZoomLevelMax) {
|
if (zoomLevelMin > mZoomLevelMax) {
|
||||||
|
@ -23,7 +23,6 @@ import java.util.ArrayList;
|
|||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
import org.oscim.core.GeoPoint;
|
import org.oscim.core.GeoPoint;
|
||||||
import org.oscim.core.MapPosition;
|
|
||||||
import org.oscim.core.MercatorProjection;
|
import org.oscim.core.MercatorProjection;
|
||||||
|
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
|
@ -32,20 +32,24 @@ import android.widget.Scroller;
|
|||||||
* Implementation for multi-touch capable devices. TODO write a AnimationTimer
|
* Implementation for multi-touch capable devices. TODO write a AnimationTimer
|
||||||
* instead of using CountDownTimer
|
* instead of using CountDownTimer
|
||||||
*/
|
*/
|
||||||
public class TouchHandler {
|
public class TouchHandler
|
||||||
|
extends SimpleOnGestureListener
|
||||||
|
implements ScaleGestureDetector.OnScaleGestureListener {
|
||||||
|
|
||||||
|
private static final float SCALE_DURATION = 450;
|
||||||
private static final int INVALID_POINTER_ID = -1;
|
private static final int INVALID_POINTER_ID = -1;
|
||||||
|
|
||||||
/* package */final MapView mMapView;
|
private final MapView mMapView;
|
||||||
/* package */final MapViewPosition mMapPosition;
|
private final MapViewPosition mMapPosition;
|
||||||
/* package */final DecelerateInterpolator mInterpolator = new DecelerateInterpolator();
|
private final DecelerateInterpolator mInterpolator = new DecelerateInterpolator();
|
||||||
/* package */boolean mBeginScale;
|
private boolean mBeginScale;
|
||||||
/* package */float mSumScale;
|
private float mSumScale;
|
||||||
|
|
||||||
private final float mMapMoveDelta;
|
private final float mMapMoveDelta;
|
||||||
private boolean mMoveStart;
|
private boolean mMoveStart;
|
||||||
private boolean mBeginRotate;
|
private boolean mBeginRotate;
|
||||||
/* package */float mPosX;
|
private float mPosX;
|
||||||
/* package */float mPosY;
|
private float mPosY;
|
||||||
private double mAngle;
|
private double mAngle;
|
||||||
|
|
||||||
private int mActivePointerId;
|
private int mActivePointerId;
|
||||||
@ -65,9 +69,47 @@ public class TouchHandler {
|
|||||||
mMapPosition = mapView.getMapPosition();
|
mMapPosition = mapView.getMapPosition();
|
||||||
mMapMoveDelta = viewConfiguration.getScaledTouchSlop();
|
mMapMoveDelta = viewConfiguration.getScaledTouchSlop();
|
||||||
mActivePointerId = INVALID_POINTER_ID;
|
mActivePointerId = INVALID_POINTER_ID;
|
||||||
mScaleGestureDetector = new ScaleGestureDetector(context, new ScaleListener());
|
mScaleGestureDetector = new ScaleGestureDetector(context, this);
|
||||||
mGestureDetector = new GestureDetector(context, new MapGestureDetector());
|
mGestureDetector = new GestureDetector(context, this);
|
||||||
|
|
||||||
|
mScroller = new Scroller(mMapView.getContext(),
|
||||||
|
new android.view.animation.LinearInterpolator());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param event
|
||||||
|
* ...
|
||||||
|
* @return ...
|
||||||
|
*/
|
||||||
|
public boolean handleMotionEvent(MotionEvent event) {
|
||||||
|
|
||||||
|
// workaround for a bug in the ScaleGestureDetector, see Android issue
|
||||||
|
// #12976
|
||||||
|
// if (event.getAction() != MotionEvent.ACTION_MOVE
|
||||||
|
// || event.getPointerCount() > 1) {
|
||||||
|
mScaleGestureDetector.onTouchEvent(event);
|
||||||
|
// }
|
||||||
|
|
||||||
|
if (!mScaling)
|
||||||
|
mGestureDetector.onTouchEvent(event);
|
||||||
|
|
||||||
|
int action = getAction(event);
|
||||||
|
boolean ret = false;
|
||||||
|
if (action == MotionEvent.ACTION_DOWN) {
|
||||||
|
ret = onActionDown(event);
|
||||||
|
} else if (action == MotionEvent.ACTION_MOVE) {
|
||||||
|
ret = onActionMove(event);
|
||||||
|
} else if (action == MotionEvent.ACTION_UP) {
|
||||||
|
ret = onActionUp(event);
|
||||||
|
} else if (action == MotionEvent.ACTION_CANCEL) {
|
||||||
|
ret = onActionCancel();
|
||||||
|
} else if (action == MotionEvent.ACTION_POINTER_DOWN) {
|
||||||
|
return onActionPointerDown(event);
|
||||||
|
} else if (action == MotionEvent.ACTION_POINTER_UP) {
|
||||||
|
ret = onActionPointerUp(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int getAction(MotionEvent motionEvent) {
|
private static int getAction(MotionEvent motionEvent) {
|
||||||
@ -131,8 +173,9 @@ public class TouchHandler {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mMapView.enableRotation) {
|
if (!mMapView.enableRotation || multi < 1)
|
||||||
if (multi > 0) {
|
return true;
|
||||||
|
|
||||||
double x1 = event.getX(0);
|
double x1 = event.getX(0);
|
||||||
double x2 = event.getX(1);
|
double x2 = event.getX(1);
|
||||||
double y1 = event.getY(0);
|
double y1 = event.getY(0);
|
||||||
@ -170,9 +213,6 @@ public class TouchHandler {
|
|||||||
mMapView.redrawMap();
|
mMapView.redrawMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -225,53 +265,12 @@ public class TouchHandler {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/******************* SimpleOnGestureListener *******************/
|
||||||
* @param event
|
|
||||||
* ...
|
|
||||||
* @return ...
|
|
||||||
*/
|
|
||||||
public boolean handleMotionEvent(MotionEvent event) {
|
|
||||||
|
|
||||||
// workaround for a bug in the ScaleGestureDetector, see Android issue
|
|
||||||
// #12976
|
|
||||||
// if (event.getAction() != MotionEvent.ACTION_MOVE
|
|
||||||
// || event.getPointerCount() > 1) {
|
|
||||||
mScaleGestureDetector.onTouchEvent(event);
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (!mScaling)
|
|
||||||
mGestureDetector.onTouchEvent(event);
|
|
||||||
|
|
||||||
int action = getAction(event);
|
|
||||||
boolean ret = false;
|
|
||||||
if (action == MotionEvent.ACTION_DOWN) {
|
|
||||||
ret = onActionDown(event);
|
|
||||||
} else if (action == MotionEvent.ACTION_MOVE) {
|
|
||||||
ret = onActionMove(event);
|
|
||||||
} else if (action == MotionEvent.ACTION_UP) {
|
|
||||||
ret = onActionUp(event);
|
|
||||||
} else if (action == MotionEvent.ACTION_CANCEL) {
|
|
||||||
ret = onActionCancel();
|
|
||||||
} else if (action == MotionEvent.ACTION_POINTER_DOWN) {
|
|
||||||
return onActionPointerDown(event);
|
|
||||||
} else if (action == MotionEvent.ACTION_POINTER_UP) {
|
|
||||||
ret = onActionPointerUp(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
class MapGestureDetector extends SimpleOnGestureListener {
|
|
||||||
private Scroller mScroller;
|
private Scroller mScroller;
|
||||||
private float mScrollX, mScrollY, mPrevScale;
|
private float mScrollX, mScrollY;
|
||||||
private CountDownTimer mTimer = null;
|
|
||||||
private boolean fling = false;
|
private boolean fling = false;
|
||||||
|
|
||||||
public MapGestureDetector() {
|
|
||||||
mScroller = new Scroller(mMapView.getContext(),
|
|
||||||
new android.view.animation.LinearInterpolator());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onDown(MotionEvent e) {
|
public boolean onDown(MotionEvent e) {
|
||||||
if (fling) {
|
if (fling) {
|
||||||
@ -346,14 +345,12 @@ public class TouchHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final float mScaleDuration = 300;
|
boolean scale2(long tick) {
|
||||||
|
|
||||||
boolean scale(long tick) {
|
|
||||||
|
|
||||||
fling = true;
|
fling = true;
|
||||||
if (mPrevScale >= 1)
|
if (mPrevScale >= 1)
|
||||||
return false;
|
return false;
|
||||||
float adv = (mScaleDuration - tick) / mScaleDuration;
|
float adv = (SCALE_DURATION - tick) / SCALE_DURATION;
|
||||||
adv = mInterpolator.getInterpolation(adv);
|
adv = mInterpolator.getInterpolation(adv);
|
||||||
|
|
||||||
float scale = adv - mPrevScale;
|
float scale = adv - mPrevScale;
|
||||||
@ -381,10 +378,10 @@ public class TouchHandler {
|
|||||||
mScrollY = (e.getY(0) - (mMapView.getHeight() >> 1)) * 2f;
|
mScrollY = (e.getY(0) - (mMapView.getHeight() >> 1)) * 2f;
|
||||||
mPrevScale = 0;
|
mPrevScale = 0;
|
||||||
|
|
||||||
mTimer = new CountDownTimer((int) mScaleDuration, 30) {
|
mTimer = new CountDownTimer((int) SCALE_DURATION, 30) {
|
||||||
@Override
|
@Override
|
||||||
public void onTick(long tick) {
|
public void onTick(long tick) {
|
||||||
scale(tick);
|
scale2(tick);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -395,9 +392,9 @@ public class TouchHandler {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
class ScaleListener implements ScaleGestureDetector.OnScaleGestureListener {
|
/******************* ScaleListener *******************/
|
||||||
|
|
||||||
private float mCenterX;
|
private float mCenterX;
|
||||||
private float mCenterY;
|
private float mCenterY;
|
||||||
private float mFocusX;
|
private float mFocusX;
|
||||||
@ -425,7 +422,7 @@ public class TouchHandler {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
mMapPosition.scaleMap(scale, mFocusX, mFocusY);
|
if (mMapPosition.scaleMap(scale, mFocusX, mFocusY))
|
||||||
mMapView.redrawMap();
|
mMapView.redrawMap();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -458,7 +455,7 @@ public class TouchHandler {
|
|||||||
|
|
||||||
mZooutOut = mSumScale < 0.99;
|
mZooutOut = mSumScale < 0.99;
|
||||||
|
|
||||||
mTimer = new CountDownTimer((int) mScaleDuration, 15) {
|
mTimer = new CountDownTimer((int) SCALE_DURATION, 15) {
|
||||||
@Override
|
@Override
|
||||||
public void onTick(long tick) {
|
public void onTick(long tick) {
|
||||||
scale(tick);
|
scale(tick);
|
||||||
@ -477,7 +474,6 @@ public class TouchHandler {
|
|||||||
private float mPrevScale;
|
private float mPrevScale;
|
||||||
private CountDownTimer mTimer;
|
private CountDownTimer mTimer;
|
||||||
boolean mZooutOut;
|
boolean mZooutOut;
|
||||||
private final float mScaleDuration = 450;
|
|
||||||
|
|
||||||
boolean scale(long tick) {
|
boolean scale(long tick) {
|
||||||
|
|
||||||
@ -486,7 +482,7 @@ public class TouchHandler {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
float adv = (mScaleDuration - tick) / mScaleDuration;
|
float adv = (SCALE_DURATION - tick) / SCALE_DURATION;
|
||||||
adv = mInterpolator.getInterpolation(adv);
|
adv = mInterpolator.getInterpolation(adv);
|
||||||
|
|
||||||
float scale = adv - mPrevScale;
|
float scale = adv - mPrevScale;
|
||||||
@ -505,5 +501,4 @@ public class TouchHandler {
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -15,12 +15,12 @@
|
|||||||
package org.oscim.view.generator;
|
package org.oscim.view.generator;
|
||||||
|
|
||||||
import org.oscim.utils.PausableThread;
|
import org.oscim.utils.PausableThread;
|
||||||
import org.oscim.view.renderer.TileGenerator;
|
|
||||||
import org.oscim.view.renderer.MapRenderer;
|
import org.oscim.view.renderer.MapRenderer;
|
||||||
|
import org.oscim.view.renderer.TileGenerator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A MapWorker uses a {@link IMapGenerator} to generate map tiles. It runs in a separate thread to avoid blocking the UI
|
* A MapWorker uses a {@link TileGenerator} to generate map tiles. It runs in a
|
||||||
* thread.
|
* separate thread to avoid blocking the UI thread.
|
||||||
*/
|
*/
|
||||||
public class MapWorker extends PausableThread {
|
public class MapWorker extends PausableThread {
|
||||||
private final String THREAD_NAME;
|
private final String THREAD_NAME;
|
||||||
@ -28,11 +28,11 @@ public class MapWorker extends PausableThread {
|
|||||||
private final TileGenerator mMapGenerator;
|
private final TileGenerator mMapGenerator;
|
||||||
private final MapRenderer mMapRenderer;
|
private final MapRenderer mMapRenderer;
|
||||||
|
|
||||||
// private final int mPrio;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param id
|
* @param id
|
||||||
* thread id
|
* thread id
|
||||||
|
* @param jobQueue
|
||||||
|
* ...
|
||||||
* @param tileGenerator
|
* @param tileGenerator
|
||||||
* ...
|
* ...
|
||||||
* @param mapRenderer
|
* @param mapRenderer
|
||||||
@ -46,7 +46,6 @@ public class MapWorker extends PausableThread {
|
|||||||
mMapRenderer = mapRenderer;
|
mMapRenderer = mapRenderer;
|
||||||
|
|
||||||
THREAD_NAME = "MapWorker" + id;
|
THREAD_NAME = "MapWorker" + id;
|
||||||
// mPrio = Math.max(Thread.MIN_PRIORITY + id, Thread.NORM_PRIORITY - 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public TileGenerator getMapGenerator() {
|
public TileGenerator getMapGenerator() {
|
||||||
@ -85,7 +84,6 @@ public class MapWorker extends PausableThread {
|
|||||||
@Override
|
@Override
|
||||||
protected int getThreadPriority() {
|
protected int getThreadPriority() {
|
||||||
return (Thread.NORM_PRIORITY + Thread.MIN_PRIORITY) / 3;
|
return (Thread.NORM_PRIORITY + Thread.MIN_PRIORITY) / 3;
|
||||||
// return mPrio;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -32,11 +32,13 @@ import java.util.concurrent.locks.ReentrantLock;
|
|||||||
import javax.microedition.khronos.egl.EGLConfig;
|
import javax.microedition.khronos.egl.EGLConfig;
|
||||||
import javax.microedition.khronos.opengles.GL10;
|
import javax.microedition.khronos.opengles.GL10;
|
||||||
|
|
||||||
import org.oscim.core.MapPosition;
|
|
||||||
import org.oscim.core.Tile;
|
import org.oscim.core.Tile;
|
||||||
import org.oscim.theme.RenderTheme;
|
import org.oscim.theme.RenderTheme;
|
||||||
import org.oscim.utils.GlUtils;
|
import org.oscim.utils.GlUtils;
|
||||||
|
import org.oscim.view.MapPosition;
|
||||||
import org.oscim.view.MapView;
|
import org.oscim.view.MapView;
|
||||||
|
import org.oscim.view.MapViewPosition;
|
||||||
|
import org.oscim.view.renderer.MapRenderer.TilesData;
|
||||||
|
|
||||||
import android.opengl.GLES20;
|
import android.opengl.GLES20;
|
||||||
import android.opengl.GLSurfaceView;
|
import android.opengl.GLSurfaceView;
|
||||||
@ -59,6 +61,10 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
static int CACHE_TILES = CACHE_TILES_MAX;
|
static int CACHE_TILES = CACHE_TILES_MAX;
|
||||||
|
|
||||||
private final MapView mMapView;
|
private final MapView mMapView;
|
||||||
|
private final MapViewPosition mMapViewPosition;
|
||||||
|
|
||||||
|
private static final MapPosition mMapPosition = new MapPosition();
|
||||||
|
|
||||||
private static ArrayList<VertexBufferObject> mVBOs;
|
private static ArrayList<VertexBufferObject> mVBOs;
|
||||||
|
|
||||||
private static int mWidth, mHeight;
|
private static int mWidth, mHeight;
|
||||||
@ -71,12 +77,8 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
private static int mBufferMemoryUsage;
|
private static int mBufferMemoryUsage;
|
||||||
|
|
||||||
private static float[] mMVPMatrix = new float[16];
|
private static float[] mMVPMatrix = new float[16];
|
||||||
private static float[] mRotateMatrix = new float[16];
|
|
||||||
private static float[] mTmpMatrix = new float[16];
|
|
||||||
private static float[] mTmp2Matrix = new float[16];
|
|
||||||
|
|
||||||
private static float[] mProjMatrix = new float[16];
|
private static float[] mProjMatrix = new float[16];
|
||||||
private static float[] mProjMatrixI = new float[16];
|
private static float[] mTileCoords = new float[8];
|
||||||
|
|
||||||
// mNextTiles is set by TileLoader and swapped with
|
// mNextTiles is set by TileLoader and swapped with
|
||||||
// mDrawTiles in onDrawFrame in GL thread.
|
// mDrawTiles in onDrawFrame in GL thread.
|
||||||
@ -86,8 +88,6 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
// changed. used in onDrawFrame to flip mNextTiles/mDrawTiles
|
// changed. used in onDrawFrame to flip mNextTiles/mDrawTiles
|
||||||
private static boolean mUpdateTiles;
|
private static boolean mUpdateTiles;
|
||||||
|
|
||||||
private static MapPosition mCurPosition;
|
|
||||||
|
|
||||||
private float[] mClearColor = null;
|
private float[] mClearColor = null;
|
||||||
|
|
||||||
// number of tiles drawn in one frame
|
// number of tiles drawn in one frame
|
||||||
@ -98,17 +98,6 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
// lock to synchronize Main- and GL-Thread
|
// lock to synchronize Main- and GL-Thread
|
||||||
static ReentrantLock tilelock = new ReentrantLock();
|
static ReentrantLock tilelock = new ReentrantLock();
|
||||||
|
|
||||||
// used for passing tiles to be rendered from TileLoader(Main-Thread) to
|
|
||||||
// GLThread
|
|
||||||
static class TilesData {
|
|
||||||
int cnt = 0;
|
|
||||||
final MapTile[] tiles;
|
|
||||||
|
|
||||||
TilesData(int numTiles) {
|
|
||||||
tiles = new MapTile[numTiles];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param mapView
|
* @param mapView
|
||||||
* the MapView
|
* the MapView
|
||||||
@ -117,34 +106,27 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
Log.d(TAG, "init MapRenderer");
|
Log.d(TAG, "init MapRenderer");
|
||||||
|
|
||||||
mMapView = mapView;
|
mMapView = mapView;
|
||||||
|
mMapViewPosition = mapView.getMapViewPosition();
|
||||||
|
// mMapPosition = new MapPosition();
|
||||||
|
|
||||||
|
mMapPosition.init();
|
||||||
|
|
||||||
Matrix.setIdentityM(mMVPMatrix, 0);
|
Matrix.setIdentityM(mMVPMatrix, 0);
|
||||||
|
|
||||||
mUpdateTiles = false;
|
mUpdateTiles = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* called by TileLoader when only position changed
|
|
||||||
*
|
|
||||||
* @param mapPosition
|
|
||||||
* current MapPosition
|
|
||||||
*/
|
|
||||||
static void updatePosition(MapPosition mapPosition) {
|
|
||||||
mCurPosition = mapPosition;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* called by TileLoader when list of active tiles changed
|
* called by TileLoader when list of active tiles changed
|
||||||
*
|
*
|
||||||
* @param mapPosition
|
|
||||||
* current MapPosition
|
|
||||||
* @param tiles
|
* @param tiles
|
||||||
* active tiles
|
* active tiles
|
||||||
* @return mNextTiles (the previously active tiles)
|
* @return mNextTiles (the previously active tiles)
|
||||||
*/
|
*/
|
||||||
static TilesData updateTiles(MapPosition mapPosition, TilesData tiles) {
|
static TilesData updateTiles(TilesData tiles) {
|
||||||
GLRenderer.tilelock.lock();
|
GLRenderer.tilelock.lock();
|
||||||
|
|
||||||
mCurPosition = mapPosition;
|
// mCurPosition = mapPosition;
|
||||||
|
|
||||||
// unlock previously active tiles
|
// unlock previously active tiles
|
||||||
for (int i = 0; i < mNextTiles.cnt; i++) {
|
for (int i = 0; i < mNextTiles.cnt; i++) {
|
||||||
@ -178,13 +160,13 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
// lock tiles (and their proxies) to not be removed from cache
|
// lock tiles (and their proxies) to not be removed from cache
|
||||||
for (int i = 0; i < mNextTiles.cnt; i++) {
|
for (int i = 0; i < mNextTiles.cnt; i++) {
|
||||||
MapTile t = mNextTiles.tiles[i];
|
MapTile t = mNextTiles.tiles[i];
|
||||||
if (!t.isActive)
|
if (!t.isLocked)
|
||||||
t.lock();
|
t.lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int j = 0; j < mDrawTiles.cnt; j++) {
|
for (int j = 0; j < mDrawTiles.cnt; j++) {
|
||||||
MapTile t = mDrawTiles.tiles[j];
|
MapTile t = mDrawTiles.tiles[j];
|
||||||
if (!t.isActive)
|
if (!t.isLocked)
|
||||||
t.lock();
|
t.lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -386,8 +368,9 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
CACHE_TILES -= 50;
|
CACHE_TILES -= 50;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isVisible(MapPosition mapPosition, MapTile tile) {
|
private static boolean isVisible(MapTile tile) {
|
||||||
float dx, dy, scale, div = 1;
|
float dx, dy, scale, div = 1;
|
||||||
|
MapPosition mapPosition = mMapPosition;
|
||||||
int diff = mapPosition.zoomLevel - tile.zoomLevel;
|
int diff = mapPosition.zoomLevel - tile.zoomLevel;
|
||||||
|
|
||||||
if (diff < 0)
|
if (diff < 0)
|
||||||
@ -407,7 +390,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
// this kindof works for typical screen aspect
|
// this kindof works for typical screen aspect
|
||||||
if (mRotate) {
|
if (mRotate) {
|
||||||
int ssize = mWidth > mHeight ? mWidth : mHeight;
|
int ssize = mWidth > mHeight ? mWidth : mHeight;
|
||||||
|
ssize += Tile.TILE_SIZE;
|
||||||
if (sy > ssize / 2 || sx > ssize / 2
|
if (sy > ssize / 2 || sx > ssize / 2
|
||||||
|| sx + size * scale < -ssize / 2
|
|| sx + size * scale < -ssize / 2
|
||||||
|| sy + size * scale < -ssize / 2) {
|
|| sy + size * scale < -ssize / 2) {
|
||||||
@ -429,10 +412,12 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
|
|
||||||
private static boolean mRotate = false;
|
private static boolean mRotate = false;
|
||||||
|
|
||||||
private static void setMatrix(float[] matrix, MapPosition mapPosition, MapTile tile,
|
private static void setMatrix(float[] matrix, MapTile tile,
|
||||||
float div, boolean project) {
|
float div, boolean project) {
|
||||||
float x, y, scale;
|
float x, y, scale;
|
||||||
|
|
||||||
|
MapPosition mapPosition = mMapPosition;
|
||||||
|
|
||||||
scale = mapPosition.scale / (div * COORD_MULTIPLIER);
|
scale = mapPosition.scale / (div * COORD_MULTIPLIER);
|
||||||
x = (float) (tile.pixelX - mapPosition.x * div);
|
x = (float) (tile.pixelX - mapPosition.x * div);
|
||||||
y = (float) (tile.pixelY - mapPosition.y * div);
|
y = (float) (tile.pixelY - mapPosition.y * div);
|
||||||
@ -443,48 +428,30 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
Matrix.scaleM(matrix, 0, scale, scale, 1);
|
Matrix.scaleM(matrix, 0, scale, scale, 1);
|
||||||
|
|
||||||
// translate relative to map center
|
// translate relative to map center
|
||||||
Matrix.translateM(matrix, 0,
|
Matrix.translateM(matrix, 0, x * COORD_MULTIPLIER,
|
||||||
x * COORD_MULTIPLIER,
|
-(y + Tile.TILE_SIZE) * COORD_MULTIPLIER, 0);
|
||||||
-(y + Tile.TILE_SIZE) * COORD_MULTIPLIER,
|
|
||||||
-1); // put on near plane
|
|
||||||
|
|
||||||
if (mRotate)
|
if (mRotate)
|
||||||
Matrix.multiplyMM(matrix, 0, mRotateMatrix, 0, matrix, 0);
|
Matrix.multiplyMM(matrix, 0, mapPosition.rotation, 0, matrix, 0);
|
||||||
|
|
||||||
if (project)
|
if (project)
|
||||||
Matrix.multiplyMM(matrix, 0, mProjMatrix, 0, matrix, 0);
|
Matrix.multiplyMM(matrix, 0, mProjMatrix, 0, matrix, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// private float[] mv = new float[4];
|
private static float scaleDiv(MapTile t) {
|
||||||
// private float[] mu = { 1, 1, -1, 1 };
|
float div = 1;
|
||||||
//
|
int diff = mMapPosition.zoomLevel - t.zoomLevel;
|
||||||
// private float[] mUnprojMatrix = new float[16];
|
if (diff < 0)
|
||||||
//
|
div = (1 << -diff);
|
||||||
// private void unproject(MapPosition pos, float x, float y) {
|
else if (diff > 0)
|
||||||
// mu[0] = x;
|
div = (1.0f / (1 << diff));
|
||||||
// mu[1] = y;
|
return div;
|
||||||
// mu[2] = -1;
|
}
|
||||||
//
|
|
||||||
// // add tilt
|
|
||||||
// Matrix.multiplyMV(mv, 0, mTmpMatrix, 0, mu, 0);
|
|
||||||
// // Log.d(TAG, ">> " + mv[0] + " " + mv[1] + " " + mv[2]);
|
|
||||||
//
|
|
||||||
// Matrix.multiplyMV(mv, 0, mUnprojMatrix, 0, mv, 0);
|
|
||||||
// float size = Tile.TILE_SIZE * pos.scale;
|
|
||||||
// if (mv[3] != 0) {
|
|
||||||
// float w = 1 / mv[3];
|
|
||||||
// float xx = Math.round(((mv[0] * w) / size) * 100) / 100f;
|
|
||||||
// float yy = Math.round(((mv[1] * w) / size) * 100) / 100f;
|
|
||||||
// Log.d(TAG, " " + xx + " " + yy);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDrawFrame(GL10 glUnused) {
|
public void onDrawFrame(GL10 glUnused) {
|
||||||
long start = 0;
|
long start = 0;
|
||||||
|
|
||||||
MapPosition mapPosition;
|
|
||||||
|
|
||||||
if (MapView.debugFrameTime)
|
if (MapView.debugFrameTime)
|
||||||
start = SystemClock.uptimeMillis();
|
start = SystemClock.uptimeMillis();
|
||||||
|
|
||||||
@ -498,66 +465,55 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
| GLES20.GL_STENCIL_BUFFER_BIT);
|
| GLES20.GL_STENCIL_BUFFER_BIT);
|
||||||
|
|
||||||
// get position and current tiles to draw
|
// get position and current tiles to draw
|
||||||
GLRenderer.tilelock.lock();
|
// mapPosition = mCurPosition;
|
||||||
mapPosition = mCurPosition;
|
|
||||||
if (mUpdateTiles) {
|
if (mUpdateTiles) {
|
||||||
|
GLRenderer.tilelock.lock();
|
||||||
TilesData tmp = mDrawTiles;
|
TilesData tmp = mDrawTiles;
|
||||||
mDrawTiles = mNextTiles;
|
mDrawTiles = mNextTiles;
|
||||||
mNextTiles = tmp;
|
mNextTiles = tmp;
|
||||||
mUpdateTiles = false;
|
mUpdateTiles = false;
|
||||||
}
|
|
||||||
GLRenderer.tilelock.unlock();
|
GLRenderer.tilelock.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
if (mDrawTiles == null)
|
if (mDrawTiles == null || mDrawTiles.cnt == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// if (mRotate != (mMapView.enableRotation || mMapView.enableCompass)) {
|
// MapPosition mapPosition =
|
||||||
// Matrix.setIdentityM(mMVPMatrix, 0);
|
// mMapView.getMapViewPosition().getMapPosition();
|
||||||
// mRotate = mMapView.enableRotation || mMapView.enableCompass;
|
|
||||||
// }
|
MapPosition mapPosition = mMapPosition;
|
||||||
|
boolean changed = mMapViewPosition.getMapPosition(mapPosition, mTileCoords);
|
||||||
|
|
||||||
|
int tileCnt = mDrawTiles.cnt;
|
||||||
|
MapTile[] tiles = mDrawTiles.tiles;
|
||||||
|
|
||||||
|
if (changed) {
|
||||||
|
for (int i = 0; i < tileCnt; i++)
|
||||||
|
tiles[i].isVisible = false;
|
||||||
|
|
||||||
|
// get relative zoom-level, tiles could not have been updated after
|
||||||
|
// zoom-level changed.
|
||||||
|
float div = scaleDiv(tiles[0]);
|
||||||
|
|
||||||
mRotate = mMapView.enableRotation || mMapView.enableCompass;
|
mRotate = mMapView.enableRotation || mMapView.enableCompass;
|
||||||
|
|
||||||
if (mRotate) {
|
float s = Tile.TILE_SIZE;
|
||||||
// rotate map
|
float scale = mapPosition.scale / div;
|
||||||
Matrix.setRotateM(mRotateMatrix, 0, mapPosition.angle, 0, 0, 1);
|
float px = (float) (mapPosition.x * div);
|
||||||
|
float py = (float) (mapPosition.y * div);
|
||||||
|
|
||||||
// tilt map
|
mTileCoords[0] = (px + mTileCoords[0] / scale) / s;
|
||||||
// mMapView.getMapViewPosition().mTilt;
|
mTileCoords[1] = (py - mTileCoords[1] / scale) / s;
|
||||||
|
mTileCoords[2] = (px + mTileCoords[2] / scale) / s;
|
||||||
|
mTileCoords[3] = (py - mTileCoords[3] / scale) / s;
|
||||||
|
mTileCoords[4] = (px + mTileCoords[4] / scale) / s;
|
||||||
|
mTileCoords[5] = (py - mTileCoords[5] / scale) / s;
|
||||||
|
mTileCoords[6] = (px + mTileCoords[6] / scale) / s;
|
||||||
|
mTileCoords[7] = (py - mTileCoords[7] / scale) / s;
|
||||||
|
|
||||||
float angle = mMapView.getMapViewPosition().mTilt / (mHeight / 2);
|
byte z = tiles[0].zoomLevel;
|
||||||
Matrix.setRotateM(mTmpMatrix, 0, -angle, 1, 0, 0);
|
ScanBox.scan(mTileCoords, mDrawTiles, 1 << z);
|
||||||
|
|
||||||
// move camera center back to map center
|
|
||||||
Matrix.translateM(mTmpMatrix, 0,
|
|
||||||
0, (float) Math.tan(Math.toRadians(angle)), 0);
|
|
||||||
|
|
||||||
// apply first rotation, then tilt
|
|
||||||
Matrix.multiplyMM(mRotateMatrix, 0, mTmpMatrix, 0, mRotateMatrix, 0);
|
|
||||||
|
|
||||||
// // get unproject matrix
|
|
||||||
// Matrix.setIdentityM(mTmp2Matrix, 0);
|
|
||||||
// float s = mapPosition.scale;
|
|
||||||
// Matrix.translateM(mTmp2Matrix, 0,
|
|
||||||
// (float) (mapPosition.x * s),
|
|
||||||
// (float) (mapPosition.y * s), 0);
|
|
||||||
//
|
|
||||||
// Matrix.multiplyMM(mTmp2Matrix, 0, mRotateMatrix, 0, mTmp2Matrix,
|
|
||||||
// 0);
|
|
||||||
//
|
|
||||||
// // Matrix.invertM(mTmpMatrix, 0, mTmp2Matrix, 0);
|
|
||||||
// // (AB)^-1 = B^-1*A^-1
|
|
||||||
// Matrix.multiplyMM(mUnprojMatrix, 0, mTmp2Matrix, 0, mProjMatrixI,
|
|
||||||
// 0);
|
|
||||||
//
|
|
||||||
// // set tilt of screen coords
|
|
||||||
// Matrix.setRotateM(mTmpMatrix, 0, -15, 1, 0, 0);
|
|
||||||
//
|
|
||||||
// // unproject(mapPosition, 0, 0);
|
|
||||||
// unproject(mapPosition, -1, -1); // top-left
|
|
||||||
// unproject(mapPosition, 1, -1); // top-right
|
|
||||||
// unproject(mapPosition, -1, 1); // bottom-left
|
|
||||||
// unproject(mapPosition, 1, 1); // bottom-right
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mUpdateColor && mClearColor != null) {
|
if (mUpdateColor && mClearColor != null) {
|
||||||
@ -566,9 +522,6 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
mUpdateColor = false;
|
mUpdateColor = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int tileCnt = mDrawTiles.cnt;
|
|
||||||
MapTile[] tiles = mDrawTiles.tiles;
|
|
||||||
|
|
||||||
uploadCnt = 0;
|
uploadCnt = 0;
|
||||||
int updateTextures = 0;
|
int updateTextures = 0;
|
||||||
|
|
||||||
@ -576,7 +529,9 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
for (int i = 0; i < tileCnt; i++) {
|
for (int i = 0; i < tileCnt; i++) {
|
||||||
MapTile tile = tiles[i];
|
MapTile tile = tiles[i];
|
||||||
|
|
||||||
if (!isVisible(mapPosition, tile))
|
// if (!isVisible(mapPosition, tile))
|
||||||
|
// continue;
|
||||||
|
if (!tile.isVisible)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (tile.texture == null && TextRenderer.drawToTexture(tile))
|
if (tile.texture == null && TextRenderer.drawToTexture(tile))
|
||||||
@ -616,14 +571,14 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
|
|
||||||
for (int i = 0; i < tileCnt; i++) {
|
for (int i = 0; i < tileCnt; i++) {
|
||||||
if (tiles[i].isVisible && tiles[i].isReady)
|
if (tiles[i].isVisible && tiles[i].isReady)
|
||||||
drawTile(mapPosition, tiles[i]);
|
drawTile(tiles[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// proxies are clipped to the region where nothing was drawn to depth
|
// proxies are clipped to the region where nothing was drawn to depth
|
||||||
// buffer. TODO draw all parent before grandparent
|
// buffer. TODO draw all parent before grandparent
|
||||||
for (int i = 0; i < tileCnt; i++) {
|
for (int i = 0; i < tileCnt; i++) {
|
||||||
if (tiles[i].isVisible && !tiles[i].isReady)
|
if (tiles[i].isVisible && !tiles[i].isReady)
|
||||||
drawProxyTile(mapPosition, tiles[i]);
|
drawProxyTile(tiles[i]);
|
||||||
}
|
}
|
||||||
// GlUtils.checkGlError("end draw");
|
// GlUtils.checkGlError("end draw");
|
||||||
|
|
||||||
@ -647,19 +602,32 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
else
|
else
|
||||||
TextRenderer.beginDraw(s, mProjMatrix);
|
TextRenderer.beginDraw(s, mProjMatrix);
|
||||||
|
|
||||||
// s = (float) 1.0 / COORD_MULTIPLIER;
|
|
||||||
// TextRenderer.beginDraw(s, mProjMatrix);
|
|
||||||
|
|
||||||
for (int i = 0; i < tileCnt; i++) {
|
for (int i = 0; i < tileCnt; i++) {
|
||||||
if (!tiles[i].isVisible || tiles[i].texture == null)
|
if (!tiles[i].isVisible || tiles[i].texture == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
setMatrix(mMVPMatrix, mapPosition, tiles[i], 1, false);
|
setMatrix(mMVPMatrix, tiles[i], 1, false);
|
||||||
TextRenderer.drawTile(tiles[i], mMVPMatrix);
|
TextRenderer.drawTile(tiles[i], mMVPMatrix);
|
||||||
}
|
}
|
||||||
TextRenderer.endDraw();
|
TextRenderer.endDraw();
|
||||||
|
|
||||||
// TODO call overlay renderer
|
// TODO call overlay renderer here
|
||||||
|
|
||||||
|
// s = 0.5f;
|
||||||
|
// mTileCoords[0] = -s;
|
||||||
|
// mTileCoords[1] = s;
|
||||||
|
// mTileCoords[2] = s;
|
||||||
|
// mTileCoords[3] = s;
|
||||||
|
// mTileCoords[4] = -s;
|
||||||
|
// mTileCoords[5] = -s;
|
||||||
|
// mTileCoords[6] = s;
|
||||||
|
// mTileCoords[7] = -s;
|
||||||
|
//
|
||||||
|
// Matrix.setIdentityM(mMVPMatrix, 0);
|
||||||
|
// // Matrix.scaleM(mMVPMatrix, 0, 0.99f, 0.99f, 1);
|
||||||
|
// // Matrix.multiplyMM(mMVPMatrix, 0, mRotateMatrix, 0, mMVPMatrix, 0);
|
||||||
|
// // Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mMVPMatrix, 0);
|
||||||
|
// PolygonRenderer.debugDraw(mMVPMatrix, mTileCoords);
|
||||||
|
|
||||||
if (MapView.debugFrameTime) {
|
if (MapView.debugFrameTime) {
|
||||||
GLES20.glFinish();
|
GLES20.glFinish();
|
||||||
@ -670,27 +638,26 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
// used to not draw a tile twice per frame...
|
// used to not draw a tile twice per frame...
|
||||||
private static byte mDrawSerial = 0;
|
private static byte mDrawSerial = 0;
|
||||||
|
|
||||||
private static void drawTile(MapPosition mapPosition, MapTile tile) {
|
private static void drawTile(MapTile tile) {
|
||||||
// draw parents only once
|
// draw parents only once
|
||||||
if (tile.lastDraw == mDrawSerial)
|
if (tile.lastDraw == mDrawSerial)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
float div = 1;
|
float div = scaleDiv(tile);
|
||||||
|
// float div = 1;
|
||||||
int diff = mapPosition.zoomLevel - tile.zoomLevel;
|
// int diff = mapPosition.zoomLevel - tile.zoomLevel;
|
||||||
|
// if (diff < 0)
|
||||||
if (diff < 0)
|
// div = (1 << -diff);
|
||||||
div = (1 << -diff);
|
// else if (diff > 0)
|
||||||
else if (diff > 0)
|
// div = (1.0f / (1 << diff));
|
||||||
div = (1.0f / (1 << diff));
|
|
||||||
|
|
||||||
tile.lastDraw = mDrawSerial;
|
tile.lastDraw = mDrawSerial;
|
||||||
|
|
||||||
int z = mapPosition.zoomLevel;
|
int z = mMapPosition.zoomLevel;
|
||||||
float s = mapPosition.scale;
|
float s = mMapPosition.scale;
|
||||||
float[] mvp = mMVPMatrix;
|
float[] mvp = mMVPMatrix;
|
||||||
|
|
||||||
setMatrix(mvp, mapPosition, tile, div, true);
|
setMatrix(mvp, tile, div, true);
|
||||||
|
|
||||||
GLES20.glPolygonOffset(0, mDrawCount++);
|
GLES20.glPolygonOffset(0, mDrawCount++);
|
||||||
|
|
||||||
@ -734,7 +701,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO could use tile.proxies here
|
// TODO could use tile.proxies here
|
||||||
private static boolean drawProxyChild(MapPosition mapPosition, MapTile tile) {
|
private static boolean drawProxyChild(MapTile tile) {
|
||||||
int drawn = 0;
|
int drawn = 0;
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
if (tile.rel.child[i] == null)
|
if (tile.rel.child[i] == null)
|
||||||
@ -744,13 +711,13 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
if (c == null)
|
if (c == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!isVisible(mapPosition, c)) {
|
if (!isVisible(c)) {
|
||||||
drawn++;
|
drawn++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c.isReady) {
|
if (c.isReady) {
|
||||||
drawTile(mapPosition, c);
|
drawTile(c);
|
||||||
drawn++;
|
drawn++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -758,17 +725,17 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO could use tile.proxies here
|
// TODO could use tile.proxies here
|
||||||
private static void drawProxyTile(MapPosition mapPosition, MapTile tile) {
|
private static void drawProxyTile(MapTile tile) {
|
||||||
int diff = mapPosition.zoomLevel - tile.zoomLevel;
|
int diff = mMapPosition.zoomLevel - tile.zoomLevel;
|
||||||
|
|
||||||
boolean drawn = false;
|
boolean drawn = false;
|
||||||
if (mapPosition.scale > 1.5f || diff < 0) {
|
if (mMapPosition.scale > 1.5f || diff < 0) {
|
||||||
// prefer drawing children
|
// prefer drawing children
|
||||||
if (!drawProxyChild(mapPosition, tile)) {
|
if (!drawProxyChild(tile)) {
|
||||||
if ((tile.proxies & MapTile.PROXY_PARENT) != 0) {
|
if ((tile.proxies & MapTile.PROXY_PARENT) != 0) {
|
||||||
MapTile t = tile.rel.parent.tile;
|
MapTile t = tile.rel.parent.tile;
|
||||||
if (t.isReady) {
|
if (t.isReady) {
|
||||||
drawTile(mapPosition, t);
|
drawTile(t);
|
||||||
drawn = true;
|
drawn = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -776,7 +743,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
if (!drawn && (tile.proxies & MapTile.PROXY_GRAMPA) != 0) {
|
if (!drawn && (tile.proxies & MapTile.PROXY_GRAMPA) != 0) {
|
||||||
MapTile t = tile.rel.parent.parent.tile;
|
MapTile t = tile.rel.parent.parent.tile;
|
||||||
if (t.isReady)
|
if (t.isReady)
|
||||||
drawTile(mapPosition, t);
|
drawTile(t);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -785,14 +752,14 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
MapTile t = tile.rel.parent.tile;
|
MapTile t = tile.rel.parent.tile;
|
||||||
|
|
||||||
if (t != null && t.isReady) {
|
if (t != null && t.isReady) {
|
||||||
drawTile(mapPosition, t);
|
drawTile(t);
|
||||||
|
|
||||||
} else if (!drawProxyChild(mapPosition, tile)) {
|
} else if (!drawProxyChild(tile)) {
|
||||||
|
|
||||||
if ((tile.proxies & MapTile.PROXY_GRAMPA) != 0) {
|
if ((tile.proxies & MapTile.PROXY_GRAMPA) != 0) {
|
||||||
t = tile.rel.parent.parent.tile;
|
t = tile.rel.parent.parent.tile;
|
||||||
if (t.isReady)
|
if (t.isReady)
|
||||||
drawTile(mapPosition, t);
|
drawTile(t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -814,14 +781,18 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
|
|
||||||
// Matrix.orthoM(mProjMatrix, 0, -0.5f / mAspect, 0.5f / mAspect, -0.5f,
|
// Matrix.orthoM(mProjMatrix, 0, -0.5f / mAspect, 0.5f / mAspect, -0.5f,
|
||||||
// 0.5f, -1, 1);
|
// 0.5f, -1, 1);
|
||||||
|
float s = 0.5f;
|
||||||
|
Matrix.frustumM(mProjMatrix, 0, -s * width, s * width,
|
||||||
|
-s * height, s * height, 1, 2);
|
||||||
|
Matrix.translateM(mProjMatrix, 0, 0, 0, -1);
|
||||||
|
|
||||||
Matrix.frustumM(mProjMatrix, 0,
|
// Matrix.invertM(mProjMatrixI, 0, mProjMatrix, 0);
|
||||||
-0.5f * width,
|
|
||||||
0.5f * width,
|
|
||||||
-0.5f * height,
|
|
||||||
0.5f * height, 1, 2);
|
|
||||||
|
|
||||||
Matrix.invertM(mProjMatrixI, 0, mProjMatrix, 0);
|
// use this to scale only the view to see which tiles are rendered
|
||||||
|
// s = 1.0f;
|
||||||
|
// Matrix.frustumM(mProjMatrix, 0, -s * width, s * width,
|
||||||
|
// -s * height, s * height, 1, 2);
|
||||||
|
// Matrix.translateM(mProjMatrix, 0, 0, 0, -1);
|
||||||
|
|
||||||
// set to zero: we modify the z value with polygon-offset for clipping
|
// set to zero: we modify the z value with polygon-offset for clipping
|
||||||
mProjMatrix[10] = 0;
|
mProjMatrix[10] = 0;
|
||||||
@ -869,6 +840,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
mMapView.redrawMap();
|
mMapView.redrawMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME this is a bit too spaghetti
|
||||||
void clearTiles(int numTiles) {
|
void clearTiles(int numTiles) {
|
||||||
mDrawTiles = new TilesData(numTiles);
|
mDrawTiles = new TilesData(numTiles);
|
||||||
mNextTiles = new TilesData(numTiles);
|
mNextTiles = new TilesData(numTiles);
|
||||||
|
@ -40,8 +40,8 @@ class LineLayer {
|
|||||||
boolean isOutline;
|
boolean isOutline;
|
||||||
int layer;
|
int layer;
|
||||||
|
|
||||||
ShortItem pool;
|
VertexPoolItem pool;
|
||||||
protected ShortItem curItem;
|
protected VertexPoolItem curItem;
|
||||||
|
|
||||||
// number of vertices this layer holds
|
// number of vertices this layer holds
|
||||||
int verticesCnt;
|
int verticesCnt;
|
||||||
@ -85,10 +85,10 @@ class LineLayer {
|
|||||||
squared = true;
|
squared = true;
|
||||||
|
|
||||||
if (pool == null) {
|
if (pool == null) {
|
||||||
pool = curItem = ShortPool.get();
|
pool = curItem = VertexPool.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
ShortItem si = curItem;
|
VertexPoolItem si = curItem;
|
||||||
short v[] = si.vertices;
|
short v[] = si.vertices;
|
||||||
int opos = si.used;
|
int opos = si.used;
|
||||||
|
|
||||||
@ -137,8 +137,8 @@ class LineLayer {
|
|||||||
ux = -vy;
|
ux = -vy;
|
||||||
uy = vx;
|
uy = vx;
|
||||||
|
|
||||||
if (opos == ShortItem.SIZE) {
|
if (opos == VertexPoolItem.SIZE) {
|
||||||
si = si.next = ShortPool.get();
|
si = si.next = VertexPool.get();
|
||||||
v = si.vertices;
|
v = si.vertices;
|
||||||
opos = 0;
|
opos = 0;
|
||||||
}
|
}
|
||||||
@ -151,8 +151,8 @@ class LineLayer {
|
|||||||
|
|
||||||
boolean outside = (x < tmin || x > tmax || y < tmin || y > tmax);
|
boolean outside = (x < tmin || x > tmax || y < tmin || y > tmax);
|
||||||
|
|
||||||
if (opos == ShortItem.SIZE) {
|
if (opos == VertexPoolItem.SIZE) {
|
||||||
si = si.next = ShortPool.get();
|
si = si.next = VertexPool.get();
|
||||||
v = si.vertices;
|
v = si.vertices;
|
||||||
opos = 0;
|
opos = 0;
|
||||||
}
|
}
|
||||||
@ -170,8 +170,8 @@ class LineLayer {
|
|||||||
v[opos++] = dx;
|
v[opos++] = dx;
|
||||||
v[opos++] = dy;
|
v[opos++] = dy;
|
||||||
|
|
||||||
if (opos == ShortItem.SIZE) {
|
if (opos == VertexPoolItem.SIZE) {
|
||||||
si = si.next = ShortPool.get();
|
si = si.next = VertexPool.get();
|
||||||
v = si.vertices;
|
v = si.vertices;
|
||||||
opos = 0;
|
opos = 0;
|
||||||
}
|
}
|
||||||
@ -181,8 +181,8 @@ class LineLayer {
|
|||||||
v[opos++] = dx;
|
v[opos++] = dx;
|
||||||
v[opos++] = dy;
|
v[opos++] = dy;
|
||||||
|
|
||||||
if (opos == ShortItem.SIZE) {
|
if (opos == VertexPoolItem.SIZE) {
|
||||||
si = si.next = ShortPool.get();
|
si = si.next = VertexPool.get();
|
||||||
v = si.vertices;
|
v = si.vertices;
|
||||||
opos = 0;
|
opos = 0;
|
||||||
}
|
}
|
||||||
@ -195,8 +195,8 @@ class LineLayer {
|
|||||||
v[opos++] = (short) (2 | ddx & DIR_MASK);
|
v[opos++] = (short) (2 | ddx & DIR_MASK);
|
||||||
v[opos++] = (short) (2 | ddy & DIR_MASK);
|
v[opos++] = (short) (2 | ddy & DIR_MASK);
|
||||||
|
|
||||||
if (opos == ShortItem.SIZE) {
|
if (opos == VertexPoolItem.SIZE) {
|
||||||
si = si.next = ShortPool.get();
|
si = si.next = VertexPool.get();
|
||||||
v = si.vertices;
|
v = si.vertices;
|
||||||
opos = 0;
|
opos = 0;
|
||||||
}
|
}
|
||||||
@ -210,8 +210,8 @@ class LineLayer {
|
|||||||
v[opos++] = (short) (0 | ddx & DIR_MASK);
|
v[opos++] = (short) (0 | ddx & DIR_MASK);
|
||||||
v[opos++] = (short) (1 | ddy & DIR_MASK);
|
v[opos++] = (short) (1 | ddy & DIR_MASK);
|
||||||
|
|
||||||
if (opos == ShortItem.SIZE) {
|
if (opos == VertexPoolItem.SIZE) {
|
||||||
si = si.next = ShortPool.get();
|
si = si.next = VertexPool.get();
|
||||||
v = si.vertices;
|
v = si.vertices;
|
||||||
opos = 0;
|
opos = 0;
|
||||||
}
|
}
|
||||||
@ -248,8 +248,8 @@ class LineLayer {
|
|||||||
v[opos++] = dx;
|
v[opos++] = dx;
|
||||||
v[opos++] = dy;
|
v[opos++] = dy;
|
||||||
|
|
||||||
if (opos == ShortItem.SIZE) {
|
if (opos == VertexPoolItem.SIZE) {
|
||||||
si = si.next = ShortPool.get();
|
si = si.next = VertexPool.get();
|
||||||
v = si.vertices;
|
v = si.vertices;
|
||||||
opos = 0;
|
opos = 0;
|
||||||
}
|
}
|
||||||
@ -259,8 +259,8 @@ class LineLayer {
|
|||||||
v[opos++] = dx;
|
v[opos++] = dx;
|
||||||
v[opos++] = dy;
|
v[opos++] = dy;
|
||||||
|
|
||||||
if (opos == ShortItem.SIZE) {
|
if (opos == VertexPoolItem.SIZE) {
|
||||||
si = si.next = ShortPool.get();
|
si = si.next = VertexPool.get();
|
||||||
v = si.vertices;
|
v = si.vertices;
|
||||||
opos = 0;
|
opos = 0;
|
||||||
}
|
}
|
||||||
@ -334,8 +334,8 @@ class LineLayer {
|
|||||||
ddx = (int) (ux * DIR_SCALE);
|
ddx = (int) (ux * DIR_SCALE);
|
||||||
ddy = (int) (uy * DIR_SCALE);
|
ddy = (int) (uy * DIR_SCALE);
|
||||||
|
|
||||||
if (opos == ShortItem.SIZE) {
|
if (opos == VertexPoolItem.SIZE) {
|
||||||
si = si.next = ShortPool.get();
|
si = si.next = VertexPool.get();
|
||||||
v = si.vertices;
|
v = si.vertices;
|
||||||
opos = 0;
|
opos = 0;
|
||||||
}
|
}
|
||||||
@ -345,8 +345,8 @@ class LineLayer {
|
|||||||
v[opos++] = (short) (0 | ddx & DIR_MASK);
|
v[opos++] = (short) (0 | ddx & DIR_MASK);
|
||||||
v[opos++] = (short) (1 | ddy & DIR_MASK);
|
v[opos++] = (short) (1 | ddy & DIR_MASK);
|
||||||
|
|
||||||
if (opos == ShortItem.SIZE) {
|
if (opos == VertexPoolItem.SIZE) {
|
||||||
si = si.next = ShortPool.get();
|
si = si.next = VertexPool.get();
|
||||||
v = si.vertices;
|
v = si.vertices;
|
||||||
opos = 0;
|
opos = 0;
|
||||||
}
|
}
|
||||||
@ -375,8 +375,8 @@ class LineLayer {
|
|||||||
|
|
||||||
outside = (x < tmin || x > tmax || y < tmin || y > tmax);
|
outside = (x < tmin || x > tmax || y < tmin || y > tmax);
|
||||||
|
|
||||||
if (opos == ShortItem.SIZE) {
|
if (opos == VertexPoolItem.SIZE) {
|
||||||
si.next = ShortPool.get();
|
si.next = VertexPool.get();
|
||||||
si = si.next;
|
si = si.next;
|
||||||
opos = 0;
|
opos = 0;
|
||||||
v = si.vertices;
|
v = si.vertices;
|
||||||
@ -394,8 +394,8 @@ class LineLayer {
|
|||||||
v[opos++] = (short) (0 | ddx & DIR_MASK);
|
v[opos++] = (short) (0 | ddx & DIR_MASK);
|
||||||
v[opos++] = (short) (1 | ddy & DIR_MASK);
|
v[opos++] = (short) (1 | ddy & DIR_MASK);
|
||||||
|
|
||||||
if (opos == ShortItem.SIZE) {
|
if (opos == VertexPoolItem.SIZE) {
|
||||||
si = si.next = ShortPool.get();
|
si = si.next = VertexPool.get();
|
||||||
v = si.vertices;
|
v = si.vertices;
|
||||||
opos = 0;
|
opos = 0;
|
||||||
}
|
}
|
||||||
@ -405,8 +405,8 @@ class LineLayer {
|
|||||||
v[opos++] = (short) (2 | -ddx & DIR_MASK);
|
v[opos++] = (short) (2 | -ddx & DIR_MASK);
|
||||||
v[opos++] = (short) (1 | -ddy & DIR_MASK);
|
v[opos++] = (short) (1 | -ddy & DIR_MASK);
|
||||||
|
|
||||||
if (opos == ShortItem.SIZE) {
|
if (opos == VertexPoolItem.SIZE) {
|
||||||
si = si.next = ShortPool.get();
|
si = si.next = VertexPool.get();
|
||||||
v = si.vertices;
|
v = si.vertices;
|
||||||
opos = 0;
|
opos = 0;
|
||||||
}
|
}
|
||||||
@ -422,8 +422,8 @@ class LineLayer {
|
|||||||
v[opos++] = dx;
|
v[opos++] = dx;
|
||||||
v[opos++] = dy;
|
v[opos++] = dy;
|
||||||
|
|
||||||
if (opos == ShortItem.SIZE) {
|
if (opos == VertexPoolItem.SIZE) {
|
||||||
si = si.next = ShortPool.get();
|
si = si.next = VertexPool.get();
|
||||||
v = si.vertices;
|
v = si.vertices;
|
||||||
opos = 0;
|
opos = 0;
|
||||||
}
|
}
|
||||||
@ -439,8 +439,8 @@ class LineLayer {
|
|||||||
v[opos++] = dx;
|
v[opos++] = dx;
|
||||||
v[opos++] = dy;
|
v[opos++] = dy;
|
||||||
|
|
||||||
if (opos == ShortItem.SIZE) {
|
if (opos == VertexPoolItem.SIZE) {
|
||||||
si = si.next = ShortPool.get();
|
si = si.next = VertexPool.get();
|
||||||
v = si.vertices;
|
v = si.vertices;
|
||||||
opos = 0;
|
opos = 0;
|
||||||
}
|
}
|
||||||
@ -470,8 +470,8 @@ class LineLayer {
|
|||||||
v[opos++] = (short) (0 | ddx & DIR_MASK);
|
v[opos++] = (short) (0 | ddx & DIR_MASK);
|
||||||
v[opos++] = (short) (1 | ddy & DIR_MASK);
|
v[opos++] = (short) (1 | ddy & DIR_MASK);
|
||||||
|
|
||||||
if (opos == ShortItem.SIZE) {
|
if (opos == VertexPoolItem.SIZE) {
|
||||||
si = si.next = ShortPool.get();
|
si = si.next = VertexPool.get();
|
||||||
v = si.vertices;
|
v = si.vertices;
|
||||||
opos = 0;
|
opos = 0;
|
||||||
}
|
}
|
||||||
@ -487,8 +487,8 @@ class LineLayer {
|
|||||||
v[opos++] = dx;
|
v[opos++] = dx;
|
||||||
v[opos++] = dy;
|
v[opos++] = dy;
|
||||||
|
|
||||||
if (opos == ShortItem.SIZE) {
|
if (opos == VertexPoolItem.SIZE) {
|
||||||
si = si.next = ShortPool.get();
|
si = si.next = VertexPool.get();
|
||||||
v = si.vertices;
|
v = si.vertices;
|
||||||
opos = 0;
|
opos = 0;
|
||||||
}
|
}
|
||||||
|
@ -183,18 +183,18 @@ class LineRenderer {
|
|||||||
|
|
||||||
static void compileLayerData(LineLayer layers, ShortBuffer sbuf) {
|
static void compileLayerData(LineLayer layers, ShortBuffer sbuf) {
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
ShortItem last = null, items = null;
|
VertexPoolItem last = null, items = null;
|
||||||
|
|
||||||
for (LineLayer l = layers; l != null; l = l.next) {
|
for (LineLayer l = layers; l != null; l = l.next) {
|
||||||
if (l.isOutline)
|
if (l.isOutline)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (ShortItem item = l.pool; item != null; item = item.next) {
|
for (VertexPoolItem item = l.pool; item != null; item = item.next) {
|
||||||
|
|
||||||
if (item.next == null) {
|
if (item.next == null) {
|
||||||
sbuf.put(item.vertices, 0, item.used);
|
sbuf.put(item.vertices, 0, item.used);
|
||||||
} else {
|
} else {
|
||||||
// item.used = ShortItem.SIZE;
|
// item.used = VertexPoolItem.SIZE;
|
||||||
sbuf.put(item.vertices);
|
sbuf.put(item.vertices);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -213,7 +213,7 @@ class LineRenderer {
|
|||||||
l.curItem = null;
|
l.curItem = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
ShortPool.add(items);
|
VertexPool.add(items);
|
||||||
}
|
}
|
||||||
|
|
||||||
// @SuppressLint("UseValueOf")
|
// @SuppressLint("UseValueOf")
|
||||||
@ -310,7 +310,7 @@ class LineRenderer {
|
|||||||
static void clear(LineLayer layer) {
|
static void clear(LineLayer layer) {
|
||||||
for (LineLayer l = layer; l != null; l = l.next) {
|
for (LineLayer l = layer; l != null; l = l.next) {
|
||||||
if (l.pool != null) {
|
if (l.pool != null) {
|
||||||
ShortPool.add(l.pool);
|
VertexPool.add(l.pool);
|
||||||
l.pool = null;
|
l.pool = null;
|
||||||
l.curItem = null;
|
l.curItem = null;
|
||||||
}
|
}
|
||||||
|
@ -17,21 +17,21 @@ package org.oscim.view.renderer;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
import org.oscim.core.MapPosition;
|
|
||||||
import org.oscim.core.MercatorProjection;
|
import org.oscim.core.MercatorProjection;
|
||||||
import org.oscim.core.Tile;
|
import org.oscim.core.Tile;
|
||||||
import org.oscim.database.MapInfo;
|
import org.oscim.database.MapInfo;
|
||||||
import org.oscim.theme.RenderTheme;
|
import org.oscim.theme.RenderTheme;
|
||||||
import org.oscim.utils.GlConfigChooser;
|
import org.oscim.utils.GlConfigChooser;
|
||||||
|
import org.oscim.view.MapPosition;
|
||||||
import org.oscim.view.MapView;
|
import org.oscim.view.MapView;
|
||||||
import org.oscim.view.generator.JobTile;
|
import org.oscim.view.generator.JobTile;
|
||||||
import org.oscim.view.renderer.GLRenderer.TilesData;
|
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.opengl.GLSurfaceView;
|
import android.opengl.GLSurfaceView;
|
||||||
import android.util.FloatMath;
|
import android.util.FloatMath;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
// FIXME to many 'Renderer', this one needs a better name.. TileLoader?
|
||||||
public class MapRenderer extends GLSurfaceView {
|
public class MapRenderer extends GLSurfaceView {
|
||||||
private final static String TAG = "MapRenderer";
|
private final static String TAG = "MapRenderer";
|
||||||
private GLRenderer mRenderer;
|
private GLRenderer mRenderer;
|
||||||
@ -45,7 +45,7 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
|
|
||||||
// all tiles currently referenced
|
// all tiles currently referenced
|
||||||
private static ArrayList<MapTile> mTiles;
|
private static ArrayList<MapTile> mTiles;
|
||||||
// private static ArrayList<MapTile> mTilesActive;
|
|
||||||
// tiles that have new data to upload, see passTile()
|
// tiles that have new data to upload, see passTile()
|
||||||
private static ArrayList<MapTile> mTilesLoaded;
|
private static ArrayList<MapTile> mTilesLoaded;
|
||||||
|
|
||||||
@ -59,9 +59,20 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
// private static MapPosition mCurPosition, mDrawPosition;
|
// private static MapPosition mCurPosition, mDrawPosition;
|
||||||
private static int mWidth = 0, mHeight = 0;
|
private static int mWidth = 0, mHeight = 0;
|
||||||
|
|
||||||
|
// used for passing tiles to be rendered from TileLoader(Main-Thread) to
|
||||||
|
// GLThread
|
||||||
|
static final class TilesData {
|
||||||
|
int cnt = 0;
|
||||||
|
final MapTile[] tiles;
|
||||||
|
|
||||||
|
TilesData(int numTiles) {
|
||||||
|
tiles = new MapTile[numTiles];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static TilesData mCurrentTiles;
|
private static TilesData mCurrentTiles;
|
||||||
|
|
||||||
// map zoom-level to available zoom-levels in MapDatabase
|
// maps zoom-level to available zoom-levels in MapDatabase
|
||||||
// e.g. 16->16, 15->16, 14->13, 13->13, 12->13,....
|
// e.g. 16->16, 15->16, 14->13, 13->13, 12->13,....
|
||||||
private static int[] mZoomLevels;
|
private static int[] mZoomLevels;
|
||||||
|
|
||||||
@ -85,7 +96,7 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
mTiles = new ArrayList<MapTile>();
|
mTiles = new ArrayList<MapTile>();
|
||||||
mTilesLoaded = new ArrayList<MapTile>(30);
|
mTilesLoaded = new ArrayList<MapTile>(30);
|
||||||
|
|
||||||
ShortPool.init();
|
VertexPool.init();
|
||||||
QuadTree.init();
|
QuadTree.init();
|
||||||
|
|
||||||
mInitial = true;
|
mInitial = true;
|
||||||
@ -97,13 +108,10 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
* loading by TileGenerator class
|
* loading by TileGenerator class
|
||||||
*
|
*
|
||||||
* @param clear
|
* @param clear
|
||||||
* ...
|
* whether to clear and reload all tiles
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public synchronized void updateMap(boolean clear) {
|
public synchronized void updateMap(boolean clear) {
|
||||||
|
|
||||||
boolean changedPos = false;
|
boolean changedPos = false;
|
||||||
boolean changedZoom = false;
|
|
||||||
|
|
||||||
if (mMapView == null)
|
if (mMapView == null)
|
||||||
return;
|
return;
|
||||||
@ -155,24 +163,20 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
|
|
||||||
int zdir = 0;
|
int zdir = 0;
|
||||||
if (mInitial || mPrevZoom != zoomLevel) {
|
if (mInitial || mPrevZoom != zoomLevel) {
|
||||||
changedZoom = true;
|
|
||||||
mPrevScale = scale;
|
|
||||||
}
|
|
||||||
else if (tileX != mTileX || tileY != mTileY) {
|
|
||||||
if (mPrevScale - scale > 0 && scale > 1.2)
|
|
||||||
zdir = 1;
|
|
||||||
mPrevScale = scale;
|
|
||||||
changedPos = true;
|
changedPos = true;
|
||||||
}
|
|
||||||
else if (mPrevScale - scale > 0.2 || mPrevScale - scale < -0.2) {
|
} else if (tileX != mTileX || tileY != mTileY) {
|
||||||
|
if (mPrevScale - scale > 0 && scale > 1.2)
|
||||||
|
zdir = 1;
|
||||||
|
changedPos = true;
|
||||||
|
|
||||||
|
} else if (mPrevScale - scale > 0.2 || mPrevScale - scale < -0.2) {
|
||||||
if (mPrevScale - scale > 0 && scale > 1.2)
|
if (mPrevScale - scale > 0 && scale > 1.2)
|
||||||
zdir = 1;
|
zdir = 1;
|
||||||
mPrevScale = scale;
|
|
||||||
changedPos = true;
|
changedPos = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mInitial) {
|
if (mInitial) {
|
||||||
// mCurPosition = mapPosition;
|
|
||||||
mInitial = false;
|
mInitial = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,30 +184,19 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
mTileY = tileY;
|
mTileY = tileY;
|
||||||
mPrevZoom = zoomLevel;
|
mPrevZoom = zoomLevel;
|
||||||
|
|
||||||
GLRenderer.updatePosition(mapPosition);
|
// GLRenderer.updatePosition(mapPosition);
|
||||||
|
|
||||||
if (!MapView.debugFrameTime)
|
if (!MapView.debugFrameTime)
|
||||||
requestRender();
|
requestRender();
|
||||||
|
|
||||||
if (changedZoom || changedPos) {
|
if (changedPos) {
|
||||||
// need to update visible list first when zoom level changes
|
mPrevScale = scale;
|
||||||
// as scaling is relative to the tiles of current zoom-level
|
|
||||||
updateVisibleList(mapPosition, zdir);
|
updateVisibleList(mapPosition, zdir);
|
||||||
|
|
||||||
if (!MapView.debugFrameTime)
|
if (!MapView.debugFrameTime)
|
||||||
requestRender();
|
requestRender();
|
||||||
}
|
|
||||||
// else {
|
|
||||||
// // pass new position to glThread
|
|
||||||
// GLRenderer.updatePosition(mapPosition);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (!MapView.debugFrameTime)
|
|
||||||
// requestRender();
|
|
||||||
|
|
||||||
// if (changedPos)
|
|
||||||
// updateVisibleList(mapPosition, zdir);
|
|
||||||
|
|
||||||
if (changedPos || changedZoom) {
|
|
||||||
int remove = mTiles.size() - GLRenderer.CACHE_TILES;
|
int remove = mTiles.size() - GLRenderer.CACHE_TILES;
|
||||||
if (remove > 50)
|
if (remove > 50)
|
||||||
limitCache(mapPosition, remove);
|
limitCache(mapPosition, remove);
|
||||||
@ -256,15 +249,15 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
// check MapDatabase zoom-level-mapping
|
// check MapDatabase zoom-level-mapping
|
||||||
if (mZoomLevels[zoomLevel] == 0) {
|
if (mZoomLevels[zoomLevel] == 0) {
|
||||||
mCurrentTiles.cnt = 0;
|
mCurrentTiles.cnt = 0;
|
||||||
mCurrentTiles = GLRenderer.updateTiles(mapPosition, mCurrentTiles);
|
mCurrentTiles = GLRenderer.updateTiles(mCurrentTiles);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mZoomLevels[zoomLevel] > zoomLevel) {
|
if (mZoomLevels[zoomLevel] > zoomLevel) {
|
||||||
fetchChildren = true;
|
fetchChildren = true;
|
||||||
fetchProxy = true;
|
fetchProxy = true;
|
||||||
}
|
|
||||||
else if (mZoomLevels[zoomLevel] < zoomLevel) {
|
} else if (mZoomLevels[zoomLevel] < zoomLevel) {
|
||||||
fetchParent = true;
|
fetchParent = true;
|
||||||
fetchProxy = true;
|
fetchProxy = true;
|
||||||
}
|
}
|
||||||
@ -285,12 +278,12 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
mTiles.add(tile);
|
mTiles.add(tile);
|
||||||
}
|
}
|
||||||
|
|
||||||
mCurrentTiles.tiles[tiles++] = tile;
|
if (!fetchProxy && !tile.isActive()) {
|
||||||
|
|
||||||
if (!fetchProxy && !(tile.isLoading || tile.newData || tile.isReady)) {
|
|
||||||
mJobList.add(tile);
|
mJobList.add(tile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mCurrentTiles.tiles[tiles++] = tile;
|
||||||
|
|
||||||
if (fetchChildren) {
|
if (fetchChildren) {
|
||||||
byte z = (byte) (zoomLevel + 1);
|
byte z = (byte) (zoomLevel + 1);
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
@ -306,7 +299,7 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
mTiles.add(c);
|
mTiles.add(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(c.isLoading || c.newData || c.isReady)) {
|
if (!c.isActive()) {
|
||||||
mJobList.add(c);
|
mJobList.add(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -314,18 +307,18 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
|
|
||||||
if (fetchParent || (!fetchProxy && zdir > 0 && zoomLevel > 0)) {
|
if (fetchParent || (!fetchProxy && zdir > 0 && zoomLevel > 0)) {
|
||||||
// prefetch parent
|
// prefetch parent
|
||||||
MapTile parent = tile.rel.parent.tile;
|
MapTile p = tile.rel.parent.tile;
|
||||||
|
|
||||||
if (parent == null) {
|
if (p == null) {
|
||||||
parent = new MapTile(xx >> 1, yy >> 1, (byte) (zoomLevel - 1));
|
p = new MapTile(xx >> 1, yy >> 1, (byte) (zoomLevel - 1));
|
||||||
|
|
||||||
QuadTree.add(parent);
|
QuadTree.add(p);
|
||||||
mTiles.add(parent);
|
mTiles.add(p);
|
||||||
}
|
mJobList.add(p);
|
||||||
|
|
||||||
if (!(parent.isLoading || parent.isReady || parent.newData)) {
|
} else if (!p.isActive()) {
|
||||||
if (!mJobList.contains(parent))
|
if (!mJobList.contains(p))
|
||||||
mJobList.add(parent);
|
mJobList.add(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -333,7 +326,7 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
|
|
||||||
// pass new tile list to glThread
|
// pass new tile list to glThread
|
||||||
mCurrentTiles.cnt = tiles;
|
mCurrentTiles.cnt = tiles;
|
||||||
mCurrentTiles = GLRenderer.updateTiles(mapPosition, mCurrentTiles);
|
mCurrentTiles = GLRenderer.updateTiles(mCurrentTiles);
|
||||||
|
|
||||||
// note: this sets isLoading == true for all job tiles
|
// note: this sets isLoading == true for all job tiles
|
||||||
if (mJobList.size() > 0) {
|
if (mJobList.size() > 0) {
|
||||||
@ -366,8 +359,7 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
QuadTree.remove(t);
|
QuadTree.remove(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void updateTileDistances(ArrayList<?> tiles,
|
private static void updateTileDistances(ArrayList<?> tiles, MapPosition mapPosition) {
|
||||||
MapPosition mapPosition) {
|
|
||||||
int h = (Tile.TILE_SIZE >> 1);
|
int h = (Tile.TILE_SIZE >> 1);
|
||||||
byte zoom = mapPosition.zoomLevel;
|
byte zoom = mapPosition.zoomLevel;
|
||||||
long x = (long) mapPosition.x;
|
long x = (long) mapPosition.x;
|
||||||
@ -422,18 +414,17 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
|
|
||||||
// remove orphaned tiles
|
// remove orphaned tiles
|
||||||
for (int i = 0; i < size;) {
|
for (int i = 0; i < size;) {
|
||||||
MapTile cur = mTiles.get(i);
|
MapTile t = mTiles.get(i);
|
||||||
// make sure tile cannot be used by GL or MapWorker Thread
|
// make sure tile cannot be used by GL or MapWorker Thread
|
||||||
if (!cur.isLocked() && !cur.isLoading && !cur.newData && !cur.isReady) {
|
if (t.isLocked() || t.isActive()) {
|
||||||
|
i++;
|
||||||
clearTile(cur);
|
} else {
|
||||||
|
// Log.d(TAG, "remove empty tile" + cur);
|
||||||
|
clearTile(t);
|
||||||
mTiles.remove(i);
|
mTiles.remove(i);
|
||||||
removes--;
|
removes--;
|
||||||
size--;
|
size--;
|
||||||
// Log.d(TAG, "remove empty tile" + cur);
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Log.d(TAG, "remove tiles: " + removes + " " + size);
|
// Log.d(TAG, "remove tiles: " + removes + " " + size);
|
||||||
@ -451,7 +442,7 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
synchronized (t) {
|
synchronized (t) {
|
||||||
if (t.isLocked()) {
|
if (t.isLocked()) {
|
||||||
// dont remove tile used by renderthread
|
// dont remove tile used by renderthread
|
||||||
Log.d(TAG, "X not removing " + t + " " + t.isActive + " "
|
Log.d(TAG, "X not removing " + t + " " + t.isLocked + " "
|
||||||
+ t.distance);
|
+ t.distance);
|
||||||
|
|
||||||
mTiles.add(t);
|
mTiles.add(t);
|
||||||
@ -478,7 +469,7 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
|
|
||||||
synchronized (mTilesLoaded) {
|
synchronized (mTilesLoaded) {
|
||||||
|
|
||||||
// remove uploaded tiles
|
// remove tiles uploaded to vbo
|
||||||
for (int i = 0; i < size;) {
|
for (int i = 0; i < size;) {
|
||||||
MapTile t = mTilesLoaded.get(i);
|
MapTile t = mTilesLoaded.get(i);
|
||||||
// rel == null means tile is already removed by limitCache
|
// rel == null means tile is already removed by limitCache
|
||||||
@ -535,8 +526,7 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
|
|
||||||
if (!tile.isLoading) {
|
if (!tile.isLoading) {
|
||||||
// no one should be able to use this tile now, mapgenerator passed
|
// no one should be able to use this tile now, mapgenerator passed
|
||||||
// it,
|
// it, glthread does nothing until newdata is set.
|
||||||
// glthread does nothing until newdata is set.
|
|
||||||
Log.d(TAG, "passTile: canceled " + tile);
|
Log.d(TAG, "passTile: canceled " + tile);
|
||||||
synchronized (mTilesLoaded) {
|
synchronized (mTilesLoaded) {
|
||||||
mTilesLoaded.add(tile);
|
mTilesLoaded.add(tile);
|
||||||
|
@ -41,7 +41,7 @@ class MapTile extends JobTile {
|
|||||||
/**
|
/**
|
||||||
* tile is used by render thread. set by updateVisibleList (main thread).
|
* tile is used by render thread. set by updateVisibleList (main thread).
|
||||||
*/
|
*/
|
||||||
boolean isActive;
|
boolean isLocked;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* tile has new data to upload to gl
|
* tile has new data to upload to gl
|
||||||
@ -74,13 +74,16 @@ class MapTile extends JobTile {
|
|||||||
// counting the tiles that use this tile as proxy
|
// counting the tiles that use this tile as proxy
|
||||||
byte refs;
|
byte refs;
|
||||||
|
|
||||||
|
boolean isActive() {
|
||||||
|
return isLoading || newData || isReady;
|
||||||
|
}
|
||||||
|
|
||||||
boolean isLocked() {
|
boolean isLocked() {
|
||||||
return isActive || refs > 0;
|
return isLocked || refs > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void lock() {
|
void lock() {
|
||||||
|
isLocked = true;
|
||||||
isActive = true;
|
|
||||||
|
|
||||||
if (isReady || newData)
|
if (isReady || newData)
|
||||||
return;
|
return;
|
||||||
@ -110,7 +113,7 @@ class MapTile extends JobTile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void unlock() {
|
void unlock() {
|
||||||
isActive = false;
|
isLocked = false;
|
||||||
|
|
||||||
if (proxies == 0)
|
if (proxies == 0)
|
||||||
return;
|
return;
|
||||||
|
@ -23,8 +23,8 @@ class PolygonLayer {
|
|||||||
PolygonLayer next;
|
PolygonLayer next;
|
||||||
Area area;
|
Area area;
|
||||||
|
|
||||||
ShortItem pool;
|
VertexPoolItem pool;
|
||||||
protected ShortItem curItem;
|
protected VertexPoolItem curItem;
|
||||||
int verticesCnt;
|
int verticesCnt;
|
||||||
int offset;
|
int offset;
|
||||||
|
|
||||||
@ -33,14 +33,14 @@ class PolygonLayer {
|
|||||||
PolygonLayer(int layer, Area area) {
|
PolygonLayer(int layer, Area area) {
|
||||||
this.layer = layer;
|
this.layer = layer;
|
||||||
this.area = area;
|
this.area = area;
|
||||||
curItem = ShortPool.get();
|
curItem = VertexPool.get();
|
||||||
pool = curItem;
|
pool = curItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
void addPolygon(float[] points, short[] index) {
|
void addPolygon(float[] points, short[] index) {
|
||||||
short center = (short) ((Tile.TILE_SIZE >> 1) * S);
|
short center = (short) ((Tile.TILE_SIZE >> 1) * S);
|
||||||
|
|
||||||
ShortItem si = curItem;
|
VertexPoolItem si = curItem;
|
||||||
short[] v = si.vertices;
|
short[] v = si.vertices;
|
||||||
int outPos = si.used;
|
int outPos = si.used;
|
||||||
|
|
||||||
@ -59,8 +59,8 @@ class PolygonLayer {
|
|||||||
|
|
||||||
int inPos = pos;
|
int inPos = pos;
|
||||||
|
|
||||||
if (outPos == ShortItem.SIZE) {
|
if (outPos == VertexPoolItem.SIZE) {
|
||||||
si = si.next = ShortPool.get();
|
si = si.next = VertexPool.get();
|
||||||
v = si.vertices;
|
v = si.vertices;
|
||||||
outPos = 0;
|
outPos = 0;
|
||||||
}
|
}
|
||||||
@ -69,8 +69,8 @@ class PolygonLayer {
|
|||||||
v[outPos++] = center;
|
v[outPos++] = center;
|
||||||
|
|
||||||
for (int j = 0; j < length; j += 2) {
|
for (int j = 0; j < length; j += 2) {
|
||||||
if (outPos == ShortItem.SIZE) {
|
if (outPos == VertexPoolItem.SIZE) {
|
||||||
si = si.next = ShortPool.get();
|
si = si.next = VertexPool.get();
|
||||||
v = si.vertices;
|
v = si.vertices;
|
||||||
outPos = 0;
|
outPos = 0;
|
||||||
}
|
}
|
||||||
@ -78,8 +78,8 @@ class PolygonLayer {
|
|||||||
v[outPos++] = (short) (points[inPos++] * S);
|
v[outPos++] = (short) (points[inPos++] * S);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (outPos == ShortItem.SIZE) {
|
if (outPos == VertexPoolItem.SIZE) {
|
||||||
si = si.next = ShortPool.get();
|
si = si.next = VertexPool.get();
|
||||||
v = si.vertices;
|
v = si.vertices;
|
||||||
outPos = 0;
|
outPos = 0;
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,9 @@ import static android.opengl.GLES20.glUniformMatrix4fv;
|
|||||||
import static android.opengl.GLES20.glUseProgram;
|
import static android.opengl.GLES20.glUseProgram;
|
||||||
import static android.opengl.GLES20.glVertexAttribPointer;
|
import static android.opengl.GLES20.glVertexAttribPointer;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
|
import java.nio.FloatBuffer;
|
||||||
import java.nio.ShortBuffer;
|
import java.nio.ShortBuffer;
|
||||||
|
|
||||||
import org.oscim.utils.GlUtils;
|
import org.oscim.utils.GlUtils;
|
||||||
@ -257,7 +260,7 @@ class PolygonRenderer {
|
|||||||
if (mCount > 0)
|
if (mCount > 0)
|
||||||
fillPolygons(zoom, scale);
|
fillPolygons(zoom, scale);
|
||||||
|
|
||||||
//
|
// maybe reset start when only few layers left in stencil buffer
|
||||||
// if (mCount > 5){
|
// if (mCount > 5){
|
||||||
// mCount = 0;
|
// mCount = 0;
|
||||||
// mStart = 0;
|
// mStart = 0;
|
||||||
@ -273,6 +276,35 @@ class PolygonRenderer {
|
|||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static float[] debugFillColor = { 0.3f, 0.0f, 0.0f, 0.3f };
|
||||||
|
|
||||||
|
private static ByteBuffer mDebugFill;
|
||||||
|
|
||||||
|
static void debugDraw(float[] matrix, float[] coords) {
|
||||||
|
|
||||||
|
mDebugFill = ByteBuffer.allocateDirect(32).order(ByteOrder.nativeOrder());
|
||||||
|
FloatBuffer buf = mDebugFill.asFloatBuffer();
|
||||||
|
buf.put(coords);
|
||||||
|
|
||||||
|
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
|
||||||
|
|
||||||
|
mDebugFill.position(0);
|
||||||
|
glUseProgram(polygonProgram);
|
||||||
|
GLES20.glEnableVertexAttribArray(hPolygonVertexPosition);
|
||||||
|
|
||||||
|
glVertexAttribPointer(hPolygonVertexPosition, 2, GLES20.GL_FLOAT,
|
||||||
|
false, 0, mDebugFill);
|
||||||
|
|
||||||
|
glUniformMatrix4fv(hPolygonMatrix, 1, false, matrix, 0);
|
||||||
|
|
||||||
|
glUniform4fv(hPolygonColor, 1, debugFillColor, 0);
|
||||||
|
|
||||||
|
glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
|
||||||
|
|
||||||
|
GlUtils.checkGlError("draw debug");
|
||||||
|
GLES20.glDisableVertexAttribArray(hPolygonVertexPosition);
|
||||||
|
}
|
||||||
|
|
||||||
static void drawDepthClip() {
|
static void drawDepthClip() {
|
||||||
glColorMask(false, false, false, false);
|
glColorMask(false, false, false, false);
|
||||||
GLES20.glDepthMask(true);
|
GLES20.glDepthMask(true);
|
||||||
@ -299,16 +331,16 @@ class PolygonRenderer {
|
|||||||
static void compileLayerData(PolygonLayer layers, ShortBuffer sbuf) {
|
static void compileLayerData(PolygonLayer layers, ShortBuffer sbuf) {
|
||||||
int pos = 4;
|
int pos = 4;
|
||||||
|
|
||||||
ShortItem last = null, items = null;
|
VertexPoolItem last = null, items = null;
|
||||||
|
|
||||||
for (PolygonLayer l = layers; l != null; l = l.next) {
|
for (PolygonLayer l = layers; l != null; l = l.next) {
|
||||||
|
|
||||||
for (ShortItem item = l.pool; item != null; item = item.next) {
|
for (VertexPoolItem item = l.pool; item != null; item = item.next) {
|
||||||
|
|
||||||
if (item.next == null) {
|
if (item.next == null) {
|
||||||
sbuf.put(item.vertices, 0, item.used);
|
sbuf.put(item.vertices, 0, item.used);
|
||||||
} else {
|
} else {
|
||||||
// item.used = ShortItem.SIZE;
|
// item.used = VertexPoolItem.SIZE;
|
||||||
sbuf.put(item.vertices);
|
sbuf.put(item.vertices);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -326,13 +358,13 @@ class PolygonRenderer {
|
|||||||
l.pool = null;
|
l.pool = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
ShortPool.add(items);
|
VertexPool.add(items);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void clear(PolygonLayer layers) {
|
static void clear(PolygonLayer layers) {
|
||||||
for (PolygonLayer l = layers; l != null; l = l.next) {
|
for (PolygonLayer l = layers; l != null; l = l.next) {
|
||||||
if (l.pool != null)
|
if (l.pool != null)
|
||||||
ShortPool.add(l.pool);
|
VertexPool.add(l.pool);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
184
src/org/oscim/view/renderer/ScanBox.java
Normal file
184
src/org/oscim/view/renderer/ScanBox.java
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012 Hannes Janetzek
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ported from Polymaps: Layer.js */
|
||||||
|
|
||||||
|
package org.oscim.view.renderer;
|
||||||
|
|
||||||
|
import org.oscim.view.renderer.MapRenderer.TilesData;
|
||||||
|
|
||||||
|
import android.util.FloatMath;
|
||||||
|
|
||||||
|
public class ScanBox {
|
||||||
|
|
||||||
|
interface Callback {
|
||||||
|
void call(MapTile tile);
|
||||||
|
}
|
||||||
|
|
||||||
|
class SetVisible implements Callback {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void call(MapTile tile) {
|
||||||
|
tile.isVisible = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class Edge {
|
||||||
|
float x0, y0, x1, y1, dx, dy;
|
||||||
|
|
||||||
|
void set(float x0, float y0, float x1, float y1) {
|
||||||
|
if (y0 <= y1) {
|
||||||
|
this.x0 = x0;
|
||||||
|
this.y0 = y0;
|
||||||
|
this.x1 = x1;
|
||||||
|
this.y1 = y1;
|
||||||
|
this.dx = x1 - x0;
|
||||||
|
this.dy = y1 - y0;
|
||||||
|
} else {
|
||||||
|
this.x0 = x1;
|
||||||
|
this.y0 = y1;
|
||||||
|
this.x1 = x0;
|
||||||
|
this.y1 = y0;
|
||||||
|
this.dx = x0 - x1;
|
||||||
|
this.dy = y0 - y1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Edge ab = new Edge();
|
||||||
|
static Edge bc = new Edge();
|
||||||
|
static Edge ca = new Edge();
|
||||||
|
|
||||||
|
static void scanSpans(Edge e0, Edge e1, float ymin, float ymax) {
|
||||||
|
|
||||||
|
// sort edge by x-coordinate
|
||||||
|
if (e0.x0 == e1.x0 && e0.y0 == e1.y0) {
|
||||||
|
if (e0.x0 + e1.dy / e0.dy * e0.dx < e1.x1) {
|
||||||
|
Edge t = e0;
|
||||||
|
e0 = e1;
|
||||||
|
e1 = t;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (e0.x1 - e1.dy / e0.dy * e0.dx < e1.x0) {
|
||||||
|
Edge t = e0;
|
||||||
|
e0 = e1;
|
||||||
|
e1 = t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float m0 = e0.dx / e0.dy;
|
||||||
|
float m1 = e1.dx / e1.dy;
|
||||||
|
|
||||||
|
int d0 = e0.dx > 0 ? 1 : 0;// use y + 1 to compute x0
|
||||||
|
int d1 = e1.dx < 0 ? 1 : 0; // use y + 1 to compute x1
|
||||||
|
|
||||||
|
float x0, x1;
|
||||||
|
|
||||||
|
int y = (int) Math.max(ymin, FloatMath.floor(e1.y0));
|
||||||
|
int bottom = (int) Math.min(ymax, FloatMath.ceil(e1.y1));
|
||||||
|
|
||||||
|
for (; y < bottom; y++) {
|
||||||
|
// float x0 = (m0 * Math.min(e0.dy, y + d0 - e0.y0) + e0.x0);
|
||||||
|
// float x1 = (m1 * Math.min(e1.dy, y + d1 - e1.y0) + e1.x0);
|
||||||
|
|
||||||
|
x0 = y + d0 - e0.y0;
|
||||||
|
if (e0.dy < x0)
|
||||||
|
x0 = e0.dy;
|
||||||
|
|
||||||
|
x0 = m0 * x0 + e0.x0;
|
||||||
|
|
||||||
|
if (x0 < 0)
|
||||||
|
x0 = 0;
|
||||||
|
else
|
||||||
|
x0 = FloatMath.ceil(x0);
|
||||||
|
|
||||||
|
x1 = y + d1 - e1.y0;
|
||||||
|
if (e1.dy < x1)
|
||||||
|
x1 = e1.dy;
|
||||||
|
|
||||||
|
x1 = m1 * x1 + e1.x0;
|
||||||
|
|
||||||
|
if (x1 < 0)
|
||||||
|
x1 = 0;
|
||||||
|
else
|
||||||
|
x1 = FloatMath.floor(x1);
|
||||||
|
|
||||||
|
setVisible(y, (int) x1, (int) x0);
|
||||||
|
|
||||||
|
// setVisible(y, (int) (x1 - 0.5f), (int) (x0 + 0.5f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void scanTriangle(float ymin, float ymax) {
|
||||||
|
|
||||||
|
if (ab.dy > bc.dy) {
|
||||||
|
Edge t = ab;
|
||||||
|
ab = bc;
|
||||||
|
bc = t;
|
||||||
|
}
|
||||||
|
if (ab.dy > ca.dy) {
|
||||||
|
Edge t = ab;
|
||||||
|
ab = ca;
|
||||||
|
ca = t;
|
||||||
|
}
|
||||||
|
if (bc.dy > ca.dy) {
|
||||||
|
Edge t = bc;
|
||||||
|
bc = ca;
|
||||||
|
ca = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ab.dy != 0)
|
||||||
|
scanSpans(ca, ab, ymin, ymax);
|
||||||
|
if (bc.dy != 0)
|
||||||
|
scanSpans(ca, bc, ymin, ymax);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void scan(float[] coords, TilesData tiles, int max) {
|
||||||
|
sTiles = tiles;
|
||||||
|
cntDoubles = 0;
|
||||||
|
ab.set(coords[0], coords[1], coords[2], coords[3]);
|
||||||
|
bc.set(coords[2], coords[3], coords[4], coords[5]);
|
||||||
|
ca.set(coords[4], coords[5], coords[0], coords[1]);
|
||||||
|
|
||||||
|
scanTriangle(0, max);
|
||||||
|
// Log.d("..", ">doubles " + cntDoubles);
|
||||||
|
ab.set(coords[4], coords[5], coords[6], coords[7]);
|
||||||
|
bc.set(coords[6], coords[7], coords[0], coords[1]);
|
||||||
|
ca.set(coords[0], coords[1], coords[4], coords[5]);
|
||||||
|
|
||||||
|
scanTriangle(0, max);
|
||||||
|
|
||||||
|
// Log.d("..", "<doubles " + cntDoubles);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static TilesData sTiles;
|
||||||
|
private static int cntDoubles;
|
||||||
|
|
||||||
|
private static void setVisible(int y, int x1, int x2) {
|
||||||
|
|
||||||
|
MapTile[] tiles = sTiles.tiles;
|
||||||
|
for (int i = 0, n = sTiles.cnt; i < n; i++) {
|
||||||
|
if (tiles[i].tileY == y) {
|
||||||
|
if (tiles[i].tileX >= x1 && tiles[i].tileX < x2) {
|
||||||
|
// if (tiles[i].isVisible) {
|
||||||
|
// Log.d("..", ">>>" + y + " " + tiles[i].tileX);
|
||||||
|
// cntDoubles++;
|
||||||
|
// }
|
||||||
|
tiles[i].isVisible = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -192,7 +192,7 @@ public class TextRenderer {
|
|||||||
if (tex.tile == null)
|
if (tex.tile == null)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (!tex.tile.isActive)
|
if (!tex.tile.isLocked)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
tex = null;
|
tex = null;
|
||||||
@ -412,7 +412,7 @@ public class TextRenderer {
|
|||||||
|
|
||||||
for (int i = 0; i < mTextures.length; i++) {
|
for (int i = 0; i < mTextures.length; i++) {
|
||||||
tex = mTextures[i];
|
tex = mTextures[i];
|
||||||
if (tex.tile == null || !tex.tile.isActive)
|
if (tex.tile == null || !tex.tile.isLocked)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
mShortBuffer.put(tex.vertices, 0, tex.length);
|
mShortBuffer.put(tex.vertices, 0, tex.length);
|
||||||
|
@ -16,10 +16,10 @@ package org.oscim.view.renderer;
|
|||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
public class ShortPool {
|
public class VertexPool {
|
||||||
private static final int POOL_LIMIT = 6000;
|
private static final int POOL_LIMIT = 6000;
|
||||||
|
|
||||||
static private ShortItem pool = null;
|
static private VertexPoolItem pool = null;
|
||||||
static private int count = 0;
|
static private int count = 0;
|
||||||
static private int countAll = 0;
|
static private int countAll = 0;
|
||||||
|
|
||||||
@ -29,14 +29,14 @@ public class ShortPool {
|
|||||||
pool = null;
|
pool = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
static synchronized ShortItem get() {
|
static synchronized VertexPoolItem get() {
|
||||||
|
|
||||||
if (pool == null && count > 0) {
|
if (pool == null && count > 0) {
|
||||||
Log.d("ShortPool", "XXX wrong count: " + count);
|
Log.d("VertexPool", "XXX wrong count: " + count);
|
||||||
}
|
}
|
||||||
if (pool == null) {
|
if (pool == null) {
|
||||||
countAll++;
|
countAll++;
|
||||||
return new ShortItem();
|
return new VertexPoolItem();
|
||||||
}
|
}
|
||||||
|
|
||||||
count--;
|
count--;
|
||||||
@ -44,14 +44,14 @@ public class ShortPool {
|
|||||||
if (count < 0) {
|
if (count < 0) {
|
||||||
int c = 0;
|
int c = 0;
|
||||||
|
|
||||||
for (ShortItem tmp = pool; tmp != null; tmp = tmp.next)
|
for (VertexPoolItem tmp = pool; tmp != null; tmp = tmp.next)
|
||||||
c++;
|
c++;
|
||||||
|
|
||||||
Log.d("ShortPool", "XXX wrong count: " + count + " left" + c);
|
Log.d("VertexPool", "XXX wrong count: " + count + " left" + c);
|
||||||
return new ShortItem();
|
return new VertexPoolItem();
|
||||||
}
|
}
|
||||||
|
|
||||||
ShortItem it = pool;
|
VertexPoolItem it = pool;
|
||||||
pool = pool.next;
|
pool = pool.next;
|
||||||
it.used = 0;
|
it.used = 0;
|
||||||
it.next = null;
|
it.next = null;
|
||||||
@ -61,7 +61,7 @@ public class ShortPool {
|
|||||||
// private static float load = 1.0f;
|
// private static float load = 1.0f;
|
||||||
// private static int loadCount = 0;
|
// private static int loadCount = 0;
|
||||||
|
|
||||||
static synchronized void add(ShortItem items) {
|
static synchronized void add(VertexPoolItem items) {
|
||||||
if (items == null)
|
if (items == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -71,11 +71,11 @@ public class ShortPool {
|
|||||||
// limit pool items
|
// limit pool items
|
||||||
if (countAll < POOL_LIMIT) {
|
if (countAll < POOL_LIMIT) {
|
||||||
|
|
||||||
ShortItem last = items;
|
VertexPoolItem last = items;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
count++;
|
count++;
|
||||||
// load += (float) last.used / ShortItem.SIZE;
|
// load += (float) last.used / VertexPoolItem.SIZE;
|
||||||
// loadCount++;
|
// loadCount++;
|
||||||
|
|
||||||
if (last.next == null)
|
if (last.next == null)
|
||||||
@ -91,14 +91,14 @@ public class ShortPool {
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
// int cleared = 0;
|
// int cleared = 0;
|
||||||
ShortItem prev, tmp = items;
|
VertexPoolItem prev, tmp = items;
|
||||||
while (tmp != null) {
|
while (tmp != null) {
|
||||||
prev = tmp;
|
prev = tmp;
|
||||||
tmp = tmp.next;
|
tmp = tmp.next;
|
||||||
|
|
||||||
countAll--;
|
countAll--;
|
||||||
|
|
||||||
// load += (float) prev.used / ShortItem.SIZE;
|
// load += (float) prev.used / VertexPoolItem.SIZE;
|
||||||
// loadCount++;
|
// loadCount++;
|
||||||
|
|
||||||
prev.next = null;
|
prev.next = null;
|
@ -14,12 +14,12 @@
|
|||||||
*/
|
*/
|
||||||
package org.oscim.view.renderer;
|
package org.oscim.view.renderer;
|
||||||
|
|
||||||
public class ShortItem {
|
public class VertexPoolItem {
|
||||||
final short[] vertices;
|
final short[] vertices;
|
||||||
int used;
|
int used;
|
||||||
ShortItem next;
|
VertexPoolItem next;
|
||||||
|
|
||||||
ShortItem() {
|
VertexPoolItem() {
|
||||||
vertices = new short[SIZE];
|
vertices = new short[SIZE];
|
||||||
used = 0;
|
used = 0;
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user