package com.asha.vrlib.plugins.hotspot;
import android.content.Context;
import android.graphics.RectF;
import android.opengl.GLES20;
import com.asha.vrlib.MD360Director;
import com.asha.vrlib.MD360Program;
import com.asha.vrlib.MDVRLibrary;
import com.asha.vrlib.common.VRUtil;
import com.asha.vrlib.model.MDHitEvent;
import com.asha.vrlib.model.MDHitPoint;
import com.asha.vrlib.model.MDPluginBuilder;
import com.asha.vrlib.model.MDPosition;
import com.asha.vrlib.model.MDRay;
import com.asha.vrlib.model.MDVector3D;
import com.asha.vrlib.objects.MDAbsObject3D;
import com.asha.vrlib.objects.MDObject3DHelper;
import com.asha.vrlib.objects.MDPlane;
import com.asha.vrlib.plugins.MDAbsPlugin;
import java.nio.FloatBuffer;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import static com.asha.vrlib.common.GLUtil.glCheck;
/**
* Created by hzqiujiadi on 2017/4/12.
* hzqiujiadi ashqalcn@gmail.com
*/
public abstract class MDAbsHotspot extends MDAbsPlugin implements IMDHotspot {
private RectF size;
private MDAbsObject3D object3D;
MD360Program program;
// hotspot
private String title;
private String tag;
private MDVRLibrary.ITouchPickListener clickListener;
private MDHitPoint hitPoint1 = new MDHitPoint(){
@Override
public float getV() {
return 1 - super.getV();
}
};
private MDHitPoint hitPoint2 = new MDHitPoint(){
@Override
public float getU() {
return 1 - super.getU();
}
};
private AtomicBoolean mPendingRotateToCamera = new AtomicBoolean(false);
public MDAbsHotspot(MDPluginBuilder builder) {
setTag(builder.tag);
setTitle(builder.title);
this.clickListener = builder.clickListener;
this.size = new RectF(0, 0, builder.width, builder.height);
setModelPosition(builder.position == null ? MDPosition.getOriginalPosition() : builder.position);
}
@Override
protected void initInGL(Context context) {
program = new MD360Program(MDVRLibrary.ContentType.BITMAP);
program.build(context);
// load obj
object3D = new MDPlane(size);
MDObject3DHelper.loadObj(context,object3D);
}
@Override
public void destroyInGL() {
}
@Override
public void beforeRenderer(int totalWidth, int totalHeight) {
}
@Override
public void renderer(int index, int width, int height, MD360Director director) {
// Update Projection
director.setViewport(width, height);
// Set our per-vertex lighting program.
program.use();
glCheck("MDSimplePlugin mProgram use");
object3D.uploadVerticesBufferIfNeed(program, index);
object3D.uploadTexCoordinateBufferIfNeed(program, index);
// Pass in the combined matrix.
director.beforeShot();
consumePendingRotateToCamera(director);
director.shot(program, getModelPosition());
GLES20.glEnable(GLES20.GL_BLEND);
GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
object3D.draw();
GLES20.glDisable(GLES20.GL_BLEND);
}
@Override
protected boolean removable() {
return true;
}
@Override
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
@Override
public String getTag() {
return tag;
}
public void setTag(String tag) {
this.tag = tag;
}
@Override
public MDHitPoint hit(MDRay ray) {
if (object3D == null || object3D.getVerticesBuffer(0) == null){
return MDHitPoint.notHit();
}
MDPosition position = getModelPosition();
float[] model = position.getMatrix();
List<MDVector3D> points = new LinkedList<>();
FloatBuffer buffer = object3D.getVerticesBuffer(0);
int numPoints = buffer.capacity() / 3;
for (int i = 0; i < numPoints; i++){
MDVector3D v = new MDVector3D();
v.setX(buffer.get(i * 3)).setY(buffer.get(i * 3 + 1)).setZ(buffer.get(i * 3 + 2));
v.multiplyMV(model);
points.add(v);
}
MDHitPoint hit1 = hitPoint1;
MDHitPoint hit2 = hitPoint2;
if (points.size() == 4){
VRUtil.intersectTriangle(ray, points.get(0), points.get(1), points.get(2), hitPoint1);
VRUtil.intersectTriangle(ray, points.get(3), points.get(2), points.get(1), hitPoint2);
}
return MDHitPoint.min(hit1, hit2);
}
@Override
public void onEyeHitIn(MDHitEvent hitEvent) {
}
@Override
public void onEyeHitOut(long timestamp) {
}
@Override
public void onTouchHit(MDRay ray) {
if (clickListener != null){
clickListener.onHotspotHit(this, ray);
}
}
@Override
public void rotateToCamera(){
mPendingRotateToCamera.set(true);
}
private void consumePendingRotateToCamera(MD360Director director) {
if (mPendingRotateToCamera.get()){
MDPosition position = getModelPosition();
float[] rotation = director.getWorldRotationInvert();
position.setRotationMatrix(rotation);
mPendingRotateToCamera.set(false);
}
}
}