Почему 2d raytracing + mirror делают (иногда) полупрозрачное зеркало (свет проходит и отражается) - PullRequest
0 голосов
/ 21 апреля 2020

с использованием pygame (только с python)

Расшифровка: я изучаю трассировку лучей, и я хотел сделать зеркала (без силы света, 0% прозрачное зеркало), classi c, направляющий источники света желтые, отражающие оранжевые, а отражающие отражающие - красные, а иногда, когда источник света попадает в зеркало, он создает отражение (basi c), а затем появляется другое отражение (всегда красное, (это может помочь)), проходящее через него. зеркало с тем же углом, что и источник света (непосредственно через него (но оно становится красным (отражение при отражении)))

есть код моей стены / зеркала

class Boundary:
    def __init__(self, screen: pg.display, start: tuple, end: tuple,state: str):
        self.start = pg.Vector2(start)
        self.end = pg.Vector2(end)
        self.image = None
        self.state=state
        self.color=(255,255,255)
        self.tagged_rays=""  # None
        if self.state=="mirror":
            self.color = (0,255,255)
            self.tagged_rays=[]

    def update(self, screen: pg.display):
        if self.state=="mirror":
            ## writes the len of the tagged rays list var
            screen.blit(pg.font.SysFont("helvetica", 10).render("{}".format(len(self.tagged_rays)), 10, (0,255,0)), (int(self.start.x+10), int(self.start.y)))
            self.tagged_rays=[]
            #print(len(self.tagged_rays)) 
        ## draw the wall / the mirror
        self.image = pg.draw.line(screen, (self.color), self.start, self.end, 2)

экран ошибки

есть код моего луча

class Ray:
    def __init__(self, p: Particle, heading: float = 0):
        self.start = p.pos

        self.heading = heading
        self.end: pg.math.Vector2 = pg.math.Vector2()
        self.image = None

        #self.color = (randint(215,225),randint(175,200),0)
        self.color =(255,255,0)

        self.isrefleted=False

        self.reflect_angle=0

    def update(self, screen: pg.display, p: Particle, boundaries: list, rays:list, reflections:list):
        self.isrefleted=False
        self.start = p.pos 
        self.end.from_polar((sys.maxsize, self.heading))

        closest = float("inf")
        new_end = pg.Vector2()

        x3 = self.start.x
        x4 = self.end.x

        y3 = self.start.y
        y4 = self.end.y

        for b in boundaries:
            if b.state == "mirror" and self in b.tagged_rays:
                continue
            x1 = b.start.x
            x2 = b.end.x
            y1 = b.start.y
            y2 = b.end.y

            den = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4)
            if den == 0:
                return

            t_num = (x1 - x3) * (y3 - y4) - (y1 - y3) * (x3 - x4)
            t = t_num / den
            u_num = -((x1 - x2) * (y1 - y3) - (y1 - y2) * (x1 - x3))
            u = u_num / den

            if u >= 0 and 0 <= t <= 1:
                x = x1 + t * (x2 - x1)
                y = y1 + t * (y2 - y1)
                dist = self.start.distance_to((x, y))
                if dist < closest:
                    closest = dist
                    new_end.xy = x, y

                    if b.state=="mirror":
                        #print("REFLET")
                        #print(self.start.x-new_end.x,",",b.start.x-b.start.y)
                        radius1, self.reflect_angle1 = (self.start - self.end).as_polar()

                        radius2, self.reflect_angle2 = (b.start - b.end).as_polar()

                        #radius2, self.reflect_angle3 = (self.reflect_angle1 - self.reflect_angle2).as_polar()

                        if self.start.x < self.end.x:
                            #print(self.reflect_angle2,"pos")
                            self.reflect_angle2-=90
                        elif self.start.x > self.end.x:
                            #print(self.reflect_angle2,"neg")
                            self.reflect_angle2+=90
                        else:
                            pass
                            #print()

                        ##  90* from the miror ( to understand the mechanics )
                        _90_reflet= False
                        if _90_reflet:
                            reflect2= Reflect(new_end, self.reflect_angle2,(0,255,0))
                            b.tagged_rays.append(reflect2)
                            reflections.append(reflect2)

                        reflect= Reflect(new_end, -self.reflect_angle1,(255,100,0))
                        b.tagged_rays.append(reflect)
                        reflections.append(reflect)

                        self.isrefleted=True

        if closest == float("inf"):
            self.end = self.start
            self.image = None
        else:
            self.end = new_end
            self.image = pg.draw.line(screen, self.color, (self.start.x,self.start.y), (self.end), 1)
            anglepos=pg.math.Vector2()
            anglepos.x = int(self.end.x)
            anglepos.y= int(self.end.y)
            w, h = pg.display.get_surface().get_size()
            xoffset=10
            yoffset=-3
            if anglepos.x+len(str(self.heading)) >w:
                anglepos.x -=50

            if anglepos.y+10 >h:
                anglepos.y -=20

            if 0> anglepos.y:
                anglepos.y=+10

            screen.blit(pg.font.SysFont("helvetica", 11).render("{}".format(self.heading), 10, (0,255,255)), (int(anglepos.x+xoffset), int(anglepos.y+yoffset)))
            #pg.draw.circle(screen,(255,0,0), (int(self.end.x),int(self.end.y)),5)

и там код моего отраженного луча

from particle import Particle
import pygame as pg
from random import randint

import math,sys

class Reflect:
    def __init__(self, r_End, heading: float = 0,color: tuple=(255,0,0)):
        self.start= r_End
        self.heading=heading
        self.end: pg.math.Vector2 = pg.math.Vector2()
        self.color =color
        self.isrefleted=False

    def update(self, screen: pg.display, p: Particle, boundaries: list,rays:list,reflections:list):
        self.isrefleted=False
        self.end.from_polar((sys.maxsize, self.heading))

        closest = float("inf")
        new_end = pg.Vector2()



        x3 = self.start.x+3
        x4 = self.end.x
        y3 = self.start.y
        y4 = self.end.y
        for b in boundaries:
            if b.state == "mirror" and self in b.tagged_rays:
                continue
            x1 = b.start.x
            x2 = b.end.x
            y1 = b.start.y
            y2 = b.end.y

            den = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4)
            if den == 0:
                return

            t_num = (x1 - x3) * (y3 - y4) - (y1 - y3) * (x3 - x4)
            t = t_num / den
            u_num = -((x1 - x2) * (y1 - y3) - (y1 - y2) * (x1 - x3))
            u = u_num / den

            if u >= 0 and 0 <= t <= 1:
                x = x1 + t * (x2 - x1)
                y = y1 + t * (y2 - y1)
                dist = self.start.distance_to((x, y))
                if dist < closest:
                    closest = dist
                    new_end.xy = x, y

                    if b.state=="mirror" and 1:
                        #print("REFLET")
                        #print(self.start.x-new_end.x,",",b.start.x-b.start.y)
                        radius1, self.reflect_angle1 = (self.start - self.end).as_polar()

                        radius2, self.reflect_angle2 = (b.start - b.end).as_polar()

                        #radius2, self.reflect_angle3 = (self.reflect_angle1 - self.reflect_angle2).as_polar()

                        if self.start.x < self.end.x:
                            #print(self.reflect_angle2,"pos")
                            self.reflect_angle2-=90
                        elif self.start.x > self.end.x:
                            #print(self.reflect_angle2,"neg")
                            self.reflect_angle2+=90
                        else:
                            pass
                            #print()

                        ##  90* from the miror ( to understand the mechanics )
                        _90_reflet= False
                        if _90_reflet:
                            reflect2= Reflect(new_end, self.reflect_angle2,(0,255,0))
                            b.tagged_rays.append(reflect2)
                            reflections.append(reflect2)
                        if not -1<abs(self.heading) <1:
                            if not 179<abs(self.heading) <181:
                                #print(self.heading)
                                reflect=None
                                reflect= Reflect(new_end, -self.reflect_angle1,(255,0,0))
                                b.tagged_rays.append(reflect)
                                reflections.append(reflect)
                                self.isrefleted=True
        if closest == float("inf"):
            self.end = self.start
            self.image = None
        else:
            self.end = new_end
            #print(self.end)
            self.image = pg.draw.line(screen, self.color, self.start, self.end,2)
            anglepos=pg.math.Vector2()
            anglepos.x = int(self.end.x)
            anglepos.y= int(self.end.y)
            w, h = pg.display.get_surface().get_size()
            xoffset=10
            yoffset=-3
            if anglepos.x+len(str(self.heading)) >w:
                anglepos.x -=50

            if anglepos.y+10 >h:
                anglepos.y -=20

            if 0> anglepos.y:
                anglepos.y=+10

            screen.blit(pg.font.SysFont("helvetica", 11).render("{}".format(self.heading), 10, (0,255,255)), (int(anglepos.x+xoffset), int(anglepos.y+yoffset)))
            #pg.draw.circle(screen,(255,0,0), (int(self.end.x),int(self.end.y)),5)

Правка, есть код частицы

import pygame as pg
from random import randint


class Particle:
    def __init__(self):
        info = pg.display.Info()
        self.image = None
        pg.math.Vector2()
        self.pos = pg.Vector2(randint(0, info.current_w), randint(0, info.current_h))
        self.heading = 0
        self.vel = pg.math.Vector2((0, 0))

    def update(self, screen: pg.display,mouseX=int(),mouseY=int()):
        #self.move_random()

        self.move_on_mouse(mouseX,mouseY)

        self.image = pg.draw.circle(screen, pg.Color('white'), (int(self.pos[0]), int(self.pos[1])), 4, 2) #basic (random)


    def move_random(self):
        info = pg.display.Info()

        self.pos += self.vel
        if self.pos.x < 0:
            self.pos.x = 0
            self.vel.x += 5
        elif self.pos.x > info.current_w:
            self.pos.x = info.current_w - 1
            self.vel.x -= 5

        if self.pos.y < 0:
            self.pos.y = 0
            self.vel.y += 5
        elif self.pos.y > info.current_h:
            self.pos.y = info.current_h - 1
            self.vel.y -= 5

        self.vel.x += randint(-5, 5)
        self.vel.y += randint(-5, 5)
    def move_on_mouse(self,mouseX=int(),mouseY=int()):
        self.pos = pg.Vector2(mouseX, mouseY)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...