package org.wheelmap.android.tango.renderer;
import android.content.Context;
import android.graphics.Bitmap;
import android.util.Log;
import android.view.MotionEvent;
import com.google.atap.tangoservice.TangoPoseData;
import com.projecttango.tangosupport.TangoSupport;
import org.rajawali3d.lights.DirectionalLight;
import org.rajawali3d.materials.Material;
import org.rajawali3d.materials.textures.ATexture;
import org.rajawali3d.materials.textures.StreamingTexture;
import org.rajawali3d.math.Matrix4;
import org.rajawali3d.math.Quaternion;
import org.rajawali3d.primitives.ScreenQuad;
import org.rajawali3d.renderer.Renderer;
import javax.microedition.khronos.opengles.GL10;
public abstract class TangoRajawaliRenderer extends Renderer {
private static final String TAG = "TangoRajawaliRenderer";
private float[] textureCoords0 = new float[]{0.0F, 1.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F, 0.0F};
public interface ScreenshotCaptureListener {
void onScreenshotCaptured(Bitmap bitmap);
}
// Augmented Reality related fields
private ScreenQuad backgroundQuad;
private ATexture mTangoCameraTexture;
private boolean mSceneCameraConfigured;
private WheelmapTangoRajawaliRenderer.ScreenshotCaptureListener screenshotCaptureListener = null;
TangoRajawaliRenderer(Context context) {
super(context);
}
@Override
protected void initScene() {
// Create a quad covering the whole background and assign a texture to it where the
// Tango color camera contents will be rendered.
// Create a quad covering the whole background and assign a texture to it where the
// Tango color camera contents will be rendered.
if (backgroundQuad == null) {
backgroundQuad = new ScreenQuad();
backgroundQuad.getGeometry().setTextureCoords(textureCoords0);
}
Material tangoCameraMaterial = new Material();
tangoCameraMaterial.setColorInfluence(0);
// We need to use Rajawali's {@code StreamingTexture} since it sets up the texture
// for GL_TEXTURE_EXTERNAL_OES rendering
mTangoCameraTexture =
new StreamingTexture("camera", (StreamingTexture.ISurfaceListener) null);
try {
tangoCameraMaterial.addTexture(mTangoCameraTexture);
backgroundQuad.setMaterial(tangoCameraMaterial);
} catch (ATexture.TextureException e) {
Log.e(TAG, "Exception creating texture for RGB camera contents", e);
}
getCurrentScene().addChildAt(backgroundQuad, 0);
// Add a directional light in an arbitrary direction.
DirectionalLight light = new DirectionalLight(1, 0.2, -1);
light.setColor(1, 1, 1);
light.setPower(0.8f);
light.setPosition(3, 2, 4);
getCurrentScene().addLight(light);
}
/**
* Update background texture's UV coordinates when device orientation is changed (i.e., change
* between landscape and portrait mode.
* This must be run in the OpenGL thread.
*/
public void updateColorCameraTextureUvGlThread(int rotation) {
Log.d(TAG, "updateColorCameraTextureUvGlThread() called with " + "rotation = [" + rotation + "]");
if (backgroundQuad == null) {
backgroundQuad = new ScreenQuad();
}
float[] textureCoords =
TangoSupport.getVideoOverlayUVBasedOnDisplayRotation(textureCoords0, rotation);
backgroundQuad.getGeometry().setTextureCoords(textureCoords, true);
backgroundQuad.getGeometry().reload();
}
/**
* It returns the ID currently assigned to the texture where the Tango color camera contents
* should be rendered.
* NOTE: This must be called from the OpenGL render thread - it is not thread safe.
*/
public int getTextureId() {
return mTangoCameraTexture == null ? -1 : mTangoCameraTexture.getTextureId();
}
/**
* We need to override this method to mark the camera for re-configuration (set proper
* projection matrix) since it will be reset by Rajawali on surface changes.
*/
@Override
public void onRenderSurfaceSizeChanged(GL10 gl, int width, int height) {
super.onRenderSurfaceSizeChanged(gl, width, height);
mSceneCameraConfigured = false;
}
public boolean isSceneCameraConfigured() {
return mSceneCameraConfigured;
}
/**
* Update the scene camera based on the provided pose in Tango start of service frame.
* The camera pose should match the pose of the camera color at the time of the last rendered
* RGB frame, which can be retrieved with this.getTimestamp();
* <p/>
* NOTE: This must be called from the OpenGL render thread; it is not thread safe.
*/
public void updateRenderCameraPose(TangoPoseData cameraPose) {
float[] rotation = cameraPose.getRotationAsFloats();
float[] translation = cameraPose.getTranslationAsFloats();
Quaternion quaternion = new Quaternion(rotation[3], rotation[0], rotation[1], rotation[2]);
// Conjugating the Quaternion is needed because Rajawali uses left-handed convention for
// quaternions.
getCurrentCamera().setRotation(quaternion.conjugate());
getCurrentCamera().setPosition(translation[0], translation[1], translation[2]);
}
/**
* Sets the projection matrix for the scene camera to match the parameters of the color camera,
* provided by the {@code TangoCameraIntrinsics}.
*/
public void setProjectionMatrix(float[] matrix) {
Log.d(TAG, "setProjectionMatrix");
getCurrentCamera().setProjectionMatrix(new Matrix4(matrix));
mSceneCameraConfigured = true;
}
@Override
public void onOffsetsChanged(float xOffset, float yOffset, float xOffsetStep, float yOffsetStep, int xPixelOffset, int yPixelOffset) {
}
@Override
public void onTouchEvent(MotionEvent event) {
}
@Override
public void onRenderFrame(GL10 gl) {
super.onRenderFrame(gl);
if (screenshotCaptureListener != null) {
Bitmap bitmap = ScreenshotHelper.getBitmap(0, 0, getDefaultViewportWidth(), getDefaultViewportHeight(), gl);
screenshotCaptureListener.onScreenshotCaptured(bitmap);
screenshotCaptureListener = null;
}
}
public void captureScreenshot(ScreenshotCaptureListener listener) {
this.screenshotCaptureListener = listener;
}
}