I'm not sure if 'reconstruct' is the correct term for this but essentially what I am trying to do is calculate vertex positions (that are already calculated via shader) on the CPU for the purpose of ray tracing. I need to know the locations of the models so I can detect if my ray passes through them. It would be nice if I could retrieve the values from memory after the the shader has calculated them but it doesn't seem possible - or advisable.
What I have so far looks like it should work but when I trace my ray (that does pass directly through the model) none of the vertices fall inside the model.
Create the ray (Tested by drawing a line between far/near and it works fine):
public float[] getPickingVector(float[] modelview,
float[] projection,
int[] viewport,
float winX,
float winY) throws Exception {
float[] mat4Tmp1 = new float[16];
float[] mat4Tmp2 = new float[16];
float[] vec4Tmp2 = new float[4];
FloatUtil.mapWinToObjCoords(winX, winY, 0, modelview, 0,
projection, 0,
viewport, 0,
nearVector, 0,
mat4Tmp1, mat4Tmp2);
FloatUtil.mapWinToObjCoords(winX, winY, 1, modelview, 0,
projection, 0,
viewport, 0,
farVector, 0,
mat4Tmp1, mat4Tmp2);
// save the results in a vector, far-near
destVector[0] = farVector[0] - nearVector[0];
destVector[1] = farVector[1] - nearVector[1];
destVector[2] = farVector[2] - nearVector[2];
return destVector;
}
'Reconstruct' the model vertices by reading back the values of the vertex buffer that are keyed on the index buffer. I have stepped through the loop and the code does read back the vertex buffer values in the correct order:
//check by pairs of triangles that create a square.
public boolean findIntersection(Wh w, float[] mvp){
float[] a = new float[4];
float[] b = new float[4];
float[] c = new float[4];
boolean rslt = false;
//init boundary vars.
float[] tmp = {-2000,-2000,-2000};
float[] tmp2 = {2000,2000,2000};
//loop thru each triangle. Arrays a,b and c each represent
//a vertex of one triangle. The are 12 in total creating a
//box.
for ( int i = 0; i < w.idxBuffer.length; i += 3 ){
a[0] = w.vertBuffer[ (w.idxBuffer[i + 0] * 3) + 0];
a[1] = w.vertBuffer[ (w.idxBuffer[i + 0] * 3) + 1];
a[2] = w.vertBuffer[ (w.idxBuffer[i + 0] * 3) + 2];
b[0] = w.vertBuffer[ (w.idxBuffer[i + 1] * 3) + 0];
b[1] = w.vertBuffer[ (w.idxBuffer[i + 1] * 3) + 1];
b[2] = w.vertBuffer[ (w.idxBuffer[i + 1] * 3) + 2];
c[0] = w.vertBuffer[ (w.idxBuffer[i + 2] * 3) + 0];
c[1] = w.vertBuffer[ (w.idxBuffer[i + 2] * 3) + 1];
c[2] = w.vertBuffer[ (w.idxBuffer[i + 2] * 3) + 2];
a[3] = 1;
b[3] = 1;
c[3] = 1;
//****Here is where I suspect my problem is **********
//To rebuild the vertices I multiply the vertex from the
//vertex buffer by the model/view/projection matrix, mimicking
//what is done in the shader:
// gl_Position = MVP * vec4(VertexPosition,1.0);
//My hope is that this will provide me with the correct positioning
//of the model so the ray trace will work.
FloatUtil.multMatrixVec(mvp, a, am);
FloatUtil.multMatrixVec(mvp, b, bm);
FloatUtil.multMatrixVec(mvp, c, cm);
//The following creates max/min boundaries used to test for
//a point being inside the box.
//high x values
if (tmp[0] < am[0]){tmp[0] = am[0];}
if (tmp[0] < bm[0]){tmp[0] = bm[0];}
if (tmp[0] < cm[0]){tmp[0] = cm[0];}
//high y values
if (tmp[1] < am[1]){tmp[1] = am[1];}
if (tmp[1] < bm[1]){tmp[1] = bm[1];}
if (tmp[1] < cm[1]){tmp[1] = cm[1];}
//high z values
if (tmp[2] < am[2]){tmp[2] = am[2];}
if (tmp[2] < bm[2]){tmp[2] = bm[2];}
if (tmp[2] < cm[2]){tmp[2] = cm[2];}
//low x values
if (tmp2[0] > am[0]){tmp2[0] = am[0];}
if (tmp2[0] > bm[0]){tmp2[0] = bm[0];}
if (tmp2[0] > cm[0]){tmp2[0] = cm[0];}
//low y values
if (tmp2[1] > am[1]){tmp2[1] = am[1];}
if (tmp2[1] > bm[1]){tmp2[1] = bm[1];}
if (tmp2[1] > cm[1]){tmp2[1] = cm[1];}
//low z values
if (tmp2[2] > am[2]){tmp2[2] = am[2];}
if (tmp2[2] > bm[2]){tmp2[2] = bm[2];}
if (tmp2[2] > cm[2]){tmp2[2] = cm[2];}
}
//The following traces the ray until one of the points falls
//within the boundaries of the box.
float fract = (nearClippingDistance / (farClippingDistance));
System.out.println("x:" + tmp[0] + " " + tmp2[0]);
System.out.println("y:" + tmp[1] + " " + tmp2[1]);
System.out.println("z:" + tmp[2] + " " + tmp2[2]);
//boolean init = false;
float idx = 0;
float[] mult = new float[3];
float[] t = new float[3];
for (idx = fract; idx <= 1; idx += fract) {
mult[0] = farVector[0] * idx;
mult[1] = farVector[1] * idx;
mult[2] = farVector[2] * idx;
VectorUtil.addVec3(t, nearVector, mult);
System.out.println("x:" + t[0] + " y:" + t[1] + " z:" + t[2]);
if (((t[0] <= tmp[0]) && (t[0] >= tmp2[0])) &&
((t[1] <= tmp[1]) && (t[1] >= tmp2[1])) &&
((t[2] <= tmp[2]) && (t[2] >= tmp2[2]))){
//ray intersects this box.
rslt = true;
}
}
return rslt;
}
I have also tried many open source libraries that provide bounding box detecting / plane intersection / ray tracing but none of them work I think because my vertex values are somehow incorrect. Does anyone see a problem with what I am doing here?