Back to project page geoar-app.
The source code is released under:
Apache License
If you think the Android project geoar-app listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.
/** * Copyright 2012 52North Initiative for Geospatial Open Source Software GmbH */* w ww . ja va2 s . c o m*/ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.n52.geoar.ar.view.gl; import java.util.ArrayList; import java.util.List; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; import org.n52.geoar.ar.view.ARObject; import org.n52.geoar.tracking.camera.RealityCamera; import org.n52.geoar.tracking.camera.RealityCamera.CameraUpdateListener; import org.n52.geoar.view.geoar.gl.mode.FeatureShader; import org.n52.geoar.view.geoar.gl.mode.RenderFeature2; import org.n52.geoar.view.geoar.gl.mode.Texture; import org.n52.geoar.view.geoar.gl.mode.features.NewGridFeature; import android.location.Location; import android.opengl.GLES20; import android.opengl.GLSurfaceView; import android.opengl.GLSurfaceView.Renderer; import android.opengl.Matrix; /** * * @author Arne de Wall * */ public class ARSurfaceViewRenderer implements GLSurfaceView.Renderer, CameraUpdateListener { /** * Interface for the Methods which are called inside the OpenGL specific * thread. */ public interface OpenGLCallable { void onPreRender(); // unused void render(final float[] projectionMatrix, final float[] viewMatrix, final float[] parentMatrix, final float[] lightPosition); } public interface OnInitializeInGLThread { void onCreateInGLESThread(); } /** * Public interface to create an object which supplies the renderer with the * current extrinsic camera rotation. Ensures that matrices are just * computed as needed, since the renderer asks for data and does not listen * for them. */ public interface IRotationMatrixProvider { /** * Returns the current extrinsic rotation matrix * * @return row major 4x4 matrix */ float[] getRotationMatrix(); } private final IRotationMatrixProvider mRotationProvider; // private List<RenderFeature2> renderFeatures = new // ArrayList<RenderFeature2>(); private RenderFeature2 grid; // private RenderFeature2 test; /** light parameters */ private final float[] lightDirection = new float[] { 3.0f, 10.0f, 2.0f, 1.0f }; private final float[] lightDirectionMVP = new float[4]; private final float[] mvMatrix = new float[16]; private boolean mARObjectsChanged; private ARSurfaceView mSurfaceView; // Currently always a copy of ARView's ARObjects private List<ARObject> mARObjects = new ArrayList<ARObject>(); // FlatCircleFeature circleFeature; // TriangleFeature triangle; private boolean mLocationChanged; private Location mUserLocation; private boolean mProjectionChanged; public ARSurfaceViewRenderer(ARSurfaceView surfaceView, IRotationMatrixProvider rotationMatrixProvider) { this.mSurfaceView = surfaceView; mUserLocation = mSurfaceView.getUserLocation(); this.mRotationProvider = rotationMatrixProvider; mLocationChanged = true; mARObjectsChanged = true; } @Override public void onDrawFrame(GL10 glUnused) { if (mProjectionChanged) { // Camera may get initialized after creating the GL surface, // projection matrix will be reset here if camera settings changed GLESCamera.resetProjectionMatrix(); GLESCamera.resetViewMatrix(); mProjectionChanged = false; } // Update ARObjects if required if (mARObjectsChanged) { // Copy list of ARObjects to avoid the need for synchronization mARObjects.clear(); mARObjects.addAll(mSurfaceView.getARObjects()); for (ARObject feature : mARObjects) { feature.initializeRendering(); } mARObjectsChanged = false; } if (mARObjects == null) { // Not all information available return; } // Update location information if required if (mLocationChanged) { mUserLocation = mSurfaceView.getUserLocation(); // TODO evaluate synchronized vs. copying list; list is reused by // mSurfaceView for because of performance reasons for (ARObject feature : mARObjects) { feature.onLocationUpdate(mUserLocation); } mLocationChanged = false; } if (mUserLocation == null) { // Not all information available return; } /** clear color buffer and depth buffer */ // GLES20.glEnable(GLES20.GL_DEPTH_TEST); // GLES20.glDepthFunc(GLES20.GL_LESS); // GLES20.glDepthMask(true); // GLES20.glClearDepthf(1.f); GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT); /** extrinsic camera parameters for matching camera- with virtual view */ System.arraycopy(mRotationProvider.getRotationMatrix(), 0, mvMatrix, 0, 16); /** calculate the light position in eye space */ Matrix.multiplyMV(lightDirectionMVP, 0, mvMatrix, 0, lightDirection, 0); /** render grid */ // triangle.render(GLESCamera.projectionMatrix, GLESCamera.viewMatrix, // mvMatrix, lightDirection); grid.render(GLESCamera.projectionMatrix, GLESCamera.viewMatrix, mvMatrix, lightDirection); // circleFeature.render(GLESCamera.projectionMatrix, // GLESCamera.viewMatrix, mvMatrix, lightDirection); /** render DataSources data */ for (ARObject feature : mARObjects) { feature.render(GLESCamera.projectionMatrix, GLESCamera.viewMatrix, mvMatrix, lightDirection); } // /** for testing purposes */ // for (RenderFeature2 r : renderFeatures) { // r.render(GLESCamera.projectionMatrix, GLESCamera.viewMatrix, // mvMatrix, lightDirection); // } } @Override public void onSurfaceChanged(GL10 glUnused, int width, int height) { GLES20.glViewport(0, 0, width, height); if (!RealityCamera.hasViewportSize()) { // Set camera viewport if none exists RealityCamera.setViewportSize(width, height); // RealityCamera.setAspect((float) width / (float) height); } GLESCamera.resetViewportMatrix(width, height); GLESCamera.resetProjectionMatrix(); } @Override public void onSurfaceCreated(GL10 glUnused, EGLConfig config) { /** Set the background clear color to "black" and transparent */ GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); /** set up the view matrix */ GLESCamera.resetViewMatrix(); /** Enable depth testing */ GLES20.glEnable(GLES20.GL_DEPTH_TEST); GLES20.glClearDepthf(1.0f); GLES20.glDepthFunc(GLES20.GL_LESS); GLES20.glDepthMask(true); /** Enable texture mapping */ GLES20.glEnable(GLES20.GL_TEXTURE_2D); /** Enable blending */ GLES20.glEnable(GLES20.GL_BLEND); GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA); // GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE); /** * Backface culling - here back-facing facets are culled when facet * culling is enabled */ GLES20.glEnable(GLES20.GL_CULL_FACE); GLES20.glCullFace(GLES20.GL_BACK); // GL_FRONT_AND_BACK for no facets // Resets all cached handlers because the context was lost so that they // are recreated later on demand. FeatureShader.resetShaders(); Texture.resetTextures(); initScene(); } private void initScene() { grid = new NewGridFeature(); grid.onCreateInGLESThread(); // test = new CubeFeature2(); // test.setTextureCallback(new Callable<Bitmap>() { // @Override // public Bitmap call() throws Exception { // return BitmapFactory.decodeResource( // GeoARApplication.applicationContext.getResources(), // R.drawable.n52_logo_highreso); // } // }); // test.setRelativePosition(new float[] { 0, 0, -6 }); // test.onCreateInGLESThread(); // circleFeature = new FlatCircleFeature(); // circleFeature.setRelativePosition(new float[] { 2, 0, -6 }); // circleFeature.onCreateInGLESThread(); // test.setSubVisualization(circleFeature); // triangle = new TriangleFeature(); // triangle.setRelativePosition(new float[] {-2, 0, -6}); // triangle.onCreateInGLESThread(); // test.setSubVisualization(triangle); // renderFeatures.add(test); // // first cube // RenderFeature2 first = new CubeFeature2(); // first.setPosition(new float[] { 1, 0, 5 }); // first.onCreateInGLESThread(); // renderFeatures.add(first); // // RenderFeature2 sec = new CubeFeature2(); // sec.setPosition(new float[] { 5, 0, 5 }); // sec.onCreateInGLESThread(); // renderFeatures.add(sec); // // RenderFeature2 third = new CubeFeature2(); // third.setPosition(new float[] { 2.5f, 0, 5 }); // third.onCreateInGLESThread(); // renderFeatures.add(third); } @Override public void onCameraUpdate() { mProjectionChanged = true; } /** * Ask renderer to reload */ public void reload() { mARObjectsChanged = true; } /** * Notification for this {@link Renderer} that the objects to display were * changed. The renderer will schedule an update of the features to draw for * the next draw cycle. */ public void notifyARObjectsChanged() { mARObjectsChanged = true; } /** * Notification for this {@link Renderer} that the user location changed. * The renderer will schedule an update of the relative positions of its * displayed features for the next draw cycle. */ public void notifyLocationChanged() { mLocationChanged = true; } }