| 5 | random_table = [uniform(-1, 1) for _ in range(255)] |
| 6 | |
| 7 | class Particles: |
| 8 | def __init__(self, density=10, position=(0, 0, 0), size=1) -> None: |
| 9 | self.density = density |
| 10 | self.position = position |
| 11 | self.size = size |
| 12 | self.density_r = 1 / density |
| 13 | self.particles = [ |
| 14 | [x * self.density_r + position[0], y * self.density_r + position[1], z * self.density_r + position[2],] |
| 15 | for x in range(density * size) for y in range(density * size) for z in range(density * size) |
| 16 | ] |
| 17 | for particle in self.particles: |
| 18 | particle[0] += random_table[int((particle[1] + particle[2]) * self.density) % 255] * self.density_r |
| 19 | particle[1] += random_table[int((particle[0] + particle[2]) * self.density) % 255] * self.density_r |
| 20 | particle[2] += random_table[int((particle[0] + particle[1]) * self.density) % 255] * self.density_r |
| 21 | particle[0] = (particle[0] - self.position[0]) % self.size + self.position[0] |
| 22 | particle[1] = (particle[1] - self.position[1]) % self.size + self.position[1] |
| 23 | particle[2] = (particle[2] - self.position[2]) % self.size + self.position[2] |
| 24 | |
| 25 | def next_frame(self, time=0, percentage = 0.1): |
| 26 | start_index = int(len(self.particles) * random_table[time % 255]) |
| 27 | end_index = int(len(self.particles) * percentage) + start_index |
| 28 | for index in range(start_index, end_index): |
| 29 | particle = self.particles[index % len(self.particles)] |
| 30 | particle[0] += random_table[int((particle[1] + particle[2]) * self.density) % 255] * self.density_r * 0.01 |
| 31 | particle[1] += random_table[int((particle[0] + particle[2]) * self.density) % 255] * self.density_r * 0.01 |
| 32 | particle[2] += random_table[int((particle[0] + particle[1]) * self.density) % 255] * self.density_r * 0.01 |
| 33 | particle[0] = (particle[0] - self.position[0]) % self.size + self.position[0] |
| 34 | particle[1] = (particle[1] - self.position[1]) % self.size + self.position[1] |
| 35 | particle[2] = (particle[2] - self.position[2]) % self.size + self.position[2] |
| 36 | |
| 37 | def add_to_frame(self, frame:list, lights:list, cam) -> list: |
| 38 | |
| 39 | for particle in self.particles: |
| 40 | x = particle[0] - cam.x |
| 41 | y = particle[1] - cam.y |
| 42 | z = particle[2] - cam.z |
| 43 | x, y, z = ( |
| 44 | x * cam.rotation[0][0] + y * cam.rotation[0][1] + z * cam.rotation[0][2], |
| 45 | x * cam.rotation[1][0] + y * cam.rotation[1][1] + z * cam.rotation[1][2], |
| 46 | x * cam.rotation[2][0] + y * cam.rotation[2][1] + z * cam.rotation[2][2], |
| 47 | ) |
| 48 | if z <= cam.z_near: |
| 49 | continue |
| 50 | |
| 51 | x2d = cam.width // 2 + int(x * cam.rendering_plane_z / z) |
| 52 | y2d = cam.height // 2 - int(y * cam.rendering_plane_z / z) |
| 53 | if not (0 <= x2d < cam.width and 0 <= y2d < cam.height): |
| 54 | continue |
| 55 | |
| 56 | |
| 57 | for light in lights: |
| 58 | distance_2 = (x - light.x_in_cam) * (x - light.x_in_cam) + (y - light.y_in_cam) * (y - light.y_in_cam) + (z - light.z_in_cam) * (z - light.z_in_cam) |
| 59 | if distance_2 < 400: |
| 60 | frame[y2d][x2d] = (min(255, int(frame[y2d][x2d][0] + 50 / distance_2)), |
| 61 | min(255, int(frame[y2d][x2d][1] + 50 / distance_2)), |
| 62 | min(255, int(frame[y2d][x2d][2] + 50 / distance_2))) |
| 63 | return frame |
| 64 |
nothing calls this directly
no outgoing calls
no test coverage detected