Ejemplo n.º 1
0
Archivo: bvh.cpp Proyecto: AI42/OM3D
bool BVHAccel::IntersectQ(const Ray &ray, Intersection *isect, float* barycentrics) const {
    if (!nodes) return false;
    PBRT_BVH_INTERSECTION_STARTED(const_cast<BVHAccel *>(this), const_cast<Ray *>(&ray));	
    bool hit = false;
    //PbrtPoint origin = ray(ray.mint);
    Vector invDir(1.f / ray.d.x, 1.f / ray.d.y, 1.f / ray.d.z);
    uint32_t dirIsNeg[3] = { invDir.x < 0, invDir.y < 0, invDir.z < 0 };
    // Follow ray through BVH nodes to find primitive intersections
    uint32_t todoOffset = 0, nodeNum = 0;
    uint32_t todo[64];
	while (true) {
        const LinearBVHNode *node = &nodes[nodeNum];
        // Check ray against BVH node
        if (::IntersectP(node->bounds, ray, invDir, dirIsNeg)) {
            if (node->nPrimitives > 0) {
                // Intersect ray with primitives in leaf BVH node
                PBRT_BVH_INTERSECTION_TRAVERSED_LEAF_NODE(const_cast<LinearBVHNode *>(node));
                for (uint32_t i = 0; i < node->nPrimitives; ++i)
                {
                    PBRT_BVH_INTERSECTION_PRIMITIVE_TEST(const_cast<Primitive *>(primitives[node->primitivesOffset+i].GetPtr()));
                    if (primitives[node->primitivesOffset+i]->IntersectQ(ray, isect, barycentrics))
                    {
                        PBRT_BVH_INTERSECTION_PRIMITIVE_HIT(const_cast<Primitive *>(primitives[node->primitivesOffset+i].GetPtr()));
                        hit = true;
                    }
                    else {
                        PBRT_BVH_INTERSECTION_PRIMITIVE_MISSED(const_cast<Primitive *>(primitives[node->primitivesOffset+i].GetPtr()));
					}
                }
                if (todoOffset == 0) break;
                nodeNum = todo[--todoOffset];
            }
            else {
                // Put far BVH node on _todo_ stack, advance to near node
                PBRT_BVH_INTERSECTION_TRAVERSED_INTERIOR_NODE(const_cast<LinearBVHNode *>(node));
                if (dirIsNeg[node->axis]) {
					todo[todoOffset++] = nodeNum + 1;
					nodeNum = node->secondChildOffset;
                }
                else {
					todo[todoOffset++] = node->secondChildOffset;
					nodeNum = nodeNum + 1;
                }
            }
        }
        else {
            if (todoOffset == 0) break;
            nodeNum = todo[--todoOffset];
        }
    }
    PBRT_BVH_INTERSECTION_FINISHED();
	if (hit) {
		//printf("\t BVH Intersect: thit=%f\n", ray.maxt);
	}
    return hit;
}
Ejemplo n.º 2
0
int BAH::intersect(const ponos::Ray2 &ray, float *t) {
  UNUSED_VARIABLE(t);
  if (!nodes.size())
    return false;
  ponos::Transform2 inv = ponos::inverse(mesh->getTransform());
  ponos::Ray2 r = inv(ray);
  int hit = 0;
  ponos::vec2 invDir(1.f / r.d.x, 1.f / r.d.y);
  uint32_t dirIsNeg[2] = {invDir.x < 0, invDir.y < 0};
  uint32_t todoOffset = 0, nodeNum = 0;
  uint32_t todo[64];
  while (true) {
    LinearBAHNode *node = &nodes[nodeNum];
    if (intersect(node->bounds, r, invDir, dirIsNeg)) {
      if (node->nElements > 0) {
        // intersect ray with primitives
        for (uint32_t i = 0; i < node->nElements; i++) {
          ponos::point2 v0 =
              mesh->getMesh()
                  ->positionElement(orderedElements[node->elementsOffset + i],
                                    0)
                  .xy();
          ponos::point2 v1 =
              mesh->getMesh()
                  ->positionElement(orderedElements[node->elementsOffset + i],
                                    1)
                  .xy();
          if (ponos::ray_segment_intersection(r, ponos::Segment2(v0, v1)))
            hit++;
        }
        if (todoOffset == 0)
          break;
        nodeNum = todo[--todoOffset];
      } else {
        if (dirIsNeg[node->axis]) {
          todo[todoOffset++] = nodeNum + 1;
          nodeNum = node->secondChildOffset;
        } else {
          todo[todoOffset++] = node->secondChildOffset;
          nodeNum++;
        }
      }
    } else {
      if (todoOffset == 0)
        break;
      nodeNum = todo[--todoOffset];
    }
  }
  return hit;
}
Ejemplo n.º 3
0
Archivo: bvh.cpp Proyecto: AI42/OM3D
bool BVHAccel::IntersectP(const Ray &ray) const {
    if (!nodes) return false;
    PBRT_BVH_INTERSECTIONP_STARTED(const_cast<BVHAccel *>(this), const_cast<Ray *>(&ray));
    Vector invDir(1.f / ray.d.x, 1.f / ray.d.y, 1.f / ray.d.z);
    uint32_t dirIsNeg[3] = { invDir.x < 0, invDir.y < 0, invDir.z < 0 };
    uint32_t todo[64];
    uint32_t todoOffset = 0, nodeNum = 0;
    while (true) {
        const LinearBVHNode *node = &nodes[nodeNum];
        if (::IntersectP(node->bounds, ray, invDir, dirIsNeg)) {
            // Process BVH node _node_ for traversal
            if (node->nPrimitives > 0) {
                PBRT_BVH_INTERSECTIONP_TRAVERSED_LEAF_NODE(const_cast<LinearBVHNode *>(node));
                  for (uint32_t i = 0; i < node->nPrimitives; ++i) {
                    PBRT_BVH_INTERSECTIONP_PRIMITIVE_TEST(const_cast<Primitive *>(primitives[node->primitivesOffset + i].GetPtr()));
                    if (primitives[node->primitivesOffset+i]->IntersectP(ray)) {
                        PBRT_BVH_INTERSECTIONP_PRIMITIVE_HIT(const_cast<Primitive *>(primitives[node->primitivesOffset+i].GetPtr()));
				//		printf("\t BVH Intersect P: thit=%f\n", ray.maxt);
                        return true;
                    }
                else {
                        PBRT_BVH_INTERSECTIONP_PRIMITIVE_MISSED(const_cast<Primitive *>(primitives[node->primitivesOffset + i].GetPtr()));
                    }
                }
                if (todoOffset == 0) break;
                nodeNum = todo[--todoOffset];
            }
            else {
                PBRT_BVH_INTERSECTIONP_TRAVERSED_INTERIOR_NODE(const_cast<LinearBVHNode *>(node));
                if (dirIsNeg[node->axis]) {
                   /// second child first
                   todo[todoOffset++] = nodeNum + 1;
                   nodeNum = node->secondChildOffset;
                }
                else {
                   todo[todoOffset++] = node->secondChildOffset;
                   nodeNum = nodeNum + 1;
                }
            }
        }
        else {
            if (todoOffset == 0) break;
            nodeNum = todo[--todoOffset];
        }
    }
    PBRT_BVH_INTERSECTIONP_FINISHED();
    return false;
}
Ejemplo n.º 4
0
void BVH::hit(Ray &ray, ShadeRec &sr) const
{
    int numNodes = 0;
    int hitTests = 0;
    Vec3 invDir(1.0f/ray.m_dir[0], 1.0f/ray.m_dir[1], 1.0f/ray.m_dir[2]);
    bool dirIsNegative[] = {ray.m_dir[0] < 0.0f, ray.m_dir[1] < 0.0f, ray.m_dir[2] < 0.0f};
    int todo[64];
    int todoOffset = 0;
    int nodeNum    = 0;
    while(true){
        numNodes++;
        const BVHLinearNode *node = &m_root[nodeNum];
        if(node->m_numTris > 0){
            if(node->m_axis == 0){
                for(int i=0;i<node->m_numTris;i++){
                    m_orderedTriangles[node->m_firstTriOffset + i]->hit(ray,sr);
                }
            }
            else{
                for(int i=0;i<node->m_numTris;i++){
					m_orderedInstances[node->m_firstTriOffset + i]->hit(ray,sr);
				}
            }
            hitTests++;
            if(todoOffset == 0)
                break;
            nodeNum = todo[--todoOffset];
        }
        else{
            if(node->m_bbox.hit(ray,invDir, dirIsNegative)){
                if(dirIsNegative[node->m_axis]){
                    todo[todoOffset++] = nodeNum+1;
                    nodeNum = node->m_secondChildOffset;
                }
                else{
                    nodeNum = nodeNum+1;
                    todo[todoOffset++] = node->m_secondChildOffset;
                }
            }
            else{
                if(todoOffset == 0)
                    break;
                nodeNum = todo[--todoOffset];
            }
        }
    }
}
Ejemplo n.º 5
0
bool BVHAccel::Intersect(const Ray &ray, SurfaceInteraction *isect) const {
    if (!nodes) return false;
    ProfilePhase p(Prof::AccelIntersect);
    bool hit = false;
    Vector3f invDir(1 / ray.d.x, 1 / ray.d.y, 1 / ray.d.z);
    int dirIsNeg[3] = {invDir.x < 0, invDir.y < 0, invDir.z < 0};
    // Follow ray through BVH nodes to find primitive intersections
    int toVisitOffset = 0, currentNodeIndex = 0;
    int nodesToVisit[64];
    while (true) {
        const LinearBVHNode *node = &nodes[currentNodeIndex];
        // Check ray against BVH node
        if (node->bounds.IntersectP(ray, invDir, dirIsNeg)) {
            if (node->nPrimitives > 0) {
                // Intersect ray with primitives in leaf BVH node
                for (int i = 0; i < node->nPrimitives; ++i)
                    if (primitives[node->primitivesOffset + i]->Intersect(
                            ray, isect))
                        hit = true;
                if (toVisitOffset == 0) break;
                currentNodeIndex = nodesToVisit[--toVisitOffset];
            } else {
                // Put far BVH node on _nodesToVisit_ stack, advance to near
                // node
                if (dirIsNeg[node->axis]) {
                    nodesToVisit[toVisitOffset++] = currentNodeIndex + 1;
                    currentNodeIndex = node->secondChildOffset;
                } else {
                    nodesToVisit[toVisitOffset++] = node->secondChildOffset;
                    currentNodeIndex = currentNodeIndex + 1;
                }
            }
        } else {
            if (toVisitOffset == 0) break;
            currentNodeIndex = nodesToVisit[--toVisitOffset];
        }
    }
    return hit;
}
Ejemplo n.º 6
0
bool BVHAccel::IntersectP(const Ray &ray) const {
    if (!nodes) return false;
    ProfilePhase p(Prof::AccelIntersectP);
    Vector3f invDir(1.f / ray.d.x, 1.f / ray.d.y, 1.f / ray.d.z);
    int dirIsNeg[3] = {invDir.x < 0, invDir.y < 0, invDir.z < 0};
    int nodesToVisit[64];
    int toVisitOffset = 0, currentNodeIndex = 0;
    while (true) {
        const LinearBVHNode *node = &nodes[currentNodeIndex];
        if (node->bounds.IntersectP(ray, invDir, dirIsNeg)) {
            // Process BVH node _node_ for traversal
            if (node->nPrimitives > 0) {
                for (int i = 0; i < node->nPrimitives; ++i) {
                    if (primitives[node->primitivesOffset + i]->IntersectP(
                            ray)) {
                        return true;
                    }
                }
                if (toVisitOffset == 0) break;
                currentNodeIndex = nodesToVisit[--toVisitOffset];
            } else {
                if (dirIsNeg[node->axis]) {
                    /// second child first
                    nodesToVisit[toVisitOffset++] = currentNodeIndex + 1;
                    currentNodeIndex = node->secondChildOffset;
                } else {
                    nodesToVisit[toVisitOffset++] = node->secondChildOffset;
                    currentNodeIndex = currentNodeIndex + 1;
                }
            }
        } else {
            if (toVisitOffset == 0) break;
            currentNodeIndex = nodesToVisit[--toVisitOffset];
        }
    }
    return false;
}
Ejemplo n.º 7
0
void GeomTree::TraceRay(const BVHNode *currnode, const vector3f &a_origin, const vector3f &a_dir, isect_t *isect) const
{
	BVHNode *stack[32];
	int stackpos = -1;
	vector3f invDir(1.0f/a_dir.x, 1.0f/a_dir.y, 1.0f/a_dir.z);

	for (;;) {
		while (!currnode->IsLeaf()) {
			if (!SlabsRayAabbTest(currnode, a_origin, invDir, isect)) goto pop_bstack;

			stackpos++;
			stack[stackpos] = currnode->kids[1];
			currnode = currnode->kids[0];
		}
		// triangle intersection j**z
		for (int i=0; i<currnode->numTris; i++) {
			RayTriIntersect(1, a_origin, &a_dir, currnode->triIndicesStart[i], isect);
		}
pop_bstack:
		if (stackpos < 0) break;
		currnode = stack[stackpos];
		stackpos--;
	}
}
Ejemplo n.º 8
0
void CollisionSpace::TraceRay(const vector3d &start, const vector3d &dir, double len, CollisionContact *c, Geom *ignore)
{
	vector3d invDir(1.0/dir.x, 1.0/dir.y, 1.0/dir.z);
	c->dist = len;

	BvhNode *vn_stack[16];
	BvhNode *node = m_staticObjectTree->m_root;
	int stackPos = -1;

	for (;node;) {
		// do we hit it?
		{
			isect_t isect;
			isect.dist = float(c->dist);
			isect.triIdx = -1;
			if (!node->CollideRay(start, invDir, &isect)) goto pop_jizz;
		}

		if (node->geomStart) {
			// it is a leaf node
			// collide with all geoms
			for (int i=0; i<node->numGeoms; i++) {
				Geom *g = node->geomStart[i];

				const matrix4x4d &invTrans = g->GetInvTransform();
				vector3d ms = invTrans * start;
				vector3d md = invTrans.ApplyRotationOnly(dir);
				vector3f modelStart = vector3f(ms.x, ms.y, ms.z);
				vector3f modelDir = vector3f(md.x, md.y, md.z);

				isect_t isect;
				isect.dist = float(c->dist);
				isect.triIdx = -1;
				g->GetGeomTree()->TraceRay(modelStart, modelDir, &isect);
				if (isect.triIdx != -1) {
					c->pos = start + dir*double(isect.dist);

					vector3f n = g->GetGeomTree()->GetTriNormal(isect.triIdx);
					c->normal = vector3d(n.x, n.y, n.z);
					c->normal = g->GetTransform().ApplyRotationOnly(c->normal);

					c->depth = len - isect.dist;
					c->triIdx = isect.triIdx;
					c->userData1 = g->GetUserData();
					c->userData2 = 0;
					c->geomFlag = g->GetGeomTree()->GetTriFlag(isect.triIdx);
					c->dist = isect.dist;
				}
			}
		} else if (node->kids[0]) {
			vn_stack[++stackPos] = node->kids[0];
			node = node->kids[1];
			continue;
		}
pop_jizz:
		if (stackPos < 0) break;
		node = vn_stack[stackPos--];
	}

	for (std::list<Geom*>::iterator i = m_geoms.begin(); i != m_geoms.end(); ++i) {
		if ((*i) == ignore) continue;
		if ((*i)->IsEnabled()) {
			const matrix4x4d &invTrans = (*i)->GetInvTransform();
			vector3d ms = invTrans * start;
			vector3d md = invTrans.ApplyRotationOnly(dir);
			vector3f modelStart = vector3f(ms.x, ms.y, ms.z);
			vector3f modelDir = vector3f(md.x, md.y, md.z);

			isect_t isect;
			isect.dist = float(c->dist);
			isect.triIdx = -1;
			(*i)->GetGeomTree()->TraceRay(modelStart, modelDir, &isect);
			if (isect.triIdx != -1) {
				c->pos = start + dir*double(isect.dist);

				vector3f n = (*i)->GetGeomTree()->GetTriNormal(isect.triIdx);
				c->normal = vector3d(n.x, n.y, n.z);
				c->normal = (*i)->GetTransform().ApplyRotationOnly(c->normal);

				c->depth = len - isect.dist;
				c->triIdx = isect.triIdx;
				c->userData1 = (*i)->GetUserData();
				c->userData2 = 0;
				c->geomFlag = (*i)->GetGeomTree()->GetTriFlag(isect.triIdx);
				c->dist = isect.dist;
			}
		}
	}
	{
		isect_t isect;
		isect.dist = float(c->dist);
		isect.triIdx = -1;
		CollideRaySphere(start, dir, &isect);
		if (isect.triIdx != -1) {
			c->pos = start + dir*double(isect.dist);
			c->normal = vector3d(0.0);
			c->depth = len - isect.dist;
			c->triIdx = -1;
			c->userData1 = sphere.userData;
			c->userData2 = 0;
			c->geomFlag = 0;
		}
	}
}
Ejemplo n.º 9
0
bool EBVHAccel::IntersectP(const Ray &ray) const {
    if (!nodes) return false;
    PBRT_BVH_INTERSECTIONP_STARTED(const_cast<EBVHAccel *>(this), const_cast<Ray *>(&ray));
    Vector invDir(1.f / ray.d.x, 1.f / ray.d.y, 1.f / ray.d.z);
    uint32_t dirIsNeg[3] = { invDir.x < 0, invDir.y < 0, invDir.z < 0 };
    uint32_t todo[64];
    uint32_t todoOffset = 0, nodeNum = 0;

    std::stack<BBox> stackOfBoxes;
    stackOfBoxes.push(this->sceneBoundingBox);

    while (true) {
        const LinearEBVHNode *node = &nodes[nodeNum];

        BBox myBBox = uncompressBBox(BBox(Point(node->bounds_x0, node->bounds_y0, node->bounds_z0), Point(node->bounds_x1, node->bounds_y1, node->bounds_z1)), stackOfBoxes.top());

        if (::IntersectP(myBBox, ray, invDir, dirIsNeg)) {
            // Process EBVH node _node_ for traversal
            if (node->nPrimitives > 0) {
                PBRT_BVH_INTERSECTIONP_TRAVERSED_LEAF_NODE(const_cast<LinearEBVHNode *>(node));
                for (uint32_t i = 0; i < node->nPrimitives; ++i) {
                    PBRT_BVH_INTERSECTIONP_PRIMITIVE_TEST(const_cast<Primitive *>(primitives[node->primitivesOffset + i].GetPtr()));
                    if (primitives[node->primitivesOffset+i]->IntersectP(ray)) {
                        PBRT_BVH_INTERSECTIONP_PRIMITIVE_HIT(const_cast<Primitive *>(primitives[node->primitivesOffset+i].GetPtr()));
                        return true;
                    }
                    else {
                        PBRT_BVH_INTERSECTIONP_PRIMITIVE_MISSED(const_cast<Primitive *>(primitives[node->primitivesOffset + i].GetPtr()));
                    }
                }
                if (todoOffset == 0) break;
                todoOffset--;
                nodeNum = todo[todoOffset];
                stackOfBoxes.pop();
            }
            else {
                PBRT_BVH_INTERSECTIONP_TRAVERSED_INTERIOR_NODE(const_cast<LinearEBVHNode *>(node));
                if (dirIsNeg[node->axis]) {
                   /// second child first
                   todo[todoOffset] = nodeNum + 1;
                   nodeNum = node->secondChildOffset;

                   todoOffset++;
                   stackOfBoxes.pop();
                   stackOfBoxes.push(myBBox);
                   stackOfBoxes.push(myBBox);
                }
                else {
                   todo[todoOffset] = node->secondChildOffset;
                   nodeNum = nodeNum + 1;
                   todoOffset++;
                   stackOfBoxes.pop();
                   stackOfBoxes.push(myBBox);
                   stackOfBoxes.push(myBBox);
                }
            }
        }
        else {
            if (todoOffset == 0) break;
            todoOffset--;
            nodeNum = todo[todoOffset];
            stackOfBoxes.pop();
        }
    }
    PBRT_BVH_INTERSECTIONP_FINISHED();
    return false;
}
Ejemplo n.º 10
0
bool EBVHAccel::Intersect(const Ray &ray, Intersection *isect) const {
    if (!nodes) return false;
    PBRT_BVH_INTERSECTION_STARTED(const_cast<EBVHAccel *>(this), const_cast<Ray *>(&ray));
    bool hit = false;
    Vector invDir(1.f / ray.d.x, 1.f / ray.d.y, 1.f / ray.d.z);
    uint32_t dirIsNeg[3] = { invDir.x < 0, invDir.y < 0, invDir.z < 0 };
    // Follow ray through EBVH nodes to find primitive intersections
    uint32_t todoOffset = 0, nodeNum = 0;
    uint32_t todo[64];

    std::stack<BBox> stackOfBoxes;
    stackOfBoxes.push(this->sceneBoundingBox);

    while (true) {
        LinearEBVHNode *node = &nodes[nodeNum];

        BBox myBBox = uncompressBBox(BBox(Point(node->bounds_x0, node->bounds_y0, node->bounds_z0), Point(node->bounds_x1, node->bounds_y1, node->bounds_z1)), stackOfBoxes.top());

        // Check ray against EBVH node
        if (::IntersectP(myBBox, ray, invDir, dirIsNeg)) {
            if (node->nPrimitives > 0) {
                // Intersect ray with primitives in leaf EBVH node
                PBRT_BVH_INTERSECTION_TRAVERSED_LEAF_NODE(const_cast<LinearEBVHNode *>(node));
                for (uint32_t i = 0; i < node->nPrimitives; ++i)
                {
                    PBRT_BVH_INTERSECTION_PRIMITIVE_TEST(const_cast<Primitive *>(primitives[node->primitivesOffset+i].GetPtr()));
                    if (primitives[node->primitivesOffset+i]->Intersect(ray, isect))
                    {
                        PBRT_BVH_INTERSECTION_PRIMITIVE_HIT(const_cast<Primitive *>(primitives[node->primitivesOffset+i].GetPtr()));
                        hit = true;
                    }
                    else {
                        PBRT_BVH_INTERSECTION_PRIMITIVE_MISSED(const_cast<Primitive *>(primitives[node->primitivesOffset+i].GetPtr()));
                   }
                }
                if (todoOffset == 0) break;
                todoOffset--;
                nodeNum = todo[todoOffset];
                stackOfBoxes.pop();
            }
            else {
                // Put far EBVH node on _todo_ stack, advance to near node
                PBRT_BVH_INTERSECTION_TRAVERSED_INTERIOR_NODE(const_cast<LinearEBVHNode *>(node));
                if (dirIsNeg[node->axis]) {
                   todo[todoOffset] = nodeNum + 1;
                   nodeNum = node->secondChildOffset;
                   stackOfBoxes.pop();
                   stackOfBoxes.push(myBBox);
                   stackOfBoxes.push(myBBox);
                   todoOffset++;
                }
                else {
                   todo[todoOffset] = node->secondChildOffset;
                   nodeNum = nodeNum + 1;
                   stackOfBoxes.pop();
                   stackOfBoxes.push(myBBox);
                   stackOfBoxes.push(myBBox);
                   todoOffset++;
                }
            }
        }
        else {
            if (todoOffset == 0) break;
            todoOffset--;
            nodeNum = todo[todoOffset];
            stackOfBoxes.pop();
        }
    }
    PBRT_BVH_INTERSECTION_FINISHED();
    return hit;
}
Ejemplo n.º 11
0
bool KdTreeAccel::IntersectP(const Ray &ray) const {
	// Compute initial parametric range of ray inside kd-tree extent
	float tmin, tmax;
	if (!bounds.IntersectP(ray, &tmin, &tmax))
		return false;
	// Prepare to traverse kd-tree for ray
	int rayId = curMailboxId++;
	Vector invDir(1.f/ray.d.x, 1.f/ray.d.y, 1.f/ray.d.z);
	#define MAX_TODO 64
	KdToDo todo[MAX_TODO];
	int todoPos = 0;
	const KdAccelNode *node = &nodes[0];
	while (node != NULL) {
		// Update kd-tree shadow ray traversal statistics
		//static StatsCounter nodesTraversed("Kd-Tree Accelerator",
		//	"Number of kd-tree nodes traversed by shadow rays");
		//++nodesTraversed;
		if (node->IsLeaf()) {
			// Check for shadow ray intersections inside leaf node
			u_int nPrimitives = node->nPrimitives();
			if (nPrimitives == 1) {
				MailboxPrim *mp = node->onePrimitive;
				if (mp->lastMailboxId != rayId) {
					mp->lastMailboxId = rayId;
					if (mp->primitive->IntersectP(ray))
						return true;
				}
			}
			else {
				MailboxPrim **prims = node->primitives;
				for (u_int i = 0; i < nPrimitives; ++i) {
					MailboxPrim *mp = prims[i];
					if (mp->lastMailboxId != rayId) {
						mp->lastMailboxId = rayId;
						if (mp->primitive->IntersectP(ray))
							return true;
					}
				}
			}
			// Grab next node to process from todo list
			if (todoPos > 0) {
				--todoPos;
				node = todo[todoPos].node;
				tmin = todo[todoPos].tmin;
				tmax = todo[todoPos].tmax;
			}
			else
				break;
		}
		else {
			// Process kd-tree interior node
			// Compute parametric distance along ray to split plane
			int axis = node->SplitAxis();
			float tplane = (node->SplitPos() - ray.o[axis]) *
				invDir[axis];
			// Get node children pointers for ray
			const KdAccelNode *firstChild, *secondChild;
			int belowFirst = (ray.o[axis] <  node->SplitPos()) ||
					 (ray.o[axis] == node->SplitPos() && ray.d[axis] >= 0);
			if (belowFirst) {
				firstChild = node + 1;
				secondChild = &nodes[node->aboveChild];
			}
			else {
				firstChild = &nodes[node->aboveChild];
				secondChild = node + 1;
			}
			// Advance to next child node, possibly enqueue other child
			if (tplane > tmax || tplane <= 0)
				node = firstChild;
			else if (tplane < tmin)
				node = secondChild;
			else {
				// Enqueue _secondChild_ in todo list
				todo[todoPos].node = secondChild;
				todo[todoPos].tmin = tplane;
				todo[todoPos].tmax = tmax;
				++todoPos;
				node = firstChild;
				tmax = tplane;
			}
		}
	}
	return false;
}
Ejemplo n.º 12
0
bool KdTreeAccel::intersect(const Ray &inRay, DifferentialGeometry* queryPoint, const KdAccelNode* node,
	Float* tHit, Float* rayEpsilon) const
{
	//Compute initial parametric range of ray inside kd-tree extent
	Float tmin, tmax, rayEp;//temprary DifferentialGeometry result
	if (!node->bbox.intersectP(inRay, &tmin, &tmax))
	{
		return false;
	}

	//prepare to traversal kd-tree for ray
	Vector3f invDir(1.0 / inRay.d.x, 1.0 / inRay.d.y, 1.0 / inRay.d.z);

	//Traversal kd-tree node in order of ray
	bool isHit = false;
	if (node != nullptr)
	{
		//if hit outside the box, think it's used for later use
		if (inRay.tmax < tmin)
		{
			return isHit;
		}
		if (node->isLeaf())
		{
			DifferentialGeometry* tmpQuery = new DifferentialGeometry();
			Float hitDist;
			for (int i = 0; i < node->primIndex.size(); ++i)
			{
				int idx = node->primIndex[i];

				if (primitives[idx]->intersectP(inRay))
				{
					if (primitives[idx]->intersect(inRay, tmpQuery, &hitDist, &rayEp))
					{
						if (hitDist < *tHit && inRange(hitDist, tmin, tmax))
						{
							*queryPoint = *tmpQuery;
							*tHit = hitDist;
							*rayEpsilon = rayEp;
							queryPoint->shape = primitives[idx];
							isHit = true;
						}
					}
				}
			}
			delete tmpQuery;
		}
		else//if hit interior node
		{
			/*process interior node*/
			//calculate parametric distance from ray to split plane
			int axis = node->flags;
			Float tsplit = (node->split - inRay.o[axis]) * invDir[axis];

			//get children node for ray
            const KdAccelNode* nearChild;
            const KdAccelNode* farChild;
			bool belowFisrt = ((inRay.o[axis] < node->split) ||
				(inRay.o[axis] == node->split && inRay.d[axis] < 0));
			if (belowFisrt)
			{
				nearChild = node->belowNode;
				farChild = node->aboveNode;
			}
			else
			{
				nearChild = node->aboveNode;
				farChild = node->belowNode;
			}
			if (tsplit > tmax || tsplit <= 0)
			{
				isHit = intersect(inRay, queryPoint, nearChild, tHit, rayEpsilon);
			}
			else if (tsplit < tmin)
			{
				isHit = intersect(inRay, queryPoint, farChild, tHit, rayEpsilon);
			}
			else
			{
				isHit = intersect(inRay, queryPoint, nearChild, tHit, rayEpsilon);
				if (!isHit)
				{
					isHit = intersect(inRay, queryPoint, farChild, tHit, rayEpsilon);
				}
			}
// 			nearChild = nullptr;
// 			farChild = nullptr;
		}
	}
	return isHit;
}
Ejemplo n.º 13
0
bool KdTreeAccelerator::intersect(const Ray& ray, float *t, Intersection* pIntersection, Triangle::IsectMode isectMode) const
{
	// compute initial parametric range of ray inside kd-tree extent
	float t_min = std::numeric_limits<float>::max();
	float t_max = std::numeric_limits<float>::min();

	float t_best = std::numeric_limits<float>::max();
	Intersection isect_best;

	if(!m_boundingBox.intersect(ray, &t_min, &t_max))
		return false;

	// prepare to traverse kd-tree for ray
	glm::vec3 invDir(1.f/ray.getDirection().x, 1.f/ray.getDirection().y, 1.f/ray.getDirection().z);
	KdToTraverse toTraverse[MAX_TO_TRAVERSE];
	int toTraversePos = 0;

	// traverse kd-tree nodes in order for ray
	bool hit = false;
	const KdAccelNode* node = &m_nodes[0];
	while(node != NULL)
	{
		// bail out if we found a hit closer than the current node
		if(t_best <= t_min) break;

		if(!node->isLeaf())
		{
			// process kd-tree interior node

			// compute parametric distance along ray to split plane
			const int axis = node->getSplitAxis();
			
			// get node children pointers for ray
			const KdAccelNode* firstChild;
			const KdAccelNode* secondChild;
			
			const int belowFirst = (ray.getOrigin()[axis] < node->getSplitPosition()) || 
				(ray.getOrigin()[axis] == node->getSplitPosition() && ray.getDirection()[axis] >= 0);
			
			if(belowFirst)
			{
				firstChild = node + 1;
				secondChild = &m_nodes[node->aboveChild()];
			}
			else
			{
				firstChild = &m_nodes[node->aboveChild()];
				secondChild = node + 1;
			}

			// advance to next child node, possibly enqueue other child

			// t for which ray.getOrigin() + t * ray.getDirection() intersects the split plane
			float t_plane = (node->getSplitPosition() - ray.getOrigin()[axis]) * invDir[axis]; 

			if(t_plane > t_max || t_plane <= 0)
				node = firstChild;
			else if(t_plane < t_min)
				node = secondChild;
			else
			{
				// enqueue second child in todo list
				toTraverse[toTraversePos].node = secondChild;
				toTraverse[toTraversePos].t_min = t_plane;
				toTraverse[toTraversePos].t_max = t_max;
				toTraversePos++;

				node = firstChild;
				t_max = t_plane;
			}
		}
		else
		{
			// check for intersection inside leaf node
			const uint numPrimitives = node->getNumPrimitives();
			if(numPrimitives == 1)
			{
				Triangle const& primitive = m_primitives[node->m_onePrimitive];
				float t_temp = 0.f;
				Intersection isect_temp;
				if(primitive.intersect(ray, &t_temp, &isect_temp, isectMode))
				{
					if(t_temp < t_best && t_temp > 0.f) {
						t_best = t_temp;
						isect_best = isect_temp;
						hit = true;
					}
				}
			}
			else
			{
				uint* primitives = node->m_primitives;
				for(uint i = 0; i < node->getNumPrimitives(); ++i)
				{
					Triangle const& primitive = m_primitives[node->m_primitives[i]];
					float t_temp = 0.f;
					Intersection isect_temp;
					if(primitive.intersect(ray, &t_temp, &isect_temp, isectMode))
					{
						if(t_temp < t_best && t_temp > 0.f) {
							t_best = t_temp;
							isect_best = isect_temp;
							hit = true;
						}
					}
				}
			}

			// grab next node to process from toTraverse list
			if(toTraversePos > 0)
			{
				--toTraversePos;
				node = toTraverse[toTraversePos].node;
				t_min = toTraverse[toTraversePos].t_min;
				t_max = toTraverse[toTraversePos].t_max;
			}
			else
				break;
		}
	}

	*pIntersection = isect_best;
	*t = t_best; 

	return hit;
}
Ejemplo n.º 14
0
BVHItems BVH::intersect( const Ray &i_ray ) const
{
    BVHItems hitItems;
    const vec3f &direction = i_ray.getDirection();
    
    vec3f invDir( 1 / direction.x, 1 / direction.y, 1 / direction.z );
    bool dirIsNeg[ 3 ] = { invDir.x < 0, invDir.y < 0, invDir.z < 0 };
    
    if ( m_nodes.empty() )
    {
        return hitItems;
    }
    
    size_t currentIndex = 0;
    size_t nodeToVisitOffset = 0;
    size_t nodesToVisit[ 64 ];
    
    while ( 1 )
    {
        const BVHNode &node = m_nodes[ currentIndex ];
        const Bounds3f &bounds = node.getBounds();
        
        if ( bounds.intersect( i_ray ) )
        {
            size_t itemCount = node.getItemCount();
            
            // Leaf node
            if ( itemCount > 0 )
            {
                size_t start = node.getItemOffset();
                size_t end = start + itemCount;

                for ( size_t i = start; i < end; i++ )
                {
                    hitItems.push_back( m_items[ i ] );
                }
                
                if ( nodeToVisitOffset == 0 )
                {
                    break;
                }
                
                currentIndex = nodesToVisit[ --nodeToVisitOffset ];
            }
            else
            {
                if ( dirIsNeg[ node.getSplitAxis() ] )
                {
                    nodesToVisit[ nodeToVisitOffset++ ] = currentIndex + 1;
                    currentIndex = node.getSecondChildOffset();
                }
                else
                {
                    nodesToVisit[ nodeToVisitOffset++ ] = node.getSecondChildOffset();
                    currentIndex = currentIndex + 1;
                }
            }
        }
        else
        {
            if ( nodeToVisitOffset == 0 )
            {
                break;
            }
            
            currentIndex = nodesToVisit[ --nodeToVisitOffset ];
        }
    }
    
    return hitItems;
}
Ejemplo n.º 15
0
TIntersection KDTree::IntersectP(Ray &a_Ray)
{
   
    // Compute initial parametric range of ray inside kd-tree extent
    float tmin;
	TIntersection Intersect(-1,a_Ray.maxt);	
	
    if (!bounds.IntersectP(a_Ray, &tmin, &a_Ray.maxt))
    {
       return Intersect;
    }

   
	// Prepare to traverse kd-tree for ray
    Vector invDir(1.f/a_Ray.d.x, 1.f/a_Ray.d.y, 1.f/a_Ray.d.z);

	int TriangleID; 
	TIntersection test;	
	bool result = false;

#define MAX_TODO 64
    KdToDo todo[MAX_TODO];
    int todoPos = 0;
    const KdNode *node = &nodes[0];
    while (node != NULL) {
        if (node->IsLeaf()) {
            // Check for shadow ray intersections inside leaf node
            uint32_t nPrimitives = node->nPrimitives();
            if (nPrimitives == 1) {
                const KDTreePrimitiveInfo &prim = primitives[node->onePrimitive];
               
                //m_Candidates++;
				if (prim.bounds.IntersectP(a_Ray)){
						TriangleID = prim.primitiveNumber;
						//candidates++;
						if (RayTriangleTest(a_Ray.o,a_Ray.d,test,TriangleID,m_pPrimitives) && test.t<Intersect.t) {
							Intersect.t = test.t;
								Intersect.u = test.u;
								Intersect.v = test.v;
								Intersect.IDTr = TriangleID;
								result = true;
								 break;
						}
					}
				//break;
            }
            else {
                uint32_t *prims = node->primitives;
				bool tmp = false;
                for (uint32_t i = 0; i < nPrimitives; ++i) {
                    const KDTreePrimitiveInfo &prim = primitives[prims[i]];
					//m_Candidates++;
					if (prim.bounds.IntersectP(a_Ray)){
						TriangleID = prim.primitiveNumber;
						//candidates++;
						if (RayTriangleTest(a_Ray.o,a_Ray.d,test,TriangleID,m_pPrimitives) && test.t<Intersect.t) {
								Intersect.t = test.t;
								Intersect.u = test.u;
								Intersect.v = test.v;
								Intersect.IDTr = TriangleID;
								result = true;
								tmp = true;
						}
						
					}
                }
				if(tmp) break;
            }

            // Grab next node to process from todo list
            if (todoPos > 0) {
                --todoPos;
                node = todo[todoPos].node;
                tmin = todo[todoPos].tmin;
                a_Ray.maxt = todo[todoPos].maxT;
            }
            else
                break;
        }
        else {
            
            // Process kd-tree interior node

            // Compute parametric distance along ray to split plane
            int axis = node->SplitAxis();
            float tplane = (node->SplitPos() - a_Ray.o[axis]) * invDir[axis];

            // Get node children pointers for ray
            const KdNode *firstChild, *secondChild;
            int belowFirst = (a_Ray.o[axis] <  node->SplitPos()) ||
                             (a_Ray.o[axis] == node->SplitPos() && a_Ray.d[axis] >= 0);
            if (belowFirst) {
                firstChild = node + 1;
                secondChild = &nodes[node->AboveChild()];
            }
            else {
                firstChild = &nodes[node->AboveChild()];
                secondChild = node + 1;
            }

            // Advance to next child node, possibly enqueue other child
            if (tplane > a_Ray.maxt || tplane <= 0)
                node = firstChild;
            else if (tplane < tmin)
                node = secondChild;
            else {
                // Enqueue _secondChild_ in todo list
                todo[todoPos].node = secondChild;
                todo[todoPos].tmin = tplane;
                todo[todoPos].maxT = a_Ray.maxt;
                ++todoPos;
                node = firstChild;
                a_Ray.maxt = tplane;
            }
        }
    }
 
 return Intersect;
}