void GMBoundingFrustum::createCorners() { corners[0] = intersectionPoint(near, left, top); corners[1] = intersectionPoint(near, right, top); corners[2] = intersectionPoint(near, right, bottom); corners[3] = intersectionPoint(near, left, bottom); corners[4] = intersectionPoint(far, left, top); corners[5] = intersectionPoint(far, right, top); corners[6] = intersectionPoint(far, right, bottom); corners[7] = intersectionPoint(far, left, bottom); }
double Ray::intersect(Triangle triangle) { // check if the normal is facing the right direction if(direction.dot(triangle.normal) < 0) { return -1; } // check if the bounding sphere is hit Vector3 difference = start - triangle.center; if(square(direction.dot(difference)) - difference.dot(difference) + square(triangle.radius) < 0) { return -1; } // get the actual intersectoin point Vector3 point = intersectionPoint(triangle.vertexA, triangle.normal); Vector3 edgeC = point - triangle.vertexA; double AA = triangle.edgeA.dot(triangle.edgeA); double BB = triangle.edgeB.dot(triangle.edgeB); double AB = triangle.edgeA.dot(triangle.edgeB); double AC = triangle.edgeA.dot(edgeC); double BC = triangle.edgeB.dot(edgeC); double D = AA*BB - AB*AB; if(D != 0) { double u = (BB*AC - AB*BC)/D; double v = (AA*BC - AB*AC)/D; if(u+v <= 1 && (v >= 0 && u >= 0)) { return u+v; } } return -1; }
intersectionPoint triangleMesh::intersect(const ray& r) const { intersectionPoint ip; // check bounding box, and bail if not hit if(!_boundingBox.isHit(r)) return ip; // for every triangle for(std::vector<triangle>::const_iterator itr = _triangles.begin(); itr != _triangles.end(); itr++) { // hit & closer? float t; vec3d barycentric; if(itr->intersect(r, barycentric, t)) // hit? if(ip > t) // closer by? ip = intersectionPoint(r, barycentric, t, *itr, _material); } // Done. return ip; }
int intersectionTriangle(unTriangle T1, unTriangle T2, unTriangle *T3) { //connu : dansTriangle(unTriangle T, unPoint P) //connu : intersectionPoint(unPoint S1, unPoint S2, unPoint P1, unPoint P2, unPoint *PI) //on regarde si les sommets de T2 sont dans T1 int i, nbpt = 0, sommetDansTriangle = {0,0,0}; for (i=0; i<3; i++) { //on commence la lecture à 0 dans le tableau sommetDansTriangle[i] = dansTriangle(T1,T2.point[i]); nbpt += sommetDansTriangle[i]; //On stock quels sommets sont dans le triangle précédent } if(nbpt == 1) { //Bon je ne suis pas sur non plus... il faut tester ts les cas possible... for(i=0; i<3; i++) for(j=0; j<3; j++) if(sommetDansTriangle[i]) && i!=j) intersectionPoint(T1.point[i], T1.point[j], T2.point[i], T2.point[j], T3.point[i]); return 1; } else return 0;
void PolygonLine :: computeIntersectionPoints(Line *l, std :: vector< FloatArray > &oIntersectionPoints) { printf("Warning: entering PolygonLine :: computeIntersectionPoints(Line *l, std::vector< FloatArray > &oIntersectionPoints).\n"); #ifdef __BOOST_MODULE int numSeg = this->giveNrVertices() - 1; // Segment bPoint2 lineP1( l->giveVertex ( 1 )->at(1), l->giveVertex ( 1 )->at(2) ); bPoint2 lineP2( l->giveVertex ( 2 )->at(1), l->giveVertex ( 2 )->at(2) ); bSeg2 lineSeg(lineP1, lineP2); double distTol = 1.0e-9; bool foundOverlap = false; // Loop over the crack segments and test each segment for // overlap with the element for ( int segId = 1; segId <= numSeg; segId++ ) { // Crack segment bPoint2 crackP1( this->giveVertex ( segId )->at(1), this->giveVertex ( segId )->at(2) ); bPoint2 crackP2( this->giveVertex ( segId + 1 )->at(1), this->giveVertex ( segId + 1 )->at(2) ); bSeg2 crackSeg(crackP1, crackP2); bPoint2 intersectionPoint(0.0, 0.0); double d = bDist(crackSeg, lineSeg, & intersectionPoint); if ( d < distTol ) { if ( !foundOverlap ) { foundOverlap = true; oIntersectionPoints.emplace_back({intersectionPoint.x(), intersectionPoint.y()}); } } } #endif }
/** Always set m_fp before calling this function!!! * callOnVertices will use data from tmod to find the vertices described by * tmod.ray and tmod.radius, and call m_fp on them. * \param tmod data about the modification * \param call_outside true means that m_fp will be called on non-exsisting vertices as well. tmod.in_terrain flag will distinguish them * \param call_in_square true means that m_fp is called if the distance is < r * along (x || z) axis */ void Terrain::callOnVertices(TerrainMod* tmod, bool call_outside, bool call_in_square) { s32 ix, iz, dx, dz; vector2df cpos; if (!intersectionPoint(tmod->ray, tmod->radius, &cpos, &ix, &iz)) return; dx = (s32)(tmod->radius / (m_x / m_nx) + 1); dz = (s32)(tmod->radius / (m_z / m_nz) + 1); tmod->index = 0; for (s32 j = -dz; j <= dz; j++) for (s32 i = -dx; i <= dx; i++) { tmod->in_terrain = true; // check if the point is outside of the terrain if (ix + i < 1 || ix + i >(s32)m_nx - 2 || iz + j < 1 || iz + j >(s32)m_nz - 2) tmod->in_terrain = false; if (call_outside && !tmod->in_terrain) (*this.*m_fp_h)(*tmod, ix, iz, i, j); else if (tmod->in_terrain) { S3DVertex2TCoords vert = m_mesh.vertices[(iz + j) * m_nx + ix + i]; vector2df pos; pos = vector2df(vert.Pos.X, vert.Pos.Z); // check if the point is in radius tmod->dist = tmod->radius - (cpos - pos).getLength(); if (tmod->dist > 0 || call_in_square) { (*this.*m_fp_h)(*tmod, ix, iz, i, j); } } tmod->index += 1; } // for loop - square } // callOnVertices
int main() { Node * list1 = new Node(3); list1->next = new Node(6); list1->next->next = new Node(9); list1->next->next->next = new Node(12); list1->next->next->next->next = new Node(15); list1->next->next->next->next->next = new Node(18); Node * list2 = new Node(7); list2->next = new Node(10); list2->next->next = list1->next->next->next; printList(list1); printList(list2); Node * intersectingNode = intersectionPoint( list1 , list2 ); if (intersectingNode) { std::cout << "Intersecting Node of lists is :" << intersectingNode->data << std::endl; } else { std::cout << "Lists do not interset" << std::endl; } return 0; }
// ---------------------------------------------------------------------------- vector3df Terrain::placeBBtoGround(const aabbox3d<f32>& box, line3d<float> ray) { int ix, iz, dx, dz; vector2df cpos; if (!intersectionPoint(ray, 0, &cpos, &ix, &iz)) return vector3df(cpos.X,0,cpos.Y); f32 max_h = -30000; dx = (int)(box.MaxEdge.X / (m_x / m_nx) + 1); dz = (int)(box.MaxEdge.Z / (m_z / m_nz) + 1); for (int i = -dx; i <= dx; i++) for (int j = -dz; j <= dz; j++) { // check if the point is outside of the terrain if (ix + i > 0 && ix + i < (s32)m_nx && iz + j > 0 && iz + j < (s32)m_nz) { max_h = std::max((m_mesh.vertices[(iz + j) * m_nx + ix + i].Pos.Y),max_h); } // this square point is a valid vertex } // for loop - critical rectangle return vector3df(cpos.X, max_h - box.MinEdge.Y, cpos.Y); } // placeBBtoGround
intersectionList::intersectionList(UnitigVector &unitigs) { for (uint32 ti=0; ti<unitigs.size(); ti++) { Unitig *tig = unitigs[ti]; if (tig == NULL) continue; intersectionEvidence *evidence = new intersectionEvidence [tig->ufpath.size()]; for (uint32 fi=0; fi<tig->ufpath.size(); fi++) { ufNode *frg = &tig->ufpath[fi]; if (OG->isContained(frg->ident)) continue; // For my best overlap, the ID of the unitig that the overlapping fragment is in. evidence[fi].edge5 = *OG->getBestEdgeOverlap(frg->ident, false); evidence[fi].edge3 = *OG->getBestEdgeOverlap(frg->ident, true); evidence[fi].frag5tig = tig->fragIn(evidence[fi].edge5.fragId()); evidence[fi].frag3tig = tig->fragIn(evidence[fi].edge3.fragId()); // Do NOT initialize these! An earlier fragment could have already confirmed an end. // Properly, only the 5' end of a forward fragment (or 3' end of a reverse fragment) can be // confirmed already (otherwise the tig is nonsense), but we don't yet check that. // //evidence[fi].frag5confirmed = false; //evidence[fi].frag3confirmed = false; // But, because the path could be promiscuous, not every overlap to a different tig is bad. // // If my best overlap is to a different tig, but there is an overlapping fragment (in the // unitig placement) with a best edge to me, I'm still good. The BOG build this unitig using // the edge from the other fragment to me. // // If the fragments do not overlap in the layout (yet the best edge still exists) that is a // self-intersection. // // The two blocks are identical, except for 'edge3' and 'edge5'. if (evidence[fi].frag5tig == tig->id()) { uint32 ti = tig->pathPosition(evidence[fi].edge5.fragId()); ufNode *trg = &tig->ufpath[ti]; uint32 minf = (frg->position.bgn < frg->position.end) ? frg->position.bgn : frg->position.end; uint32 maxf = (frg->position.bgn < frg->position.end) ? frg->position.end : frg->position.bgn; uint32 mint = (trg->position.bgn < trg->position.end) ? trg->position.bgn : trg->position.end; uint32 maxt = (trg->position.bgn < trg->position.end) ? trg->position.end : trg->position.bgn; // If they overlap, mark as confirmed, else remember an intersection. if (((minf < mint) && (mint < maxf)) || // t begins inside f ((mint < minf) && (minf < maxt))) { // f begins inside t if (evidence[fi].edge5.frag3p()) evidence[ti].frag3confirmed = true; else evidence[ti].frag5confirmed = true; } else { evidence[fi].frag5self = true; // Not the correct place to report this. Some of these get confirmed by later fragments. //writeLog("BUG1 F: %d,%d T %d,%d\n", minf, maxf, mint, maxt); //writeLog("INTERSECT from unitig %d frag %d end %d TO unitig %d frag %d end %d (SELF)\n", // tig->id(), frg->ident, 5, evidence[fi].frag5tig, evidence[fi].edge5.fragId(), evidence[fi].edge5.frag3p() ? 3 : 5); } } if (evidence[fi].frag3tig == tig->id()) { uint32 ti = tig->pathPosition(evidence[fi].edge3.fragId()); ufNode *trg = &tig->ufpath[ti]; uint32 minf = (frg->position.bgn < frg->position.end) ? frg->position.bgn : frg->position.end; uint32 maxf = (frg->position.bgn < frg->position.end) ? frg->position.end : frg->position.bgn; uint32 mint = (trg->position.bgn < trg->position.end) ? trg->position.bgn : trg->position.end; uint32 maxt = (trg->position.bgn < trg->position.end) ? trg->position.end : trg->position.bgn; if (((minf < mint) && (mint < maxf)) || // t begins inside f ((mint < minf) && (minf < maxt))) { // f begins inside t if (evidence[fi].edge3.frag3p()) evidence[ti].frag3confirmed = true; else evidence[ti].frag5confirmed = true; } else { evidence[fi].frag3self = true; // Not the correct place to report this. Some of these get confirmed by later fragments. //writeLog("BUG2 F: %d,%d T %d,%d\n", minf, maxf, mint, maxt); //writeLog("INTERSECT from unitig %d frag %d end %d TO unitig %d frag %d end %d (SELF)\n", // tig->id(), frg->ident, 3, evidence[fi].frag3tig, evidence[fi].edge3.fragId(), evidence[fi].edge3.frag3p() ? 3 : 5); } } } // // Build the list. // for (uint32 fi=0; fi<tig->ufpath.size(); fi++) { ufNode *frg = &tig->ufpath[fi]; if ((evidence[fi].frag5tig != 0) && (evidence[fi].frag5tig != tig->id()) && (evidence[fi].frag5confirmed == false)) isects.push_back(intersectionPoint(evidence[fi].edge5, frg->ident, false, false)); if ((evidence[fi].frag5tig == tig->id()) && (evidence[fi].frag5self == true) && (evidence[fi].frag5confirmed == false)) isects.push_back(intersectionPoint(evidence[fi].edge5, frg->ident, false, true)); if ((evidence[fi].frag3tig != 0) && (evidence[fi].frag3tig != tig->id()) && (evidence[fi].frag3confirmed == false)) isects.push_back(intersectionPoint(evidence[fi].edge3, frg->ident, true, false)); if ((evidence[fi].frag3tig == tig->id()) && (evidence[fi].frag3self == true) && (evidence[fi].frag3confirmed == false)) isects.push_back(intersectionPoint(evidence[fi].edge3, frg->ident, true, true)); } delete [] evidence; } // Sort the intersections by the ID of the intersected fragment, then build an index into the array. std::sort(isects.begin(), isects.end()); // Terminate the intersection list with a sentinal intersection. This is CRITICAL // to the way we iterate over intersections. isects.push_back(intersectionPoint(BestEdgeOverlap(), 0, true, true)); // Build a map from fragment id to the first intersection in the list. for (uint32 i=0; i<isects.size(); i++) { isectsNum[isects[i].isectFrg]++; if (isectsMap.find(isects[i].isectFrg) == isectsMap.end()) isectsMap[isects[i].isectFrg] = i; } }
void disp(void){ //clear all pixels: glClear(GL_COLOR_BUFFER_BIT); // RayTracing loop for (int i = 0; i < (viewport.xvmax - viewport.xvmin); i++) { for (int j = 0; j < (viewport.yvmax - viewport.yvmin); j++) { int intersection_object = -1; // negative to return false / no intersection // maximum positive double-precision floating-point number // found on Wikipedia (link: https://en.wikipedia.org/wiki/Double-precision_floating-point_format) double t = 0x7fefffffffffffff; Ray ray, shadow_ray, reflected_ray; Pixel pixel; Intersection intersection, current_intersection, shadow_ray_intersection, reflected_ray_intersection, current_reflected_intersection; double shadowAngle; bool bShadow = false; pixel.i = i; pixel.j = j; // initiate RayTrace RayTrace(&ray, &view_point, &viewport, &pixel, &camera, -focal_distance); // check if ray hits an object for (int i = 0; i < NUM_SPHERES; i++) { if (intersectionPoint(&ray, &sphere[i], &intersection)) { // there is an intersection between ray and object // calculate normal intersection normalIntersection(&sphere[i], &intersection, &ray); // if the intersection minimum is smaller than current infinity number if (intersection.tmin < t) { t = intersection.tmin; // found intersection intersection_object = i; // intersection sphere number copyIntersection(¤t_intersection, &intersection); // copy intersection } } } // determine the pixel colour if (intersection_object > -1) { ShadowRayTrace( &shadow_ray, &intersection, &light ); shadowAngle = shadow_ray.direction.dotproduct( intersection.normal ); for (int i = 0; i < NUM_SPHERES; i++) { if (i != intersection_object) { if (intersectionPoint(&shadow_ray, &sphere[i], &shadow_ray_intersection) && (shadowAngle > 0.0)) bShadow = true; } } if (bShadow) { // if object in shadow, add only ambiental light to the surface colour colour = shadow(&sphere[intersection_object].ka_rgb, ambient_light_intensity); } else { // the intersection renders normal colour colour = render(¤t_intersection, &light, &view_point, &sphere[intersection_object].kd_rgb, &sphere[intersection_object].ks_rgb, &sphere[intersection_object].ka_rgb, sphere[intersection_object].shininess, light_intensity, ambient_light_intensity); } glColor3f(colour.x, colour.y, colour.z); glBegin(GL_POINTS); glVertex2i(i, j); glEnd(); intersection_object = -1; bShadow = false; } else { // draw the pixel with background colour glColor3f(0.0, 0.0, 0.0); glBegin(GL_POINTS); glVertex2i(i, j); glEnd(); intersection_object = -1; bShadow = false; } t = 0x7fefffffffffffff; } } glutSwapBuffers(); }
Point vanishFromSky(const Mat& img) { auto sth=skyDetect(img); return intersectionPoint(sth[0],sth[1]); }
// called by Tcl Event loop to check for new data void TclTimerProc(ClientData clientData) { if (!isPenLoaderStarted()) { printLog("Timer stopped\n"); return; } // get the next stroke to analyze Stroke stroke = getNextAvailableStroke(); Tcl_CreateTimerHandler(TCL_TIMER_MS, &TclTimerProc, NULL); if (stroke.nSamples == 0) { return; } if (gameFinished) { printLog(" This game is already finished, skipping stroke\n"); return; } // if already have the board, determine and make the move if (numBoardLines == 4) { Line testLine = newLine(boardCenterX, boardCenterY, stroke.bounds.centerX, stroke.bounds.centerY); int crossing = (doLinesIntersect(&testLine, boardLeft)) ? CROSS_LEFT : CROSS_NONE; crossing |= (doLinesIntersect(&testLine, boardRight)) ? CROSS_RIGHT : CROSS_NONE; crossing |= (doLinesIntersect(&testLine, boardTop)) ? CROSS_TOP : CROSS_NONE; crossing |= (doLinesIntersect(&testLine, boardBottom)) ? CROSS_BOTTOM : CROSS_NONE; int move = CrossToMove[crossing]; if (move == -1) { printLog(" Invalid crossing value detected: %d, skipping\n", crossing); return; } else if (movesDone[move] != 0) { printLog(" Skipping duplicate move: %d\n", move); return; } movesDone[move] = currentPlayer; currentPlayer = (currentPlayer % 2) + 1; printLog(" Making move %d\n", move); char moveCommand[30]; sprintf(moveCommand, "ReturnFromHumanMove %d", move); Tcl_Eval(tclInterpreter, moveCommand); if (checkForFinishCondition()) { gameFinished = TRUE; printLog(" Game finished\n"); } return; } // otherwise, add the stroke to the board if (stroke.type != STROKE_LINE) { printLog(" Board isn't finished, skipping non-LINE stroke\n"); return; } boardLines[numBoardLines] = stroke.line; numBoardLines++; if (numBoardLines < 4) { return; } // determine board lines (two pairs of non-intersecting lines) int idx, match1b, match2a, match2b; match1b = 0; for (idx = 1; idx < 4; idx++) { if (!doLinesIntersect(&boardLines[0], &boardLines[idx])) { if (match1b != 0) { // matched twice, so something is wrong match1b = 0; break; } match1b = idx; match2a = (idx == 1) ? 2 : 1; match2b = (idx == 3) ? 2 : 3; } } // verify that matched lines intersect properly if ((match1b == 0) || (!doLinesIntersect(&boardLines[match1b], &boardLines[match2a])) || (!doLinesIntersect(&boardLines[match1b], &boardLines[match2b])) || (doLinesIntersect(&boardLines[match2a], &boardLines[match2b]))) { printLog(" Could not match board lines, trying again without first line\n"); boardLines[0] = boardLines[1]; boardLines[1] = boardLines[2]; boardLines[2] = boardLines[3]; numBoardLines = 3; return; } // assign proper sides (within 90 degree range away from pure vertical or horizontal) double angle = fabs(boardLines[0].angleDegrees); BOOL isLeft, isTop; int leftIdx, rightIdx, topIdx, bottomIdx; if (angle >= 45 && angle < 135) { // match 1 is vertical, match 2 is horizontal isLeft = (boardLines[0].centerX < boardLines[match1b].centerX); isTop = (boardLines[match2a].centerY < boardLines[match2b].centerY); leftIdx = isLeft ? 0 : match1b; rightIdx = isLeft ? match1b : 0; topIdx = isTop ? match2a : match2b; bottomIdx = isTop ? match2b : match2a; } else { // match 2 is vertical, match 1 is horizontal isLeft = (boardLines[match2a].centerX < boardLines[match2b].centerX); isTop = (boardLines[0].centerY < boardLines[match1b].centerY); leftIdx = isLeft ? match2a : match2b; rightIdx = isLeft ? match2b : match2a; topIdx = isTop ? 0 : match1b; bottomIdx = isTop ? match1b : 0; } boardLeft = &boardLines[leftIdx]; boardRight = &boardLines[rightIdx]; boardTop = &boardLines[topIdx]; boardBottom = &boardLines[bottomIdx]; // calculate center of the board (average of the 4 intersection points) double iLeftTop = intersectionPoint(boardLeft, boardTop); double iLeftBottom = intersectionPoint(boardLeft, boardBottom); double iRightTop = intersectionPoint(boardRight, boardTop); double iRightBottom = intersectionPoint(boardRight, boardBottom); boardCenterX = projectedX(boardLeft, iLeftTop, TRUE); boardCenterX += projectedX(boardLeft, iLeftBottom, TRUE); boardCenterX += projectedX(boardRight, iRightTop, TRUE); boardCenterX += projectedX(boardRight, iRightBottom, TRUE); boardCenterY = projectedY(boardLeft, iLeftTop, TRUE); boardCenterY += projectedY(boardLeft, iLeftBottom, TRUE); boardCenterY += projectedY(boardRight, iRightTop, TRUE); boardCenterY += projectedY(boardRight, iRightBottom, TRUE); boardCenterX /= 4; boardCenterY /= 4; printLog(" Detected board strokes: Left %d, Right %d, Top %d, Bottom %d, with center (%.3f, %.3f)\n", \ leftIdx, rightIdx, topIdx, bottomIdx, boardCenterX, boardCenterY); }
Intersection* Plane3D::testRayIntersection(Ray r) { /*std::cout << "ray start pos " << r.startPosition.x << " " << r.startPosition.y << " " << r.startPosition.z << std::endl; std::cout << "ray direction " << r.direction.x << " " << r.direction.y << " " << r.direction.z << std::endl;*/ //The ray is described by Point on ray = start(O) + direction(D) * t //If a point B on the ray hits a surface it must be inside the plane of that surface //We can check if B is inside the surface by making a vector between a point on the surface(A) and B //and dot multiply it with the plan's normal and see if it becomes zero //(A-B)*n = 0 //Then the point B is on the plane //We want to know at what t-value we get a point B on the ray that is inside the plane //After some calculations this formula was found //t = (O - A) dot n / D dot n //translate the plane to it's local coordinate system rotate it and tranlate it back glm::mat4 translation = glm::translate(glm::mat4(1.f), -position); glm::mat4 translationBack = glm::translate(glm::mat4(1.f), position); glm::mat4 rotat = glm::rotate(glm::rotate(glm::rotate(glm::mat4(1.f), -rotation.x, glm::vec3(1, 0, 0)), -rotation.y, glm::vec3(0, 1, 0)), -rotation.z, glm::vec3(0, 0, 1)); glm::mat4 toLocal = rotat * translation; glm::vec4 temp(translationBack * toLocal * glm::vec4(position + glm::vec3(-dimensions.x / 2, -dimensions.y / 2, 0), 1)); glm::vec3 lowerLeftCorner(temp.x, temp.y, temp.z); temp = glm::vec4(translationBack * toLocal * glm::vec4(position + glm::vec3(dimensions.x / 2, -dimensions.y / 2, 0), 1)); glm::vec3 lowerRightCorner(temp.x, temp.y, temp.z); temp = glm::vec4(translationBack * toLocal * glm::vec4(position + glm::vec3(-dimensions.x / 2, dimensions.y / 2, 0), 1)); glm::vec3 upperLeftCorner(temp.x, temp.y, temp.z); //Find plane normal glm::vec3 planeNormal(glm::normalize(glm::cross(lowerRightCorner - lowerLeftCorner, upperLeftCorner - lowerLeftCorner))); /*std::cout << "lower left " << lowerLeftCorner.x << " " << lowerLeftCorner.y << " " << lowerLeftCorner.z << std::endl; std::cout << "lower right " << lowerRightCorner.x << " " << lowerRightCorner.y << " " << lowerRightCorner.z << std::endl; std::cout << "upper left " << upperLeftCorner.x << " " << upperLeftCorner.y << " " << upperLeftCorner.z << std::endl; std::cout << "ray start pos " << r.startPosition.x << " " << r.startPosition.y << " " << r.startPosition.z << std::endl; std::cout << "ray direction " << r.direction.x << " " << r.direction.y << " " << r.direction.z << std::endl;*/ //If D dot n == 0 the direction goes along the plane and the ray won't hit the plane //If D dot n < 0 the surface can't be seen from the ray's starting point //But if the ray is a shadow ray it doesn't matter if we can't see the object, just that it is in the way float DdotN = glm::dot(-r.direction, planeNormal); if (r.shadowRay) { if (DdotN < EPSILON && DdotN > -EPSILON) return nullptr; } else if (DdotN < EPSILON){ //std::cout << "DdotN <= 0 " << std::endl; return nullptr; } //std::cout << "ray direction " << r.direction.x << " " << r.direction.y << " " << r.direction.z << std::endl; //std::cout << "planeNormal " << planeNormal.x << " " << planeNormal.y << " " << planeNormal.z << std::endl; //Find point inside plane -> position, which is the center of the plane //Find intersection float t; if (r.startPosition - position != planeNormal) { t = glm::dot(r.startPosition - position, planeNormal) / DdotN; //std::cout << "1t = " << t << std::endl; } else { glm::vec3 temp = r.startPosition - lowerLeftCorner; //std::cout << "vector on plane? " << temp.x << " " << temp.y << " " << temp.z << std::endl; t = glm::dot(r.startPosition - lowerLeftCorner, planeNormal) / DdotN; //std::cout << "2t = " << t << " dot " << glm::dot(r.startPosition - lowerLeftCorner, planeNormal) << std::endl; } //If t < 0 the plane is behind or inside the ray origin and we aren't interested in it if (t < EPSILON){ //std::cout << "t <= 0 " << std::endl; return nullptr; } //Is B inside the surface bounds? //Create vectors that decribe the bounds //"Inside" is on the right side of the vector temp = glm::vec4(translationBack * toLocal * glm::vec4(position + glm::vec3(dimensions.x / 2, dimensions.y / 2, 0), 1)); glm::vec3 upperRightCorner(temp.x, temp.y, temp.z); //std::cout << "upper right " << upperRightCorner.x << " " << upperRightCorner.y << " " << upperRightCorner.z << std::endl; glm::vec3 leftSide(upperLeftCorner - lowerLeftCorner); glm::vec3 topSide(upperRightCorner - upperLeftCorner); glm::vec3 rightSide(lowerRightCorner - upperRightCorner); glm::vec3 bottomSide(lowerLeftCorner - lowerRightCorner); //To know if B is on the correct side of the vector we take the cross product of //the bounding vector and a vector from the same starting point as the bounding vector and ends in B //If the result is a vector along the plane's normal, the point B is on the correct side of the bounding vector //If the result is a vector against the plane's normal the point is on the wrong side //To know if the vector is going along the normal we take the dot product between them //If it is larger than zero they go with each other //leftSide glm::vec3 B(r.startPosition + t * r.direction); glm::vec3 Bvector(B - lowerLeftCorner); if (glm::dot(glm::cross(Bvector, leftSide), planeNormal) > 0) { //topSide Bvector = glm::vec3(B - upperLeftCorner); if (glm::dot(glm::cross(Bvector, topSide), planeNormal) > 0) { //rightSide Bvector = glm::vec3(B - upperRightCorner); if (glm::dot(glm::cross(Bvector, rightSide), planeNormal) > 0) { //bottomSide Bvector = glm::vec3(B - lowerRightCorner); if (glm::dot(glm::cross(Bvector, bottomSide), planeNormal) > 0) { // If the object is blocked if (t > r.tMax){ //std::cout << "t > r.tMax" << std::endl; return nullptr; } //else r.tMax = t; glm::vec3 intersectionPoint(r.startPosition + t * r.direction); //std::cout << "intersected object" << std::endl; return new Intersection(intersectionPoint, planeNormal, color, reflectionCoef, t); } } } } //std::cout << "not inside bounds" << std::endl; return nullptr; }
/// /// \brief Get the intersection point between an AABB and a Ray /// static std::pair<bool, float> intersectionPoint(const Ray& r, const AABB& b) { return intersectionPoint(b, r); }
intersectionPoint boundingVolumeHierarchy::intersect(const ray& r) const { if(_root->isBoundingBoxHit(r)) return _root->intersect(r, *_mesh); else return intersectionPoint(); }