예제 #1
0
 def get_intensity(self, pos):
     q = sub(self.pos, pos)
     dsq = dot(q, q)
     invlend = 1 / math.sqrt(dsq)
     cosangle = -dot(q, self.d) * invlend
     if cosangle < self.coscutoff:
         return (0.0, 0.0, 0.0)
     i = pow(dot(self.d, mul(d, -invlend)), self.exp)
     return mul(self.color, i * 100.0 / (99.0 + dsq))
예제 #2
0
 def intersect(self, raypos, raydir):
     tr = self.transform
     raydir = tr.inv_transform_vector(raydir)
     scale = 1.0 / length(raydir)
     raydir = mul(raydir, scale)  # normalize
     raypos = tr.inv_transform_point(raypos)
     s = dot(neg(raypos), raydir)
     lsq = dot(raypos, raypos)
     if s < 0.0 and lsq > 1.0:
         return []
     msq = lsq - s * s
     if msq > 1.0:
         return []
     q = math.sqrt(1.0 - msq)
     t1 = s + q
     t2 = s - q
     if t1 > t2:
         t1, t2 = t2, t1
     ts = []
     if t1 > 0.0:
         ts.append(
             Intersection(scale, t1, raypos, raydir, self,
                          Intersection.ENTRY, 0))
     if t2 > 0.0:
         ts.append(
             Intersection(scale, t2, raypos, raydir, self,
                          Intersection.EXIT, 0))
     return ts
예제 #3
0
    def intersect(self, raypos, raydir):
        tr = self.transform
        raydir = tr.inv_transform_vector(raydir)
        scale = 1.0 / length(raydir)
        raydir = mul(raydir, scale)  # normalize
        raypos = tr.inv_transform_point(raypos)
        eps = 1e-7

        px, py, pz = raypos
        dx, dy, dz = raydir
        tsc = self._solveCone(px, py, pz, dx, dy, dz)
        if not tsc:
            return []
        tcmin, tcmax = tsc
        ts = []
        cminy = py + tcmin[0] * dy
        cmaxy = py + tcmax[0] * dy
        if 0.0 <= cminy <= 1.0:
            ts.append(tcmin)
        if 0.0 <= cmaxy <= 1.0:
            ts.append(tcmax)
        if len(ts) == 0:
            return []
        if len(ts) == 2:
            tr = []
            if ts[0][0] > 0.0:
                tr.append(
                    Intersection(scale, ts[0][0], raypos, raydir, self,
                                 Intersection.ENTRY, ts[0][1]))
            if ts[1][0] > 0.0:
                tr.append(
                    Intersection(scale, ts[1][0], raypos, raydir, self,
                                 Intersection.EXIT, ts[1][1]))
            return tr
        # check plane
        # since we know there is only one intersection with the cone,
        # there must be an intersection in the base
        tp = (-py + 1.0) / dy
        ts.append((tp, 1))
        ts.sort()
        tr = []
        if ts[0][0] > 0.0:
            tr.append(
                Intersection(scale, ts[0][0], raypos, raydir, self,
                             Intersection.ENTRY, ts[0][1]))
        if ts[1][0] > 0.0:
            tr.append(
                Intersection(scale, ts[1][0], raypos, raydir, self,
                             Intersection.EXIT, ts[1][1]))
        return tr
예제 #4
0
 def intersect(self, raypos, raydir):
     tr = self.transform
     raydir = tr.inv_transform_vector(raydir)
     scale = 1.0 / length(raydir)
     raydir = mul(raydir, scale)  # normalize
     raypos = tr.inv_transform_point(raypos)
     eps = 1e-15
     tmin = None
     tmax = None
     p = sub((0.5, 0.5, 0.5), raypos)
     for i in range(3):
         face1, face2 = self.slabs[i]
         e = p[i]
         f = raydir[i]
         if abs(f) > eps:
             t1 = (e + 0.5) / f
             t2 = (e - 0.5) / f
             if t1 > t2:
                 t1, t2 = t2, t1
                 face1, face2 = face2, face1
             if tmin is None or t1 > tmin[0]:
                 tmin = (t1, face1)
             if tmax is None or t2 < tmax[0]:
                 tmax = (t2, face2)
             if tmin[0] > tmax[0]:
                 return []
             if tmax[0] < 0.0:
                 return []
         elif -e - 0.5 > 0.0 or -e + 0.5 < 0.0:
             return []
     ts = []
     if tmin[0] > 0.0:
         ts.append(
             Intersection(scale, tmin[0], raypos, raydir, self,
                          Intersection.ENTRY, tmin[1]))
     if tmax[0] > 0.0:
         ts.append(
             Intersection(scale, tmax[0], raypos, raydir, self,
                          Intersection.EXIT, tmax[1]))
     return ts
예제 #5
0
def trace(amb, lights, scene, depth, raypos, raydir):
    i = scene.intersect(raypos, raydir)
    if i:
        #for ic in i:
        #    print ic
        #print
        isect = i[0]
        if isect.t == Intersection.EXIT:
            return (0.0, 0.0, 0.0)
        sc, kd, ks, n = isect.primitive.get_surface(isect)
        c = get_ambient(sc, amb, kd)
        diffuse = (0.0, 0.0, 0.0)
        specular = (0.0, 0.0, 0.0)
        pos = isect.wpos
        normal = isect.normal
        for light in lights:
            lightdir, lightdistance = light.get_direction(pos)
            df = dot(normal, lightdir)
            if df > 0.0:
                poseps = add(pos, mul(lightdir, 1e-7))
                i = scene.intersect(poseps, lightdir)
                if not i or (lightdistance and
                             (lightdistance < i[0].distance)):
                    ic = cmul(sc, light.get_intensity(pos))
                    if kd > 0.0:
                        diffuse = add(diffuse, mul(ic, df))
                    if ks > 0.0:
                        specular = add(
                            specular,
                            get_specular(ic, lightdir, normal, pos, raypos, n))
        c = add(c, add(mul(diffuse, kd), mul(specular, ks)))
        if ks > 0.0 and depth > 0:
            refl_raydir = normalize(
                sub(raydir, mul(normal, 2 * dot(raydir, normal))))
            poseps = add(pos, mul(refl_raydir, 1e-7))
            rc = trace(amb, lights, scene, depth - 1, poseps, refl_raydir)
            return add(c, mul(cmul(rc, sc), ks))
        else:
            return c
    else:
        return (0.0, 0.0, 0.0)
예제 #6
0
 def intersect(self, raypos, raydir):
     tr = self.transform
     raydir = tr.inv_transform_vector(raydir)
     scale = 1.0 / length(raydir)
     raydir = mul(raydir, scale)  # normalize
     raypos = tr.inv_transform_point(raypos)
     np = self.np
     denom = dot(np, raydir)
     if abs(denom) < 1e-7:
         return []
     t = -dot(np, raypos) / denom
     if t < 0.0:
         return []
     if denom > 0.0:
         return [
             Intersection(scale, t, raypos, raydir, self, Intersection.EXIT,
                          0)
         ]
     else:
         return [
             Intersection(scale, t, raypos, raydir, self,
                          Intersection.ENTRY, 0)
         ]
예제 #7
0
def get_ambient(c, ia, kd):
    return mul(cmul(ia, c), kd)
예제 #8
0
def get_specular(ic, lightdir, sn, pos, raypos, n):
    halfway = normalize(add(lightdir, normalize(sub(raypos, pos))))
    sp = dot(sn, halfway)
    if sp > 0.0:
        return mul(ic, pow(sp, n))
    return (0.0, 0.0, 0.0)
예제 #9
0
 def get_direction(self, pos):
     d = sub(self.pos, pos)
     dl = length(d)
     return mul(d, 1.0 / dl), length(d)
예제 #10
0
 def get_intensity(self, pos):
     d = sub(self.pos, pos)
     dsq = dot(d, d)
     return mul(self.color, 100.0 / (99.0 + dsq))
예제 #11
0
 def fget(self):
     if not self._opos:
         self._opos = add(self.rp, mul(self.rd, self.odistance))
     return self._opos
예제 #12
0
    def intersect(self, raypos, raydir):
        tr = self.transform
        raydir = tr.inv_transform_vector(raydir)
        scale = 1.0 / length(raydir)
        raydir = mul(raydir, scale)  # normalize
        raypos = tr.inv_transform_point(raypos)
        eps = 1e-7

        px, py, pz = raypos
        dx, dy, dz = raydir
        ts = []
        if abs(dy) + eps >= 1.0:
            # ray is parallel to the cylinder axis
            frsd = 1.0 - px * px - pz * pz
            if frsd < 0.0:
                # outside cylinder
                return []
            ts = list(self._solvePlane(py, dy))
        elif abs(dy) < eps:
            # ray is orthogonal to the cylinder axis
            # check planes
            if py < 0.0 or py > 1.0:
                return []
            # check cylinder
            res = self._solveCyl(px, pz, dx, dz)
            if not res:
                return []
            ts = list(res)
        else:
            # general case
            # check cylinder
            res = self._solveCyl(px, pz, dx, dz)
            if not res:
                #print "baz"
                return []
            tc1, tc2 = res
            # check planes
            tp1, tp2 = self._solvePlane(py, dy)
            # same min-max strategy as for cubes
            # Check max of mins
            tmin = tp1
            tmax = tp2
            if tc1 > tmin:
                tmin = tc1
            if tc2 < tmax:
                tmax = tc2
            if tmin[0] > tmax[0]:
                return []
            if tmax[0] < 0.0:
                return []
            ts = [tmin, tmax]

        tmin, tmax = ts
        ts = []
        if tmin[0] > 0.0:
            ts.append(
                Intersection(scale, tmin[0], raypos, raydir, self,
                             Intersection.ENTRY, tmin[1]))
        if tmax[0] > 0.0:
            ts.append(
                Intersection(scale, tmax[0], raypos, raydir, self,
                             Intersection.EXIT, tmax[1]))
        return ts