Spectrum SubsurfaceOctreeNode::Mo(const BBox &nodeBound, const Point &pt,
        const DiffusionReflectance &Rd, float maxError) {
    // Compute $M_\roman{o}$ at node if error is low enough
    float dw = sumArea / DistanceSquared(pt, p);
    if (dw < maxError && !nodeBound.Inside(pt))
    {
        PBRT_SUBSURFACE_ADDED_INTERIOR_CONTRIBUTION(const_cast<SubsurfaceOctreeNode *>(this));
        return Rd(DistanceSquared(pt, p)) * E * sumArea;
    }

    // Otherwise comupte $M_\roman{o}$ from points in leaf or recursively visit children
    Spectrum Mo = 0.f;
    if (isLeaf) {
        // Accumulate $M_\roman{o}$ from leaf node
        for (int i = 0; i < 8; ++i) {
            if (!ips[i]) break;
            PBRT_SUBSURFACE_ADDED_POINT_CONTRIBUTION(const_cast<IrradiancePoint *>(ips[i]));
            Mo += Rd(DistanceSquared(pt, ips[i]->p)) * ips[i]->E * ips[i]->area;
        }
    }
    else {
        // Recursively visit children nodes to compute $M_\roman{o}$
        Point pMid = .5f * nodeBound.pMin + .5f * nodeBound.pMax;
        for (int child = 0; child < 8; ++child) {
            if (!children[child]) continue;
            BBox childBound = octreeChildBound(child, nodeBound, pMid);
            Mo += children[child]->Mo(childBound, pt, Rd, maxError);
        }
    }
    return Mo;
}
Exemple #2
0
bool GridAccel::IntersectP(const Ray &ray) const {
	if (!gridForRefined) { // NOBOOK
		rayTests.Add(0, 1); // NOBOOK
		rayHits.Add(0, 1); // NOBOOK
	} // NOBOOK
	int rayId = ++curMailboxId;
	// Check ray against overall grid bounds
	float rayT;
	if (bounds.Inside(ray(ray.mint)))
		rayT = ray.mint;
	else if (!bounds.IntersectP(ray, &rayT))
		return false;
	Point gridIntersect = ray(rayT);
	// Set up 3D DDA for ray
	float NextCrossingT[3], DeltaT[3];
	int Step[3], Out[3], Pos[3];
	for (int axis = 0; axis < 3; ++axis) {
		// Compute current voxel for axis
		Pos[axis] = PosToVoxel(gridIntersect, axis);
		if (ray.d[axis] >= 0) {
			// Handle ray with positive direction for voxel stepping
			NextCrossingT[axis] = rayT +
				(VoxelToPos(Pos[axis]+1, axis) - gridIntersect[axis]) /
					ray.d[axis];
			DeltaT[axis] = Width[axis] / ray.d[axis];
			Step[axis] = 1;
			Out[axis] = NVoxels[axis];
		}
		else {
			// Handle ray with negative direction for voxel stepping
			NextCrossingT[axis] = rayT +
				(VoxelToPos(Pos[axis], axis) - gridIntersect[axis]) /
					ray.d[axis];
			DeltaT[axis] = -Width[axis] / ray.d[axis];
			Step[axis] = -1;
			Out[axis] = -1;
		}
	}
	// Walk grid for shadow ray
	for (;;) {
		int offset = Offset(Pos[0], Pos[1], Pos[2]);
		Voxel *voxel = voxels[offset];
		if (voxel && voxel->IntersectP(ray, rayId))
			return true;
		// Advance to next voxel
		// Find _stepAxis_ for stepping to next voxel
		int bits = ((NextCrossingT[0] < NextCrossingT[1]) << 2) +
			((NextCrossingT[0] < NextCrossingT[2]) << 1) +
			((NextCrossingT[1] < NextCrossingT[2]));
		const int cmpToAxis[8] = { 2, 1, 2, 1, 2, 2, 0, 0 };
		int stepAxis = cmpToAxis[bits];
		if (ray.maxt < NextCrossingT[stepAxis])
			break;
		Pos[stepAxis] += Step[stepAxis];
		if (Pos[stepAxis] == Out[stepAxis])
			break;
		NextCrossingT[stepAxis] += DeltaT[stepAxis];
	}
	return false;
}
TEST_F(BBoxTest, InsideDetectsPointOnBorderAsInside) {
    BBox b (Point (1, 1, 1), Point (3, 3, 3));
    Point p (3, 3, 3);

    bool result = b.Inside (p);

    EXPECT_TRUE (result);
}
TEST_F(BBoxTest, InsideDetectsPointOutside) {
    BBox b (Point (1, 1, 1), Point (3, 3, 3));
    Point p (4, 4, 4);

    bool result = b.Inside (p);

    EXPECT_FALSE (result);
}
float VolumeGrid::Density(const Point &Pobj) const {
	if (!extent.Inside(Pobj)) return 0;
	// Compute voxel coordinates and offsets for _Pobj_
	float voxx = (Pobj.x - extent.pMin.x) /
		(extent.pMax.x - extent.pMin.x) * nx - .5f;
	float voxy = (Pobj.y - extent.pMin.y) /
		(extent.pMax.y - extent.pMin.y) * ny - .5f;
	float voxz = (Pobj.z - extent.pMin.z) /
		(extent.pMax.z - extent.pMin.z) * nz - .5f;
	int vx = Floor2Int(voxx);
	int vy = Floor2Int(voxy);
	int vz = Floor2Int(voxz);
	float dx = voxx - vx, dy = voxy - vy, dz = voxz - vz;
	// Trilinearly interpolate density values to compute local density
	float d00 = Lerp(dx, D(vx, vy, vz),     D(vx+1, vy, vz));
	float d10 = Lerp(dx, D(vx, vy+1, vz),  D(vx+1, vy+1, vz));
	float d01 = Lerp(dx, D(vx, vy, vz+1),  D(vx+1, vy, vz+1));
	float d11 = Lerp(dx, D(vx, vy+1, vz+1),D(vx+1, vy+1, vz+1));
	float d0 = Lerp(dy, d00, d10);
	float d1 = Lerp(dy, d01, d11);
	return Lerp(dz, d0, d1);
}
// get/update camera from values in node
GvBool	GvViewpoint::getCamera(GCamera &camera, 
							   BBox &bbox,
							   float visibilityLimitNear,float visibilityLimit,
							   Matrix *cameraTransform)
{
	Matrix m;
    float viewAngle = 0.785398;
	float aspectRatio = 1.0f;
    orientation.get(m);
	camera.position=position;
    viewAngle = (float) fieldOfView;
	Point dir(0,0,-1.0);
	Point up(0,1.0,0);
			
    // apply orientation to standard dir and up vectors
    dir *= m;	
	up *= m;	up.Normalize();
			
    if (cameraTransform) {
        camera.position *= *cameraTransform;
        dir = RotateOnly(*cameraTransform,dir);
        up = RotateOnly(*cameraTransform,up);
        // near far focalDistance ??????????
    }
    dir.Normalize();
    up.Normalize();

	Point size = bbox.Size(); // computed bounding box
		    
	float field = max(max(fabs(size.x),fabs(size.y)),fabs(size.z));
			
	int positionInBox = bbox.Inside(camera.position);
  			
	if (bbox.IsEmpty() || (field<=1E-20f)) 
		field = 2.0f; // no bounding box yet, bad 
  			
            // compute distance to target point
  			//xx float targetDistance = field*2.0f;
  			float targetDistance = field*1.0f;
			
			// viewpoint inside scene 
			if (positionInBox) targetDistance = 0.2 * field; 

            camera.targetDistanceIsDefault=1;
            camera.zrangeIsDefault=1;

            // compute a reasonable z-range 

				if (visibilityLimit >0.0f) {
					camera.zfar = visibilityLimit;
					camera.zrangeIsDefault=0;
				}
				else {
					if (positionInBox) 
						camera.zfar = field*1.5;
					else camera.zfar = field*3.0f;
					
					Point center = bbox.Center();
					Point d = camera.position - center;
					float dist = d.Length();
					
					// make shure object is visible from viewpoint 
					if ((dist+field) > camera.zfar)
						camera.zfar = dist + field;

				}

				if (visibilityLimitNear > 0.0f)
				    camera.znear = visibilityLimitNear;
				else 
					 camera.znear = camera.zfar * camera.znearFactor;

            // compute target 
			camera.target = camera.position + targetDistance*dir;
			camera.up = up;

            // field of view 
			camera.height = 2.0 * tan(viewAngle * 0.5)*targetDistance;
			camera.width = camera.height *  aspectRatio;

			if (!bbox.IsEmpty())
				camera.SetWorldReference(bbox);

			camera.ComputeWorldUpFromUp(); 

            camera.OnChanged();

	return gtrue;

}