Exemple #1
0
    def intersectRay (self, ray: Ray, isEyeRay:bool=False) -> np.ndarray:
        rayLength = MV.dot(ray.direction, ray.direction) ** 0.5
        ray.direction = MV.normalize(ray.direction)

        rayOrigin_SphereCoord = MV.transformPoint(self.inverseMat, ray.origin)
        rayDir_SphereCoord = MV.transformVector(self.inverseMat, ray.direction)
        a = MV.dot(rayDir_SphereCoord, rayDir_SphereCoord)
        b = MV.dot(rayDir_SphereCoord, rayOrigin_SphereCoord)
        c = MV.dot(rayOrigin_SphereCoord, rayOrigin_SphereCoord) - 1**2
        
        d = b * b - a * c
        
        if d < 0:
            return np.inf
        if d >= 0:
            t1 = (-b + np.sqrt(d)) / a
            t2 = (-b - np.sqrt(d)) / a
            if (isEyeRay):
                tMin = min (t1, t2)
                tMax = max (t1, t2)
                if (tMin > rayLength):
                    return tMin
                elif (tMax > rayLength):
                    return tMax
                else:
                    return np.inf
            answer = min(t1, t2)
            if answer < 0:
                return np.inf
            else:
                return answer
Exemple #2
0
 def isInside (self, point: np.ndarray) -> bool:
     point_SphereCoord = MV.transformPoint(self.inverseMat, point)
     return (MV.dot(point_SphereCoord, point_SphereCoord) <= 1)
Exemple #3
0
def rayTracer (ray: Ray, scene: Scene):
    # find the intersection of the ray with all the object
    t = np.inf
    for i, obj in enumerate(scene.objects):
        # if the ray is eye-ray, check whether t < 1, 
        # if yes, omit it.
        if (np.array_equal(ray.origin, scene.camPoint)):
            tObj = obj.intersectRay(ray, True)
        else:
            tObj = obj.intersectRay(ray)
        if tObj < t:
            t, obj_idx = tObj, i
    # if there is not any intersection, return
    if t == np.inf:
        return
    
    obj = scene.objects[obj_idx]

    # converse the intersection point to Sphere Coordinate Sytem
    # then calculate the normal vector at the intersection point
    # finally converse it back to the World Coordinate System
    P = ray.origin + ray.direction * t
    P_SphereCoord = MV.transformPoint(obj.inverseMat, P)

    N_SphereCoord = P_SphereCoord - np.zeros(3) # sphere origin is (0, 0, 0) in sphere coordinate system

    # N = P - obj.pos
    # N_SphereCoord = MV.transformVector(obj.inverseMat, N)

    N = MV.transformVector(obj.transposeInverseMat, N_SphereCoord)
    N = MV.normalize(N)

    V = MV.normalize(-P)
    color = obj.color.copy()

    '''
    PIXEL_COLOR[c] = Ka*Ia[c]*O[c] +

    for each point light (p) { Kd*Ip[c]*(N dot L)*O[c]+Ks*Ip[c]*(R dot V)n } 
    
    + Kr*(Color returned from reflection ray)

    O is the object color (<r> <g> <b>)
    '''
    Ka = scene.ambient * obj.k_a 
    Kd = np.zeros(3)
    Ks = np.zeros(3)
    for light in scene.lightSources:
        L = MV.normalize(light.pos - P)
        # Shadow: find if the point is shadowed or not.
        ray = Ray(P + N * .000001, L)
        l = [sphere.intersectRay(ray) 
        for k, sphere in enumerate(scene.objects) if k != obj_idx]
        if l and min(l) < np.inf:
            continue
        if (obj.isInside(scene.atVector)):
            if (obj.isInside(light.pos)):
                N = -N
            else:
                continue
        
        R = MV.normalize(2 * MV.dot(N, L) * N - L)

        # Lambert shading (diffuse).
        Kd += obj.k_d * max(MV.dot(N, L), 0.)  *  ( light.intensity )
        # Blinn-Phong shading (specular)
        Ks += obj.k_s * ( max(np.dot(R, V), 0.) ** obj.specular ) * ( light.intensity )
    pixelColor = Ka * color + Kd * color + Ks
    return obj, P + N * .000001, N, pixelColor