Skip to content

Commit 78751d8

Browse files
committed
moved ray casting code to PGraphicsOpenGL
1 parent fc581e0 commit 78751d8

File tree

2 files changed

+295
-268
lines changed

2 files changed

+295
-268
lines changed

core/src/processing/opengl/PGraphicsOpenGL.java

Lines changed: 291 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,27 @@ public void dispose() {
520520

521521
// ........................................................
522522

523+
protected PMatrix3D eyeMatrix;
524+
protected PMatrix3D objMatrix;
525+
526+
public float forwardX, forwardY, forwardZ;
527+
public float rightX, rightY, rightZ;
528+
public float upX, upY, upZ;
529+
530+
// Variables used in ray casting
531+
protected PVector[] ray;
532+
protected PVector hit = new PVector();
533+
protected PVector screen = new PVector();
534+
protected PVector objCenter = new PVector();
535+
protected PVector objToOrig = new PVector();
536+
protected PVector origInObjCoord = new PVector();
537+
protected PVector hitInObjCoord = new PVector();
538+
protected PVector dirInObjCoord = new PVector();
539+
protected PVector origInWorldCoord = new PVector();
540+
protected PVector dirInWorldCoord = new PVector();
541+
542+
// ........................................................
543+
523544
// Error strings:
524545

525546
static final String OPENGL_THREAD_ERROR =
@@ -830,6 +851,264 @@ public boolean saveImpl(String filename) {
830851
}
831852

832853

854+
//////////////////////////////////////////////////////////////
855+
856+
// EYE/OBJECT MATRICES
857+
858+
859+
@Override
860+
public PMatrix3D getEyeMatrix() {
861+
return getEyeMatrix(null);
862+
}
863+
864+
865+
@Override
866+
public PMatrix3D getEyeMatrix(PMatrix3D target) {
867+
if (target == null) {
868+
target = new PMatrix3D();
869+
}
870+
float sign = cameraUp ? +1 : -1;
871+
target.set(rightX, sign * upX, forwardX, cameraX,
872+
rightY, sign * upY, forwardY, cameraY,
873+
rightZ, sign * upZ, forwardZ, cameraZ,
874+
0, 0, 0, 1);
875+
return target;
876+
}
877+
878+
879+
@Override
880+
public PMatrix3D getObjectMatrix() {
881+
PMatrix3D mat = new PMatrix3D();
882+
mat.set(modelviewInv);
883+
mat.apply(camera);
884+
return mat;
885+
}
886+
887+
888+
@Override
889+
public PMatrix3D getObjectMatrix(PMatrix3D target) {
890+
if (target == null) {
891+
target = new PMatrix3D();
892+
}
893+
target.set(modelviewInv);
894+
target.apply(camera);
895+
return target;
896+
}
897+
898+
899+
@Override
900+
public void eye() {
901+
eyeMatrix = getEyeMatrix(eyeMatrix);
902+
903+
// Erasing any previous transformation in modelview
904+
modelview.set(camera);
905+
modelview.apply(eyeMatrix);
906+
907+
// The 3x3 block of eyeMatrix is orthogonal, so taking the transpose inverts it...
908+
eyeMatrix.transpose();
909+
// ...and then invert the translation separately:
910+
eyeMatrix.m03 = -cameraX;
911+
eyeMatrix.m13 = -cameraY;
912+
eyeMatrix.m23 = -cameraZ;
913+
eyeMatrix.m30 = 0;
914+
eyeMatrix.m31 = 0;
915+
eyeMatrix.m32 = 0;
916+
917+
// Applying the inverse of the previous transformations in the opposite order
918+
// to compute the modelview inverse
919+
modelviewInv.set(eyeMatrix);
920+
modelviewInv.preApply(cameraInv);
921+
922+
updateProjmodelview();
923+
}
924+
925+
926+
//////////////////////////////////////////////////////////////
927+
928+
// RAY CASTING
929+
930+
931+
@Override
932+
public PVector[] getRayFromScreen(float screenX, float screenY, PVector[] ray) {
933+
if (ray == null || ray.length < 2) {
934+
ray = new PVector[2];
935+
ray[0] = new PVector();
936+
ray[1] = new PVector();
937+
}
938+
getRayFromScreen(screenX, screenY, ray[0], ray[1]);
939+
return ray;
940+
}
941+
942+
943+
@Override
944+
public void getRayFromScreen(float screenX, float screenY, PVector origin, PVector direction) {
945+
eyeMatrix = getEyeMatrix(eyeMatrix);
946+
947+
// Transforming screen coordinates to world coordinates
948+
screen.x = screenX;
949+
screen.y = screenY;
950+
screen.z = 0;
951+
eyeMatrix.mult(screen, origin);
952+
953+
// The direction of the ray is simply extracted from the third column of the eye matrix (the
954+
// forward vector).
955+
direction.set(eyeMatrix.m02, eyeMatrix.m12, eyeMatrix.m22);
956+
}
957+
958+
959+
@Override
960+
public boolean intersectsSphere(float r, float screenX, float screenY) {
961+
ray = getRayFromScreen(screenX, screenY, ray);
962+
return intersectsSphere(r, ray[0], ray[1]);
963+
}
964+
965+
966+
@Override
967+
public boolean intersectsSphere(float r, PVector origin, PVector direction) {
968+
// Get the center of the sphere in world coordinates
969+
objCenter.x = modelview.m03;
970+
objCenter.y = modelview.m13;
971+
objCenter.z = modelview.m23;
972+
973+
PVector.sub(origin, objCenter, objToOrig);
974+
float d = objToOrig.mag();
975+
976+
// The eye is inside the sphere
977+
if (d <= r) return true;
978+
979+
// Check if sphere is in front of ray
980+
if (PVector.dot(objToOrig, direction) > 0) return false;
981+
982+
// Check intersection of ray with sphere
983+
float b = 2 * PVector.dot(direction, objToOrig);
984+
float c = d * d - r * r;
985+
float det = b * b - 4 * c;
986+
return det >= 0;
987+
}
988+
989+
990+
@Override
991+
public boolean intersectsBox(float size, float screenX, float screenY) {
992+
ray = getRayFromScreen(screenX, screenY, ray);
993+
return intersectsBox(size, size, size, ray[0], ray[1]);
994+
}
995+
996+
997+
@Override
998+
public boolean intersectsBox(float w, float h, float d, float screenX, float screenY) {
999+
ray = getRayFromScreen(screenX, screenY, ray);
1000+
return intersectsBox(w, h, d, ray[0], ray[1]);
1001+
}
1002+
1003+
1004+
@Override
1005+
public boolean intersectsBox(float size, PVector origin, PVector direction) {
1006+
return intersectsBox(size, size, size, origin, direction);
1007+
}
1008+
1009+
1010+
@Override
1011+
public boolean intersectsBox(float w, float h, float d, PVector origin, PVector direction) {
1012+
objMatrix = getObjectMatrix(objMatrix);
1013+
objMatrix.mult(origin, origInObjCoord);
1014+
PVector.add(origin, direction, hit);
1015+
objMatrix.mult(hit, hitInObjCoord);
1016+
1017+
PVector.sub(hitInObjCoord, origInObjCoord, dirInObjCoord);
1018+
return lineIntersectsAABB(origInObjCoord, dirInObjCoord, w, h, d);
1019+
}
1020+
1021+
1022+
// Line intersection with an axis-aligned bounding box (AABB), calculated using the algorithm
1023+
// from Amy William et al: http:// dl.acm.org/citation.cfm?id=1198748
1024+
protected boolean lineIntersectsAABB(PVector orig, PVector dir, float w, float h, float d) {
1025+
float minx = -w/2;
1026+
float miny = -h/2;
1027+
float minz = -d/2;
1028+
1029+
float maxx = +w/2;
1030+
float maxy = +h/2;
1031+
float maxz = +d/2;
1032+
1033+
float idx = 1/dir.x;
1034+
float idy = 1/dir.y;
1035+
float idz = 1/dir.z;
1036+
1037+
boolean sdx = idx < 0;
1038+
boolean sdy = idy < 0;
1039+
boolean sdz = idz < 0;
1040+
1041+
float bbx = sdx ? maxx : minx;
1042+
float txmin = (bbx - orig.x) * idx;
1043+
bbx = sdx ? minx : maxx;
1044+
float txmax = (bbx - orig.x) * idx;
1045+
float bby = sdy ? maxy : miny;
1046+
float tymin = (bby - orig.y) * idy;
1047+
bby = sdy ? miny : maxy;
1048+
float tymax = (bby - orig.y) * idy;
1049+
1050+
if ((txmin > tymax) || (tymin > txmax)) {
1051+
return false;
1052+
}
1053+
if (tymin > txmin) {
1054+
txmin = tymin;
1055+
}
1056+
if (tymax < txmax) {
1057+
txmax = tymax;
1058+
}
1059+
1060+
float bbz = sdz ? maxz : minz;
1061+
float tzmin = (bbz - orig.z) * idz;
1062+
bbz = sdz ? minz : maxz;
1063+
float tzmax = (bbz - orig.z) * idz;
1064+
1065+
if ((txmin > tzmax) || (tzmin > txmax)) {
1066+
return false;
1067+
}
1068+
if (tzmin > txmin) {
1069+
txmin = tzmin;
1070+
}
1071+
if (tzmax < txmax) {
1072+
txmax = tzmax;
1073+
}
1074+
1075+
if ((txmin < defCameraFar) && (txmax > 0)) {
1076+
// The intersection coordinates:
1077+
// x = orig.x + txmin * dir.x;
1078+
// y = orig.y + txmin * dir.y;
1079+
// z = orig.z + txmin * dir.z;
1080+
return true;
1081+
}
1082+
1083+
return false;
1084+
}
1085+
1086+
1087+
@Override
1088+
public PVector intersectsPlane(float screenX, float screenY) {
1089+
ray = getRayFromScreen(screenX, screenY, ray);
1090+
return intersectsPlane(ray[0], ray[1]);
1091+
}
1092+
1093+
1094+
@Override
1095+
public PVector intersectsPlane(PVector origin, PVector direction) {
1096+
modelview.mult(origin, origInWorldCoord);
1097+
modelview.mult(direction, dirInWorldCoord);
1098+
1099+
// Ray-plane intersection algorithm
1100+
PVector w = new PVector(-origInWorldCoord.x, -origInWorldCoord.y, -origInWorldCoord.z);
1101+
float d = PApplet.abs(dirInWorldCoord.z * dirInWorldCoord.z);
1102+
1103+
if (d == 0) return null;
1104+
1105+
float k = PApplet.abs((w.z * w.z)/d);
1106+
PVector p = PVector.add(origInWorldCoord, dirInWorldCoord).setMag(k);
1107+
1108+
return p;
1109+
}
1110+
1111+
8331112
//////////////////////////////////////////////////////////////
8341113

8351114
// IMAGE METADATA FOR THIS RENDERER
@@ -4605,6 +4884,18 @@ public void camera(float eyeX, float eyeY, float eyeZ,
46054884
y1 = -z0 * x2 + z2 * x0;
46064885
y2 = z0 * x1 - z1 * x0;
46074886

4887+
forwardX = 0;
4888+
forwardY = 0;
4889+
forwardZ = 1;
4890+
4891+
rightX = 1;
4892+
rightY = 0;
4893+
rightZ = 0;
4894+
4895+
this.upX = 0;
4896+
this.upY = -1;
4897+
this.upZ = 0;
4898+
46084899
// Cross product gives area of parallelogram, which is < 1.0 for
46094900
// non-perpendicular unit-length vectors; so normalize x, y here:
46104901
float xmag = PApplet.sqrt(x0 * x0 + x1 * x1 + x2 * x2);

0 commit comments

Comments
 (0)