package com.asha.vrlib.objects;
import android.content.Context;
import android.graphics.RectF;
import com.asha.vrlib.MD360Program;
import com.asha.vrlib.MDVRLibrary;
import com.asha.vrlib.strategy.projection.PlaneProjection;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;
/**
* Created by hzqiujiadi on 16/6/26.
* hzqiujiadi ashqalcn@gmail.com
*/
public class MDPlane extends MDAbsObject3D {
private static final String TAG = "MDPlane";
private float mPrevRatio;
private RectF mSize;
private PlaneProjection.PlaneScaleCalculator mCalculator;
private MDPlane(PlaneProjection.PlaneScaleCalculator calculator, RectF size) {
this.mCalculator = calculator;
this.mSize = size;
}
public MDPlane(PlaneProjection.PlaneScaleCalculator calculator) {
this(calculator,new RectF(0,0,1.0f,1.0f));
}
public MDPlane(RectF size) {
this(new PlaneProjection.PlaneScaleCalculator(MDVRLibrary.PROJECTION_MODE_PLANE_FULL,new RectF(0,0,100,100)),size);
}
@Override
protected void executeLoad(Context context) {
generateMesh(this);
}
@Override
public void uploadVerticesBufferIfNeed(MD360Program program, int index) {
if (super.getVerticesBuffer(index) == null){
return;
}
// update the texture only if the index == 0
if (index == 0){
float ratio = mCalculator.getTextureRatio();
if (ratio != mPrevRatio) {
float[] vertexs = generateVertex();
// initialize vertex byte buffer for shape coordinates
ByteBuffer bb = ByteBuffer.allocateDirect(
// (# of coordinate values * 4 bytes per float)
vertexs.length * 4);
bb.order(ByteOrder.nativeOrder());
FloatBuffer buffer = bb.asFloatBuffer();
buffer.put(vertexs);
buffer.position(0);
setVerticesBuffer(0,buffer);
setVerticesBuffer(1,buffer);
mPrevRatio = ratio;
}
}
super.uploadVerticesBufferIfNeed(program, index);
}
private float[] generateVertex(){
int z = 0;
mCalculator.calculate();
mPrevRatio = mCalculator.getTextureRatio();
float width = mCalculator.getTextureWidth() * mSize.width();
float height = mCalculator.getTextureHeight() * mSize.height();
float[] vertexs = new float[getNumPoint() * 3];
int rows = getNumRow();
int columns = getNumColumn();
float R = 1f/(float) rows;
float S = 1f/(float) columns;
short r, s;
int v = 0;
for(r = 0; r < rows + 1; r++) {
for(s = 0; s < columns + 1; s++) {
vertexs[v++] = (s * S - 0.5f) * width;
vertexs[v++] = (r * R - 0.5f) * height;
vertexs[v++] = z;
}
}
return vertexs;
}
private float[] generateTexcoords(){
float[] texcoords = new float[getNumPoint() * 2];
int rows = getNumRow();
int columns = getNumColumn();
float R = 1f/(float) rows;
float S = 1f/(float) columns;
short r, s;
int t = 0;
for(r = 0; r < rows + 1; r++) {
for(s = 0; s < columns + 1; s++) {
texcoords[t++] = s*S;
texcoords[t++] = r*R;
}
}
return texcoords;
}
private void generateMesh(MDAbsObject3D object3D){
int rows = getNumRow();
int columns = getNumColumn();
short r, s;
float[] vertexs = generateVertex();
float[] texcoords = generateTexcoords();
short[] indices = new short[getNumPoint() * 6];
int counter = 0;
int sectorsPlusOne = columns + 1;
for(r = 0; r < rows; r++){
for(s = 0; s < columns; s++) {
short k0 = (short) ((r) * sectorsPlusOne + (s+1)); // (c)
short k1 = (short) ((r+1) * sectorsPlusOne + (s)); //(b)
short k2 = (short) (r * sectorsPlusOne + s); //(a);
short k3 = (short) ((r) * sectorsPlusOne + (s+1)); // (c)
short k4 = (short) ((r+1) * sectorsPlusOne + (s+1)); // (d)
short k5 = (short) ((r+1) * sectorsPlusOne + (s)); //(b)
indices[counter++] = k0;
indices[counter++] = k1;
indices[counter++] = k2;
indices[counter++] = k3;
indices[counter++] = k4;
indices[counter++] = k5;
}
}
// initialize vertex byte buffer for shape coordinates
ByteBuffer bb = ByteBuffer.allocateDirect(
// (# of coordinate values * 4 bytes per float)
vertexs.length * 4);
bb.order(ByteOrder.nativeOrder());
FloatBuffer vertexBuffer = bb.asFloatBuffer();
vertexBuffer.put(vertexs);
vertexBuffer.position(0);
// initialize vertex byte buffer for shape coordinates
ByteBuffer cc = ByteBuffer.allocateDirect(
texcoords.length * 4);
cc.order(ByteOrder.nativeOrder());
FloatBuffer texBuffer = cc.asFloatBuffer();
texBuffer.put(texcoords);
texBuffer.position(0);
// initialize byte buffer for the draw list
ByteBuffer dlb = ByteBuffer.allocateDirect(
// (# of coordinate values * 2 bytes per short)
indices.length * 2);
dlb.order(ByteOrder.nativeOrder());
ShortBuffer indexBuffer = dlb.asShortBuffer();
indexBuffer.put(indices);
indexBuffer.position(0);
object3D.setIndicesBuffer(indexBuffer);
object3D.setTexCoordinateBuffer(0,texBuffer);
object3D.setTexCoordinateBuffer(1,texBuffer);
object3D.setVerticesBuffer(0,vertexBuffer);
object3D.setVerticesBuffer(1,vertexBuffer);
object3D.setNumIndices(indices.length);
}
private int getNumPoint(){
return (getNumRow() + 1) * (getNumColumn() + 1);
}
private int getNumRow(){
return 1;
}
private int getNumColumn(){
return 1;
}
}