Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .idea/PathTracing.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions .idea/inspectionProfiles/Project_Default.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions .idea/inspectionProfiles/profiles_settings.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

339 changes: 256 additions & 83 deletions .idea/workspace.xml

Large diffs are not rendered by default.

218 changes: 160 additions & 58 deletions PyPath.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,26 @@

#Modules
from math import sqrt, cos, sin
from random import random, gauss
from random import random, gauss, randrange
import array #for writing .ppm image file
from winsound import Beep #for beep sound when complete
from tkinter import * #for GUI
from main import prop_dict, obj_list

#========================================#
#==============CHANGE THESE==============#
#Must be a string like the default below
#and have .ppm extension as shown below
FILENAME = 'PyPath_Output.ppm'
FILENAME = prop_dict['output']
#Must be a string like the default below
DIRECTORY = 'C:\\Users\luish\ProgramasNovos\\'
DIRECTORY = './' # alterar de acordo com computador
#==============CHANGE THESE==============#
#========================================#

#Constants
EPSILON = 0.0001
HUGEVALUE = 1000000.0 #1 million
MAXDEPTH = 1 #max ray bounces
MAXDEPTH = 5 #max ray bounces
PI = 3.1415926535897932384
TWO_PI = 6.2831853071795864769
INVERTED_PI = 0.3183098861837906912
Expand Down Expand Up @@ -146,7 +147,7 @@ def OrientedHemiDir(u1, u2, normal, exp):
#Lambertian
class BxDF:
def __init__(self):
self.ke = BLACK #default, unless set with set_emission()
self.ke = RGBColour(prop_dict['ambient'], prop_dict['ambient'], prop_dict['ambient']) #default, unless set with set_emission() - change to ambient
def set_emission(self, emission_colour):
self.ke = emission_colour
def get_emission(self):
Expand Down Expand Up @@ -325,55 +326,57 @@ def __init__(self):
self.primitives = []
#trace light path
def trace_ray(self, ray, depth):
result = RGBColour(0.0, 0.0, 0.0) #black
t = HUGEVALUE
index = -1 #-1 means no hit

if depth > MAXDEPTH:
return result

#find closest hit object, its distance, hit_point and normal
#scan through primitives in scene, find closest
for i in range(0, len(self.primitives)):
#intersect returns tuple of (bool hit, distance, hit_point, normal)
hit_data = self.primitives[i].intersect(ray)
if hit_data[0] == True: #Hit
if hit_data[1] < t: #Distance
t = hit_data[1]
hit_point = hit_data[2] #hit_point
normal = hit_data[3] #normal
index = i #closest primitive index number

if index == -1: #No Hit
return BLACK

else: #Hit
wo = ray.d * -1.0 #outgoing (towards camera)
normal = orient_normal(normal, wo) #make normal point in correct direction

#sample_f returns tuple (incoming direction, pdf)
shading_data = self.primitives[index].get_BxDF().sample_f(normal, wo)
wi = shading_data[0] #incoming direction
pdf = shading_data[1] #pdf
if pdf <= 0.0:
pdf = 1.0

f = self.primitives[index].get_BxDF().f(wi, wo, normal)
incoming_ray = Ray(hit_point, wi) #make incoming to follow


#Russian Roulette
RR_prob = 0.66
if depth > 2:
if(random() < RR_prob): #2/3 chance we stop here
return result
result = RGBColour(prop_dict['background'][0], prop_dict['background'][1], prop_dict['background'][2]) #black - change to background
t = HUGEVALUE
index = -1 #-1 means no hit

if depth > MAXDEPTH:
return result

#find closest hit object, its distance, hit_point and normal
#scan through primitives in scene, find closest
for i in range(0, len(self.primitives)):
#intersect returns tuple of (bool hit, distance, hit_point, normal)
hit_data = self.primitives[i].intersect(ray)
if hit_data[0] == True: #Hit
if hit_data[1] < t: #Distance
t = hit_data[1]
hit_point = hit_data[2] #hit_point
normal = hit_data[3] #normal
index = i #closest primitive index number

if index == -1: #No Hit
return RGBColour(prop_dict['background'][0], prop_dict['background'][1], prop_dict['background'][2])

else: #Hit
wo = ray.d * -1.0 #outgoing (towards camera)
normal = orient_normal(normal, wo) #make normal point in correct direction

#sample_f returns tuple (incoming direction, pdf)
shading_data = self.primitives[index].get_BxDF().sample_f(normal, wo)
wi = shading_data[0] #incoming direction
pdf = shading_data[1] #pdf
if pdf <= 0.0:
pdf = 1.0

f = self.primitives[index].get_BxDF().f(wi, wo, normal)
incoming_ray = Ray(hit_point, wi) #make incoming to follow


#Russian Roulette
RR_prob = 0.66
if depth > 2:
if(random() < RR_prob): #2/3 chance we stop here
return result

result = result + f.multiply(self.trace_ray(incoming_ray, depth + 1)) * Dot(wi, normal) / pdf
#result = (result + f.multiply(self.trace_ray(incoming_ray, depth + 1)) * Dot(wi, normal) / pdf)/2
#Add emission
result = result + self.primitives[index].get_BxDF().get_emission()
result = result / RR_prob
return result #return final colour

result = result + f.multiply(self.trace_ray(incoming_ray, depth + 1)) * Dot(wi, normal) / pdf
#Add emission
result = result + self.primitives[index].get_BxDF().get_emission()
result = result / RR_prob
return result #return final colour

#add objects
def add_primitive(self, primitive):
self.primitives.append(primitive)
Expand Down Expand Up @@ -477,13 +480,89 @@ def render(self, integrator):
self.save_image(FILENAME) #FILENAME is define at top of source file
#Play sound to signal a beep (For Windows)
for i in range (1, 4):
Beep(i * 500, 250)
Beep(i * 500, 250)

#-------------------------------------------------Main
#Create Integrator
path_tracer = PathTraceIntegrator()
#Create Primitives w/ Materials
#materials

b = randrange(3)
b = 0

#Adicionando primeiro obj
for tFaces in obj_list[0].faces :
i = 0
a = 0.0
b = 0.0
c = 0.0
ve = []
p = []
q = []
for x in obj_list[0].faces:
ve = (obj_list[0].faces[i])
d = 0
i = i+1
for j in ve:
print(ve[d])
if d == 0:
a = (obj_list[0].vertices[ve[d]-1])
if d == 1:
b = (obj_list[0].vertices[ve[d]-1])
if d == 2:
c = (obj_list[0].vertices[ve[d]-1])
d = d+1
p = a - b
q = a - c
a.y*b.z - a.z*b.y, a.z*b.x - a.x*b.z, a.x*b.y - a.y*b.x
n = p[1]*q[2] - p[2]*q[1], p[2]*q[0] - p[0]*q[2], p[0]*q[1] - p[1]*q[0]
white_emitt_plane = Lambertian(RGBColour(1.0, 1.0, 1.0)) # emitindo luz branca enquanto obj não está desenhado
white_emitt_plane.set_emission(RGBColour(1.0, 1.0, 1.0)) # emitindo luz branca enquanto obj não está desenhado
plane_2 = Plane(Vector3D(obj_list[0].vertices[0][0], obj_list[0].vertices[0][1], obj_list[0].vertices[0][2]), Vector3D(n[0], n[1], n[2]))
plane_2.set_BxDF(white_emitt_plane) # trocado de cinza para branco
path_tracer.add_primitive(plane_2)


red2_emit = Lambertian(RGBColour(0.7, 0.0, 0.0))
red2_emit.set_emission(RGBColour(1.0, 0.0, 0.0))
green_emit = Lambertian(RGBColour(0.0, 0.7, 0.0))
green_emit.set_emission(RGBColour(0.0, 1.0, 0.0))
floor_emit = Lambertian(RGBColour(0.7, 0.7, 0.7))
floor_emit.set_emission(RGBColour(1.0, 1.0, 1.0))
white_emitt_plane = Lambertian(RGBColour(1.0, 1.0, 1.0)) # emitindo luz branca enquanto obj não está desenhado
white_emitt_plane.set_emission(RGBColour(1.0, 1.0, 1.0)) # emitindo luz branca enquanto obj não está desenh

if (b==0) :

red2_emit = Lambertian(RGBColour(0.7, 0.0, 0.0))
red2_emit.set_emission(RGBColour(1.0, 0.0, 0.0))
green_emit = Lambertian(RGBColour(0.0, 0.7, 0.0))
green_emit.set_emission(RGBColour(0.0, 1.0, 0.0))
floor_emit = Lambertian(RGBColour(0.7, 0.7, 0.7))
floor_emit.set_emission(RGBColour(1.0, 1.0, 1.0))


if (b==1) :

red2_emit = PerfectSpecular(RGBColour(0.0, 0.0, 0.0))
red2_emit.set_emission(RGBColour(1.0, 0.0, 0.0))
green_emit = PerfectSpecular(RGBColour(0.0, 0.0, 0.0))
green_emit.set_emission(RGBColour(0.0, 1.0, 0.0))
floor_emit = PerfectSpecular(RGBColour(0.0, 0.0, 0.0))
floor_emit.set_emission(RGBColour(1.0, 1.0, 1.0))


if (b==2) :

red2_emit = GlossySpecular(RGBColour(0.0, 0.0, 0.0), 0)
red2_emit.set_emission(RGBColour(1.0, 0.0, 0.0), 0)
green_emit = GlossySpecular(RGBColour(0.0, 0.0, 0.0), 0)
green_emit.set_emission(RGBColour(0.0, 1.0, 0.0))
floor_emit = GlossySpecular(RGBColour(0.0, 0.0, 0.7), 0)
floor_emit.set_emission(RGBColour(1.0, 1.0, 1.0))


gold_diff = Lambertian(RGBColour(1.0, 0.8, 0.3))
ground_diff = Lambertian(RGBColour(0.15, 0.15, 0.15))
red_emitt = Lambertian(RGBColour(3.0, 0.0, 0.0))
Expand All @@ -508,24 +587,47 @@ def render(self, integrator):
path_tracer.add_primitive(sphere_3)
#sphere 4 - mirror front
sphere_4 = Sphere(Vector3D(4.0, -8.0, 20.0), 8.0)
#sphere_4 = Sphere(Vector3D(3.411, -3.8416, -16.59), 2.0)
sphere_4.set_BxDF(glossy)
path_tracer.add_primitive(sphere_4)
#plane 1 - bottom ground
plane_1 = Plane(Vector3D(0.0, -16.0, 0.0), Vector3D(0.0, 1.0, 0.0))
plane_1.set_BxDF(ground_diff)
path_tracer.add_primitive(plane_1)
#plane 2 - top light
plane_2 = Plane(Vector3D(0.0, 45.0, 0.0), Vector3D(0.0, -1.0, 0.0))
plane_2.set_BxDF(grey_emitt_plane)
path_tracer.add_primitive(plane_2)
#plane_2 = Plane(Vector3D(0.0, 45.0, 0.0), Vector3D(0.0, -1.0, 0.0))
#plane_2 = Plane(Vector3D(-0.91, 3.836, -23.324), Vector3D(0.0, -5.758479999999996, 0.0))
#plane_2.set_BxDF(white_emitt_plane) # trocado de cinza para branco
#path_tracer.add_primitive(plane_2)

plane_3 = Plane(Vector3D(-3.822, -3.8416, -16.59), Vector3D(124.237344, 0.0, 0.0))
plane_3.set_BxDF(red2_emit) # esq
path_tracer.add_primitive(plane_3)
plane_4 = Plane(Vector3D(3.822, -3.8416, -32.76), Vector3D(-124.237344, 0.0, 0.0))
plane_4.set_BxDF(green_emit) # dir
path_tracer.add_primitive(plane_4)
plane_5 = Plane(Vector3D(3.822, -3.8416, -16.59), Vector3D(0.0, 123.60347999999999, 0.0))
plane_5.set_BxDF(floor_emit) # chao
path_tracer.add_primitive(plane_5)
plane_6 = Plane(Vector3D(-3.822, -3.8416, -32.76), Vector3D(0.0, 0.0, 58.730380800000006))
plane_6.set_BxDF(floor_emit) # atras
path_tracer.add_primitive(plane_6)
plane_7 = Plane(Vector3D(3.822, 3.8416, -32.76), Vector3D(0.0, -123.60347999999999, 0.0))
plane_7.set_BxDF(floor_emit) # chao
path_tracer.add_primitive(plane_7)


#Create Camera
eye = Vector3D(-3.0, 0.0, 190.0) #higher z = more narrow view
eye = Vector3D(prop_dict['eye'][0], prop_dict['eye'][1], prop_dict['eye'][2]) #higher z = more narrow view
#eye = Vector3D(-3.0, 0.0, 190.0) # para testar
focal = Vector3D(0.0, 0.0, 0.0)
view_distance = 1000 #larger = more orthographic like
up = Vector3D(0.0, 1.0, 0.0)
#height = int (prop_dict['size'][0])
#width = int (prop_dict['size'][1])
height = 400
width = 400
spp = 128
spp = int (prop_dict['npaths'])
cam = Camera(eye, focal, view_distance, up, height, width, spp)
cam.render(path_tracer) #trace scene and save image

Expand Down
Binary file added __pycache__/PyPath.cpython-35.pyc
Binary file not shown.
Binary file modified __pycache__/helper.cpython-35.pyc
Binary file not shown.
Binary file added __pycache__/main.cpython-35.pyc
Binary file not shown.
Binary file modified __pycache__/objetos.cpython-35.pyc
Binary file not shown.
Binary file added cornell.pnm
Binary file not shown.
6 changes: 3 additions & 3 deletions helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ def output(self,values):
def __get_faces(self, name):
faces = []

f = open ('.\src\\' + name, 'r')
f = open ('./src//' + name, 'r')

for line in f:
# Pulando linhas em branco
Expand All @@ -100,7 +100,7 @@ def __get_vertices(self, name):
vertices = []
faces = []

f = open ('.\src\\' + name, 'r')
f = open ('./src//' + name, 'r')

for line in f:
# Pulando linhas em branco
Expand Down Expand Up @@ -137,4 +137,4 @@ def read(t, values):
# Chamamos a função com nome read_ + tipo do valor a ser lido(object, light, eye...)
func = getattr(read, t)
result = func(values)
return result
return result
Loading