예제 #1
0
    def pointColor(self, material, intersect):

        objectColor = [material.diffuse[2] / 255,
                                material.diffuse[1] / 255,
                                material.diffuse[0] / 255]

        ambientColor = [0,0,0]
        diffuseColor = [0,0,0]
        specColor =[0,0,0]

        shadow_intensity = 0

        if self.ambientLight:
            ambientColor = [self.ambientLight.strength * self.ambientLight.color[2] / 255,
                                     self.ambientLight.strength * self.ambientLight.color[1] / 255,
                                     self.ambientLight.strength * self.ambientLight.color[0] / 255]

        if self.pointLight:
            # Sacamos la direccion de la luz para este punto
            light_dir = substractNPArray(self.pointLight.position, intersect.point)
            light_dir = normNPArray(light_dir)

            # Calculamos el valor del diffuse color
            intensity = self.pointLight.intensity * max(0, dotNPArray(light_dir, intersect.normal))
            diffuseColor = [intensity * self.pointLight.color[2] / 255,
                                     intensity * self.pointLight.color[1] / 255,
                                     intensity * self.pointLight.color[2] / 255]

            # Iluminacion especular
            view_dir = substractNPArray(self.camPosition, intersect.point)
            view_dir = normNPArray(view_dir)

            # R = 2 * (N dot L) * N - L
            reflect = 2 * dotNPArray(intersect.normal, light_dir)
            reflect = multiplyConstant(reflect, intersect.normal)
            reflect = substractNPArray(reflect, light_dir)

            # spec_intensity: lightIntensity * ( view_dir dot reflect) ** specularidad
            spec_intensity = self.pointLight.intensity * (max(0, dotNPArray(view_dir, reflect)) ** material.spec)

            specColor = [spec_intensity * self.pointLight.color[2] / 255,
                                  spec_intensity * self.pointLight.color[1] / 255,
                                  spec_intensity * self.pointLight.color[0] / 255]

            for obj in self.scene:
                if obj is not intersect.sceneObject:
                    hit = obj.ray_intersect(intersect.point,  light_dir)
                    if hit is not None and intersect.distance < np.linalg.norm(substractNPArray(self.pointLight.position, intersect.point)):
                        shadow_intensity = 1

        # Formula de iluminacion
        # finalColor = (ambientColor + (1 - shadow_intensity) * (diffuseColor + specColor)) * objectColor
        finalColor = multiplyColor(sumNPArray(ambientColor, multiplyConstant((1 - shadow_intensity),sumNPArray(diffuseColor, specColor))),objectColor)
        #Nos aseguramos que no suba el valor de color de 1

        r = min(1,finalColor[0])
        g = min(1,finalColor[1])
        b = min(1,finalColor[2])

        return color(r, g, b)
def reflectVector(normal, dirVector):
    # R = 2 * (N dot L) * N - L
    reflect = 2 * dotNPArray(normal, dirVector)
    reflect = multiplyConstant(reflect, normal)
    reflect = substractNPArray(reflect, dirVector)
    reflect = normNPArray(reflect)
    return reflect
    def ray_intersect(self, orig, dir):
        # t = (( position - origRayo) dot normal) / (dirRayo dot normal)

        denom = dotNPArray(dir, self.normal)

        if abs(denom) > 0.0001:
            t = dotNPArray(self.normal, substractNPArray(self.position,
                                                         orig)) / denom
            if t > 0:
                # P = O + tD
                hit = sumNPArray(orig, t * np.array(dir))

                return Intersect(distance=t,
                                 point=hit,
                                 normal=self.normal,
                                 sceneObject=self)

        return None
def fresnel(N, I, ior):
    # N = normal
    # I = incident vector
    # ior = index of refraction
    cosi = max(-1, min(1, dotNPArray(I, N)))
    etai = 1
    etat = ior

    if cosi > 0:
        etai, etat = etat, etai

    sint = etai / etat * (max(0, 1 - cosi * cosi)**0.5)

    if sint >= 1:  # Total Internal Reflection
        return 1

    cost = max(0, 1 - sint * sint)**0.5
    cosi = abs(cosi)
    Rs = ((etat * cosi) - (etai * cost)) / ((etat * cosi) + (etai * cost))
    Rp = ((etai * cosi) - (etat * cost)) / ((etai * cosi) + (etat * cost))
    return (Rs * Rs + Rp * Rp) / 2
def refractVector(N, I, ior):
    # N = normal
    # I = incident vector
    # ior = index of refraction
    # Snell's Law
    cosi = max(-1, min(1, dotNPArray(I, N)))
    etai = 1
    etat = ior

    if cosi < 0:
        cosi = -cosi
    else:
        etai, etat = etat, etai
        N = np.array(N) * -1

    eta = etai / etat
    k = 1 - eta * eta * (1 - (cosi * cosi))

    if k < 0:  # Total Internal Reflection
        return None

    R = eta * np.array(I) + (eta * cosi - k**0.5) * N
    return normNPArray(R)
    def ray_intersect(self, orig, dir):
        L = substractNPArray(self.center, orig)
        tca = dotNPArray(L, dir)
        l = magnitudeNpArray(L)  # magnitud de L
        d = (l**2 - tca**2)**0.5
        if d > self.radius:
            return None

        # thc es la distancia de P1 al punto perpendicular al centro
        thc = (self.radius**2 - d**2)**0.5
        t0 = tca - thc
        t1 = tca + thc
        if t0 < 0:
            t0 = t1

        if t0 < 0:  # t0 tiene el valor de t1
            return None

        # P = O + tD
        hit = sumNPArray(orig, t0 * np.array(dir))
        norm = substractNPArray(hit, self.center)
        norm = norm / np.linalg.norm(norm)

        return Intersect(distance=t0, point=hit, normal=norm, sceneObject=self)
    def castRay(self, orig, direction, origObj=None, recursion=0):

        material, intersect = self.scene_intercept(orig, direction, origObj)

        if material is None or recursion >= MAX_RECURSION_DEPTH:
            if self.envmap:
                return self.envmap.getColor(direction)
            return self.clear_color

        objectColor = np.array([
            material.diffuse[2] / 255, material.diffuse[1] / 255,
            material.diffuse[0] / 255
        ])

        ambientColor = np.array([0, 0, 0])
        diffuseColor = np.array([0, 0, 0])
        specColor = np.array([0, 0, 0])

        reflectColor = np.array([0, 0, 0])
        refractColor = np.array([0, 0, 0])

        finalColor = np.array([0, 0, 0])

        shadow_intensity = 0

        # Direccion de vista
        view_dir = substractNPArray(self.camPosition, intersect.point)
        view_dir = normNPArray(view_dir)

        if self.ambientLight:
            ambientColor = np.array([
                self.ambientLight.strength * self.ambientLight.color[2] / 255,
                self.ambientLight.strength * self.ambientLight.color[1] / 255,
                self.ambientLight.strength * self.ambientLight.color[0] / 255
            ])

        if self.pointLight:
            # Sacamos la direccion de la luz para este punto
            light_dir = substractNPArray(self.pointLight.position,
                                         intersect.point)
            light_dir = normNPArray(light_dir)

            # Calculamos el valor del diffuse color
            intensity = self.pointLight.intensity * max(
                0, dotNPArray(light_dir, intersect.normal))
            diffuseColor = np.array([
                intensity * self.pointLight.color[2] / 255,
                intensity * self.pointLight.color[1] / 255,
                intensity * self.pointLight.color[2] / 255
            ])

            # Iluminacion especular
            reflect = reflectVector(intersect.normal,
                                    light_dir)  # Reflejar el vector de luz

            # spec_intensity: lightIntensity * ( view_dir dot reflect) ** especularidad
            spec_intensity = self.pointLight.intensity * (max(
                0, dotNPArray(view_dir, reflect))**material.spec)
            specColor = np.array([
                spec_intensity * self.pointLight.color[2] / 255,
                spec_intensity * self.pointLight.color[1] / 255,
                spec_intensity * self.pointLight.color[0] / 255
            ])

            shadMat, shadInter = self.scene_intercept(intersect.point,
                                                      light_dir,
                                                      intersect.sceneObject)
            if shadInter is not None and shadInter.distance < magnitudeNpArray(
                    substractNPArray(self.pointLight.position,
                                     intersect.point)):
                shadow_intensity = 1

        if material.matType == OPAQUE:
            # Formula de iluminacion, PHONG
            finalColor = (ambientColor + (1 - shadow_intensity) *
                          (diffuseColor + specColor))
        elif material.matType == REFLECTIVE:
            reflect = reflectVector(intersect.normal, np.array(direction) * -1)
            reflectColor = self.castRay(intersect.point, reflect,
                                        intersect.sceneObject, recursion + 1)
            reflectColor = np.array([
                reflectColor[2] / 255, reflectColor[1] / 255,
                reflectColor[0] / 255
            ])

            finalColor = reflectColor + (1 - shadow_intensity) * specColor

        elif material.matType == TRANSPARENT:

            outside = dotNPArray(direction, intersect.normal) < 0
            bias = 0.001 * intersect.normal
            kr = fresnel(intersect.normal, direction, material.ior)

            reflect = reflectVector(intersect.normal, np.array(direction) * -1)
            reflectOrig = sumNPArray(intersect.point,
                                     bias) if outside else substractNPArray(
                                         intersect.point, bias)
            reflectColor = self.castRay(reflectOrig, reflect, None,
                                        recursion + 1)
            reflectColor = np.array([
                reflectColor[2] / 255, reflectColor[1] / 255,
                reflectColor[0] / 255
            ])

            if kr < 1:
                refract = refractVector(intersect.normal, direction,
                                        material.ior)
                refractOrig = substractNPArray(
                    intersect.point, bias) if outside else sumNPArray(
                        intersect.point, bias)
                refractColor = self.castRay(refractOrig, refract, None,
                                            recursion + 1)
                refractColor = np.array([
                    refractColor[2] / 255, refractColor[1] / 255,
                    refractColor[0] / 255
                ])

            finalColor = reflectColor * kr + refractColor * (1 - kr) + (
                1 - shadow_intensity) * specColor

        # Le aplicamos el color del objeto
        finalColor *= objectColor

        #Nos aseguramos que no suba el valor de color de 1
        r = min(1, finalColor[0])
        g = min(1, finalColor[1])
        b = min(1, finalColor[2])

        return color(r, g, b)