Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

КомпГр_ЛР6_Заболотников_Петрова_Романова_9373

.pdf
Скачиваний:
12
Добавлен:
20.06.2023
Размер:
874.64 Кб
Скачать

self.label_number_sphere_2 = ctk.CTkLabel(master=self.frame_right, text="Вторая сфера")

self.label_number_sphere_2.grid(row=6, column=0,columnspan=4, pady=0, padx=20, sticky="e")

self.entry000 = ctk.CTkEntry(master=self.frame_right, width=80,

textvariable=self.x3) self.entry000.grid(row=7, column=0, columnspan=2, pady=0, padx=20,

sticky="nw")

self.entry111 = ctk.CTkEntry(master=self.frame_right, width=50,

textvariable=self.y3) self.entry111.grid(row=7, column=0, columnspan=2, pady=0, padx=145,

sticky="nwe")

self.entry222 = ctk.CTkEntry(master=self.frame_right, width=80,

textvariable=self.z3) self.entry222.grid(row=7, column=0, columnspan=2, pady=0, padx=20,

sticky="ne")

self.label_number_sphere_3 = ctk.CTkLabel(master=self.frame_right, text="Третья сфера")

self.label_number_sphere_3.grid(row=7, column=0,columnspan=4, pady=0, padx=20, sticky="ne")

self.entry0c = ctk.CTkEntry(master=self.frame_right, width=80,

textvariable=self.r1) self.entry0c.grid(row=9, column=0, columnspan=2, pady=5, padx=20,

sticky="nw")

self.entry1c = ctk.CTkEntry(master=self.frame_right, width=50, textvariable=self.g1)

self.entry1c.grid(row=9, column=0, columnspan=2, pady=5, padx=145, sticky="nwe")

self.entry2c = ctk.CTkEntry(master=self.frame_right, width=80, textvariable=self.b1)

11

self.entry2c.grid(row=9, column=0, columnspan=2, pady=5, padx=20, sticky="ne")

self.label_number_sphere_color_1 = ctk.CTkLabel(master=self.frame_right, text="Первая сфера")

self.label_number_sphere_color_1.grid(row=9, column=0,columnspan=4, pady=0, padx=20, sticky="ne")

self.entry00c = ctk.CTkEntry(master=self.frame_right, width=80, textvariable=self.r2)

self.entry00c.grid(row=10, column=0, columnspan=2, pady=5, padx=20, sticky="nw")

self.entry11c = ctk.CTkEntry(master=self.frame_right, width=50, textvariable=self.g2)

self.entry11c.grid(row=10, column=0, columnspan=2, pady=5, padx=145, sticky="nwe")

self.entry22c = ctk.CTkEntry(master=self.frame_right, width=80, textvariable=self.b2)

self.entry22c.grid(row=10, column=0, columnspan=2, pady=5, padx=20, sticky="ne")

self.label_number_sphere_color_2 = ctk.CTkLabel(master=self.frame_right, text="Вторая сфера")

self.label_number_sphere_color_2.grid(row=10, column=0,columnspan=4, pady=0, padx=20, sticky="ne")

self.entry000c = ctk.CTkEntry(master=self.frame_right, width=80, textvariable=self.r3)

self.entry000c.grid(row=11, column=0, columnspan=2, pady=5, padx=20, sticky="nw")

self.entry111c = ctk.CTkEntry(master=self.frame_right, width=50, textvariable=self.g3)

12

self.entry111c.grid(row=11, column=0, columnspan=2, pady=5, padx=145, sticky="nwe")

self.entry222c = ctk.CTkEntry(master=self.frame_right, width=80, textvariable=self.b3)

self.entry222c.grid(row=11, column=0, columnspan=2, pady=5, padx=20, sticky="ne")

self.label_number_sphere_color_3 = ctk.CTkLabel(master=self.frame_right, text="Третья сфера")

self.label_number_sphere_color_3.grid(row=11, column=0,columnspan=4, pady=0, padx=20, sticky="ne")

self.entry_width = ctk.CTkEntry(master=self.frame_right, width=80, textvariable=self.width_im)

self.entry_width.grid(row=13, column=0, columnspan=2, pady=5, padx=20, sticky="w")

self.button_5 = ctk.CTkButton(master=self.frame_right, text="Нарисовать сцену", border_width=2, # <- custom

border_width

fg_color=None, # <- no fg_color command= self.write_to_image)

self.update()

self.button_5.grid(row=8, column=2, columnspan=1, pady=20, padx=20, sticky="we")

def apply(self): centers = []

for i in self.sph_c: t = []

for j in i: t.append(float(j.get()))

centers.append(t) t = []

colors = []

for i in self.sph_col: t = []

for j in i: t.append(float(j.get()))

13

colors.append(t) t = []

self.height = int(self.width_im.get()) self.width = int(self.height * 16.0 / 9.0) for i in range(len(centers[0])):

self.spheres[i + 1] = Sphere(vect3(centers[i][0], centers[i][1],centers[i][2]),

vect3(colors[i][0], colors[i][1],

colors[i][2]), abs(centers[i][1]))

def reset(self):

self.spheres = [Sphere(vect3(0, -1000, 0), vect3(1, 1, 1), 1000), Sphere(vect3(-3,1,1), vect3(2,2,2), 1), Sphere(vect3(0,1,1), vect3(1,1,1), 0.8), Sphere(vect3(2,1,1), vect3(1,2,2), 0.6),

# Sphere(vect3(0, 1004, 0), vect3(1, 1, 1), 1000),

]

# light sources

self.lights = [Sphere(vect3(0, 100, 0), vect3(0.0, 0.1, 0.2), 0), Sphere(vect3(100, 100, 200), vect3(0.3, 0.1, 0), 0), Sphere(vect3(-100, 100, 200), vect3(0.1, 0.3, 0.0),

0)]

c =

[[0.0,0.0,0.0],

 

[0.0,0.0,0.0],

 

[0.0,0.0,0.0]]

col

= [[0.0,0.0,0.0],

[0.0,0.0,0.0,],

[0.0,0.0,0.0]] w = 100

for i in range(len(c)):

for j in range(len(c[0])): self.sph_c[i][j].set(c[i][j])

for i in range(len(col)):

for j in range(len(col[0])): self.sph_col[i][j].set(col[i][j])

self.width_im.set(w) self.update()

def write_to_image(self):

14

maxval = 255

ppm_header = f'P6\n{self.width} {self.height}\n{maxval}\n' my_file = 'C:/USERS/Admin/blue_red_example1.ppm'

with open(my_file, 'wb') as f: f.write(bytearray(ppm_header, 'ascii'))

for y in range(self.height): for x in range(self.width):

c = trace(len(self.spheres) - 1, vect3(0, 1, 5), unit_vector(vect3(x - self.width / 2,

self.height / 2.0 - y, -self.height)), self.lights, self.spheres) pixel_col = vect3(int(min(1.0, c.x()) * 255.999),

int(min(1.0, c.y()) * 255.999),

int(min(1.0, c.z()) * 255.999)) write_color(my_file, pixel_col)

self.progressbar.set((self.width * y) / (self.width * self.height))

self.update()

window = tkinter.Tk()

window.geometry(f"{self.width + 100}x{self.height + 100}+500+500") canvas = tkinter.Canvas(window, width=self.width, height=self.height,

bg="#111111")

canvas.pack()

img = tkinter.PhotoImage(master=canvas, file=my_file, width=self.width, height=self.height)

canvas.create_image((0, 0), image=img, state="normal", anchor="nw") window.mainloop()

def change_appearance_mode(self, new_appearance_mode): ctk.set_appearance_mode(new_appearance_mode)

def on_closing(self, event=0): self.destroy()

if __name__ == "__main__": app = App() app.mainloop()

Файл «Vector.py»

class vec3:

import numpy as np class vec3:

15

def __new__(cls, *args, **kwargs): return super().__new__(cls)

def __init__(self, e0=0.0, e1=0.0, e2=0.0): self.e = [e0, e1, e2]

def x(self):

return self.e[0] def y(self):

return self.e[1] def z(self):

return self.e[2] def normalize(self):

n = self.__len__() if n > 0:

nn = 1 / n self.e[0] *= nn self.e[1] *= nn self.e[2] *= nn

return self def __neg__(self):

return vec3(-self.e[0], -self.e[1], -self.e[2]) def __getitem__(self, item):

return self.e[item]

def __iadd__(self, other): self.e[0] += other.e[0] self.e[1] += other.e[1] self.e[2] += other.e[2] return self

def __imul__(self, t: float): self.e[0] *= t

self.e[1] *= t self.e[2] *= t return self

def __idiv__(self, t: float): return self.__imul__(1 / t)

def __len__(self):

return np.sqrt(self.length_squared()) def length_squared(self):

return self.e[0] ** 2 + self.e[1] ** 2 + self.e[2] ** 2 def __repr__(self):

return f'vec3({self.e[0]}, {self.e[1]}, {self.e[2]})'

16

def __str__(self):

return f'{self.e[0]} {self.e[1]} {self.e[2]}' def __add__(self, other):

if isinstance(other, self.__class__): x = self.e[0] + other.e[0]

y = self.e[1] + other.e[1] z = self.e[2] + other.e[2] return vec3(x, y, z)

elif isinstance(other, int): x = self.e[0] + other

y = self.e[1] + other z = self.e[2] + other return vec3(x, y, z)

elif isinstance(other, float): x = self.e[0] + other

y = self.e[1] + other z = self.e[2] + other return vec3(x, y, z)

def __sub__(self, other):

if isinstance(other, self.__class__): x = self.e[0] - other.e[0]

y = self.e[1] - other.e[1] z = self.e[2] - other.e[2] return vec3(x, y, z)

elif isinstance(other, int): x = self.e[0] - other

y = self.e[1] - other z = self.e[2] - other return vec3(x, y, z)

elif isinstance(other, float): x = self.e[0] - other

y = self.e[1] - other z = self.e[2] - other return vec3(x, y, z)

def __mul__(self, other):

if isinstance(other, self.__class__): x = self.e[0] * other.e[0]

y = self.e[1] * other.e[1] z = self.e[2] * other.e[2] return vec3(x, y, z)

elif isinstance(other, int):

17

x = self.e[0] * other y = self.e[1] * other z = self.e[2] * other return vec3(x, y, z)

elif isinstance(other, float): x = self.e[0] * other

y = self.e[1] * other z = self.e[2] * other return vec3(x, y, z)

def __rmul__(self, t: float): return self * t

def __truediv__(self, t: float): return self * (1 / t)

def cross(self, other):

return vec3(self.e[1] * other.e[2] - self.e[2] * other.e[1], self.e[2] * other.e[0] - self.e[0] * other.e[2], self.e[0] * other.e[1] - self.e[1] * other.e[0])

def dot(self, other):

return self.e[0] * other.e[0] + self.e[1] * other.e[1] + self.e[2] * other.e[2]

def unit_vector(v: vec3):

return v.__truediv__(v.__len__().real)

point3 = vec3 color = vec3 vect3 = vec3

Файл «Color.py»

from struct import pack

def write_color(file_name, pixel_color):

x= int(pixel_color[0])

y= int(pixel_color[1])

z= int(pixel_color[2])

with open(file_name, 'ab') as file: file.write(pack('=BBB', x, y, z)) file.close()

Файл «Start.py»

from vector import * #from ray import * import ray

from math import pi, sqrt, inf

18

from color import *

from tkinter import Canvas, Tk, PhotoImage

class Sphere:

def __init__(self, p, ce, r): self.p = p

self.radius = r self.center = ce

def intersect(sphere: Sphere, start: vect3, direction: vect3, intersec: float):

P = start - sphere.p

a = dot(direction, direction) b = dot(P, direction) * 2

c1 = dot(P, P) - sphere.radius * sphere.radius d = b * b - 4 * a * c1

if d < 0: return 0

dsc = 2.0 * a sqd = sqrt(d)

intersec = (-b - sqd) / dsc

if intersec > 0.1: return intersec

intersec = (-b + sqd) / dsc if intersec > 0.1:

return intersec return 0

def trace(spheres_count, O, distance, lights, spheres): h = -1

T: float = 101118152822811797749760.0 t = 10.0 ** 10

for i in range(NS):

if intersect(spheres[i], O, distance, T):

T = intersect(spheres[i], O, distance, T) if t > T:

t = T h = i

if h > -1:

p = O + distance * T

n = unit_vector(p - spheres[h].p)

19

r = distance - n * dot(distance, n) * 2 c2 = spheres[h].center * 0.1

if not h:

spheres[h].center = vect3(1, 1, 1) if (int(p.x() + 10.0 ** 2) + int(p.z() + 10.0 ** 2)) & 1 else vect3(0, 0, 0)

for j in range(NL):

l1 = unit_vector(lights[j].p - p) sh = 0

for i in range(NS):

if intersect(spheres[i], p, l1, t): sh = 1

if not sh:

df = max(0, dot(l1, n)) * 0.7

sp = (max(0, dot(l1, n)) ** 50) * 0.3

c2 = c2 + spheres[h].center * lights[j].center * df + vect3(sp, sp, sp)

spheres_count = spheres_count - 1 if spheres_count:

c2 = c2 + trace(spheres_count, p, r, lights, spheres) * 0.51 return c2

return vect3(1 - distance.y(), 1 - distance.y(), 0.5 + distance.y())

spheres = [Sphere(vect3(0, -1000, 0), vect3(1, 1, 1), 1000), Sphere(vect3(-2.0, 1.0, 0.0), vect3(1, 0.0, 0.0), 1), Sphere(vect3(0.0, 0.8, 0.0), vect3(0.0, 1.0, 0.0), 0.8), Sphere(vect3(2.0, 10, -10.0), vect3(0.0, 0.0, 1.0), 0.6),

# Sphere(vect3(0, 1004, 0), vect3(1, 1, 1), 1000),

]

# light sources

lights = [Sphere(vect3(0, 100, 0), vect3(0.0, 0.1, 0.2), 0), Sphere(vect3(100, 100, 200), vect3(0.3, 0.1, 0), 0), Sphere(vect3(-100, 100, 200), vect3(0.1, 0.3, 0.0), 0)]

NS = 4

NL = 3

if __name__ == '__main__':

20