예제 #1
0
파일: sphere.py 프로젝트: neodyme60/raypy
    def Sample2(self, p: Point3d, u: (float, float), Ns: Normal) -> Point3d:
        # Compute coordinate system for sphere sampling
        Pcenter = Point3d(0, 0, 0) * self.objectToWorld
        wc = (Pcenter - p).get_normalized()
        wcX, wcY = Transform.create_coordinateSystem(wc)

        # Sample uniformly on sphere if $\pt{}$ is inside it
        if (p - Pcenter).get_length_squared() - self.radius * self.radius < 1e-40:
            return self.Sample1(u, Ns)

        # Sample sphere uniformly inside subtended cone
        sinThetaMax2 = self.radius * self.radius / (p - Pcenter).get_length_squared()
        cosThetaMax = math.sqrt(max(0.0, 1.0 - sinThetaMax2))
        dgSphere = DifferentialGeometry()

        thit = 1.0

        r = Ray(p, UniformSampleCone2(u, cosThetaMax, wcX, wcY, wc), 1e-3)
        b, t = self.get_intersection(r, dgSphere)
#        if not b:
        #bug
        thit = Vector3d.dot(Pcenter - p, r.direction.get_normalized())
        ps = r.get_at(thit)

        nn = (ps - Pcenter).get_normalized()
        Ns.Set(nn)
        # if (ReverseOrientation) *ns *= -1.f;
        return ps
예제 #2
0
    def get_is_intersected(self, ray: Ray) -> bool:

        # Check ray against overall grid bounds
        if self.bounds.get_is_point_inside(ray.get_at(ray.min_t)):
            rayT = ray.min_t
        else:
            rayT, tmp = self.bounds.get_intersect(ray)
            if rayT is None:
                return False

        gridIntersect = ray.get_at(rayT)

        # Set up 3D DDA for ray
        NextCrossingT = [float] * 3
        DeltaT = [float] * 3
        Step = [int] * 3
        Out = [int] * 3
        Pos = [int] * 3
        for axis in range(3):
            # Compute current voxel for axis
            Pos[axis] = self.get_pos_to_voxel(gridIntersect, axis)
            if ray.direction[axis] >= 0:
                # Handle ray with positive direction for voxel stepping
                NextCrossingT[axis] = rayT + (self.get_voxel_to_pos(Pos[axis] + 1, axis) - gridIntersect[axis]) / \
                                             ray.direction[axis]
                DeltaT[axis] = self.width[axis] / ray.direction[axis]
                Step[axis] = 1
                Out[axis] = self.nVoxels[axis]
            else:
                # Handle ray with negative direction for voxel stepping
                NextCrossingT[axis] = rayT + (self.get_voxel_to_pos(Pos[axis], axis) - gridIntersect[axis]) / \
                                             ray.direction[axis]
                DeltaT[axis] = -self.width[axis] / ray.direction[axis]
                Step[axis] = -1
                Out[axis] = -1

        #Walk grid for shadow ray
        while True:
            o = self.get_offset(Pos[0], Pos[1], Pos[2])
            voxel = self.voxels[o]
            if voxel is not None:
                if voxel.get_is_intersected(ray):
                    return True
            # Advance to next voxel

            # Find _stepAxis_ for stepping to next voxel
            bits = ((NextCrossingT[0] < NextCrossingT[1]) << 2) + ((NextCrossingT[0] < NextCrossingT[2]) << 1) + (
            (NextCrossingT[1] < NextCrossingT[2]))
            cmpToAxis = [2, 1, 2, 1, 2, 2, 0, 0]
            stepAxis = cmpToAxis[bits]
            if ray.max_t < NextCrossingT[stepAxis]:
                break
            Pos[stepAxis] += Step[stepAxis]
            if Pos[stepAxis] == Out[stepAxis]:
                break
            NextCrossingT[stepAxis] += DeltaT[stepAxis]
        return False
예제 #3
0
    def generate_ray(self, sample:CameraSample)->Ray:

        point_camera = Point3d(sample.image_xy[0], sample.image_xy[1], 0.0) * self.rasterToCamera
        direction = Vector3d(0.0, 0.0, 1.0)

        r = Ray(point_camera, direction, 0.0, infinity_max_f)

        if self.lensRadius>0.0:
            pass
            #todo

        r.time = sample.time
        return r * self.camera_to_world
예제 #4
0
    def generate_ray(self, sample:CameraSample)->Ray:

        camera_point = Point3d(sample.image_xy[0], sample.image_xy[1], 0.0) * self.rasterToCamera
        camera_direction = Vector3d(camera_point.x, camera_point.y, camera_point.z).get_normalized()

        r = Ray(camera_point, camera_direction, 0.0, infinity_max_f)

        if self.lensRadius>0.0:
            pass
            #todo

        r.time = sample.time
        return r * self.camera_to_world
예제 #5
0
파일: shape.py 프로젝트: neodyme60/raypy
    def Pdf2(self, p: Point3d, wi: Vector3d)->float:
        # Intersect sample ray with area light geometry
        dgLight = DifferentialGeometry()
        ray = Ray(p, wi, 1e-3)
        ray.depth = -1 # temporary hack to ignore alpha mask
        b, thit =self.get_intersection(ray, dgLight)
        if not b:
            return 0.0

        # Convert light sample weight to solid angle measure
        pdf = (p - ray.get_at(thit)).get_length_squared() / (math.fabs(Vector3d.dot(dgLight.normal, -wi) * self.Area()))
        if math.isinf(pdf):
            pdf = 0.0
        return pdf
예제 #6
0
    def scatter(self, ray, hit_record):
        target = hit_record.point + hit_record.normal + random_in_unit_sphere()
        self.scattered = Ray(hit_record.point, target - hit_record.point,
                             ray.time)
        self.attenuation = self.albedo

        return True
예제 #7
0
    def Sample1(self, p: Point3d, ls: LightSample, Ns: Normal)->Point3d:
        pdf, sn = self.areaDistribution.SampleDiscrete(ls.uComponent)
        pt = self.shapes[sn].Sample2(p, ls.uPos, Ns)

        # Find closest intersection of ray with shapes in _ShapeSet_
        r = Ray(p, (pt-p).get_normalized(), 1e-3, infinity_max_f)
        anyHit = False
        thit = 1.0
        dg = DifferentialGeometry()
        for i in range(len(self.shapes)):
            anyHit_b, thit_f = self.shapes[i].get_intersection(r, dg)
            if anyHit_b:
                anyHit = True
                thit = thit_f
        if anyHit:
            Ns.Set(dg.normal)
        return r.get_at(thit)
예제 #8
0
    def scatter(self, ray, hit_record):
        reflected = reflect(unit_vector(ray.direction), hit_record.normal)
        self.scattered = Ray(hit_record.point,
                             reflected + self.fuzzy * random_in_unit_sphere(),
                             ray.time)
        self.attenuation = self.albedo

        return np.dot(self.scattered.direction, hit_record.normal) > 0.
예제 #9
0
 def get_intersection(self, ray: Ray, intersection: Intersection) -> bool:
     hit, thit = self.shape.get_intersection(ray, intersection.differentialGeometry)
     if not hit:
         return False
     intersection.primitive = self
     intersection.WorldToObject = self.shape.objectToWorld
     intersection.ObjectToWorld = self.shape.objectToWorld
     ray.max_t = thit
     return True
예제 #10
0
파일: triangle.py 프로젝트: neodyme60/raypy
    def get_intersection(self, ray: Ray, dg: DifferentialGeometry) -> (bool, float):
        p1_index = self.mesh.index[self.triangle_index*3 + 0]
        p2_index = self.mesh.index[self.triangle_index*3 + 2]
        p3_index = self.mesh.index[self.triangle_index*3 + 1]

        p1 = self.mesh.points[p1_index]
        p2 = self.mesh.points[p2_index]
        p3 = self.mesh.points[p3_index]

        e1 = p2 - p1
        e2 = p3 - p1
        s1 = Vector3d.cross(ray.direction, e2)
        divisor = Vector3d.dot(s1, e1)

        if divisor == 0.0:
            return False, 0.0
        invDivisor = 1.0 / divisor

        # Compute first barycentric coordinate
        d = ray.origin - p1
        b1 = Vector3d.dot(d, s1) * invDivisor
        if b1 < 0.0 or b1 > 1.0:
            return False, 0.0

        #Compute second barycentric coordinate
        s2 = Vector3d.cross(d, e1)
        b2 = Vector3d.dot(ray.direction, s2) * invDivisor
        if b2 < 0.0 or (b1 + b2) > 1.0:
            return False, 0.0

        # Compute _t_ to intersection point
        t = Vector3d.dot(e2, s2) * invDivisor
        if t < ray.min_t or t > ray.max_t:
            return False, 0.0

        dg.shape = self
        dg.point = ray.get_at(t)
        dg.normal = Normal.create_from_vector3d( Vector3d.cross(e1, e2).get_normalized())

        return True, t