Example #1
0
def generate_v(
    origin: Vec3,
    normal: Vec3,
    valid_side: float,
    start_db: float,
    dist_from_origin: float,
    ray_num,
) -> list:
    """
    Generates rays in a hemisphere to represent reflected rays 
    """
    rnd = random.random() * ray_num

    points = []
    offset = 2.0 / ray_num
    increment = math.pi * (3.0 - math.sqrt(5.0))

    for i in range(ray_num):
        y = ((i * offset) - 1) + (offset / 2)
        r = math.sqrt(1 - pow(y, 2))

        phi = ((i + rnd) % ray_num) * increment

        x = math.cos(phi) * r
        z = math.sin(phi) * r

        vec = Vec3(x, y, z).normalize()
        if np.sign(normal.dot(vec)) != np.sign(valid_side):
            # Ensure that the rays are inside the object
            vec = -vec
        points.append(Ray(origin, vec, dist_from_origin, start_db))
    return points
Example #2
0
 def calc_normal(self):
     """
     Calculate the face normal using the vertices
     """
     normal = np.cross(
         self.vertices[1].vec - self.vertices[0].vec,
         self.vertices[2].vec - self.vertices[0].vec,
     )
     return Vec3(*normal).normalize()
Example #3
0
def calc_center(vertices, faces):
    """
    Calculates center of the object denoted by the given vertices
    and faces using triangulation
    """
    centers = []
    for face in faces:
        centers.append(
            triangle_center(face.vertices[0], face.vertices[1], face.vertices[2])
        )
    return Vec3(*np.mean(centers, axis=0))
Example #4
0
    def is_inside(self, point: Vec3, v0: Vec3, v1: Vec3, v2: Vec3,
                  normal: Vec3) -> bool:
        """
        Determines if the point is inside the given triangle bounds and on the same plane
        """
        edge0 = v1.sub(v0)
        edge1 = v2.sub(v1)
        edge2 = v0.sub(v2)
        C0 = point.sub(v0)
        C1 = point.sub(v1)
        C2 = point.sub(v2)

        if (normal.dot(edge0.cross(C0)) >= 0
                and normal.dot(edge1.cross(C1)) >= 0
                and normal.dot(edge2.cross(C2)) >= 0
                and C0.dot(C1.cross(C2)) == 0.0):
            return True
        return False
Example #5
0
    def load_model(self, filename):
        """
        Loads the specified file and generates the corresponding model.
        """
        self.filename = filename
        self.obj_file = ObjLoader(filename)
        self.object_vertices = self.obj_file.vertices
        self.object_faces = self.obj_file.faces

        # Calculate object geometric properties
        self.object_volume = volume(self.object_vertices, self.object_faces)
        self.object_surface_area = surface_area(self.object_faces)
        self.object_center = calc_center(self.object_vertices,
                                         self.object_faces)

        self.x_pos = -self.object_center.x
        self.y_pos = -self.object_center.y
        self.zoom = -self.object_center.z * 10
        self.sound_source = Vec3(*self.object_center)
        self.object = self.obj_file.render()
        self.update()
Example #6
0
    def __init__(self, parent=None, filename=""):
        super().__init__(parent)

        self.filename = filename
        self.object = None
        self.object_volume = 0
        self.object_surface_area = 0
        self.object_center = Vec3(0, 0, 0)
        self.raytracer = 0
        self.rays = None
        self.x_rot = 0
        self.y_rot = 0
        self.z_rot = 0
        self.x_pos = 0
        self.y_pos = 0
        self.zoom = -5.0
        self.sound_source = None

        self.last_pos = QPoint()

        self.color_black = QColor.fromRgb(0, 0, 0)
        self.color_white = QColor.fromRgb(255, 255, 255)
Example #7
0
    def generate_rays(self) -> list:
        """
        Generates an array of rays to use for the raytracing
        """
        rnd = random.random() * self.ray_num

        points = []
        offset = 2.0 / self.ray_num
        increment = math.pi * (3.0 - math.sqrt(5.0))

        for i in range(self.ray_num):
            y = ((i * offset) - 1) + (offset / 2)
            r = math.sqrt(1 - pow(y, 2))

            phi = ((i + rnd) % self.ray_num) * increment

            x = math.cos(phi) * r
            z = math.sin(phi) * r

            points.append(
                Ray(self.origin,
                    Vec3(x, y, z).normalize(), 1, self.start_db))
        return points
Example #8
0
def signed_volume_triangle(v1: Vec3, v2: Vec3, v3: Vec3):
    """
    Calculates the signed volume of a triangle through its relation
    to the origin as a tetrahedron
    """
    return v1.dot(v2.cross(v3)) / 6.0
Example #9
0
 def calc_reflection(self, phit, normal, dist_from_origin, db) -> "Ray":
     """
     Calculates the reflected Ray based on incidence and normal
     """
     ray = Vec3(*(-(normal * (self.direction.dot(normal) * 2)).sub(self.direction)))
     return Ray(phit, ray, dist_from_origin, db)
Example #10
0
from geometry.vec3 import Vec3

if __name__ == '__main__':
    v = Vec3(1, 0, 0)
    w = Vec3(0, 1, 0)
    print(Vec3.cross(v, w))
Example #11
0
    def intersect(self, ray: Ray, rNum=0) -> bool:
        """
        Determines the intersection point of the given ray for the current model
        """
        EPSILON = sys.float_info.epsilon
        for face in self.faces:
            # Origin in plane
            if self.is_inside(ray.origin, *face.vertices, face.normal):
                continue

            # Check if ray is parallel to plane
            pvec = ray.direction.cross(face.edge2)
            det = face.edge1.dot(pvec)
            if det > -EPSILON and det < EPSILON:
                continue

            inv_det = 1.0 / det
            tvec = ray.origin.sub(face.vertices[0])
            u = tvec.dot(pvec) * inv_det
            if u < 0.0 or u > 1.0:
                continue

            qvec = tvec.cross(face.edge1)
            v = ray.direction.dot(qvec) * inv_det
            if v < 0.0 or u + v > 1.0:
                continue

            # Distance from ray origin
            t = face.edge2.dot(qvec) * inv_det
            # Ray moves away from the plane
            if t < EPSILON:
                continue

            # Intersection point
            phit_long = ray.origin.add(Vec3(*(ray.direction * t)))
            phit = Vec3(*np.around(phit_long.vec, decimals=2))

            # Calcualate the dB level at the intersection
            new_dist_from_origin = ray.dist_from_origin + ray.origin.distance(
                phit)
            db_change = drop_off(ray.dist_from_origin, new_dist_from_origin)
            point_db = ray.start_db - db_change

            # Log Point
            curr_point_db = self.point_dict.get((phit.x, phit.y, phit.z))
            if curr_point_db is not None:
                self.point_dict[(phit.x, phit.y, phit.z)] = sum_levels(
                    [point_db, curr_point_db])
            else:
                self.point_dict[(phit.x, phit.y, phit.z)] = point_db

            if rNum > 0:
                # Calculate the reflected rays
                reflected_db = point_db * (
                    1 - mtl.absorption(face.material, self.freq))
                reflections = generate_brdf(ray, phit, reflected_db,
                                            new_dist_from_origin, face)

                for ray in reflections:
                    if ray.start_db > 0:
                        self.intersect(ray, rNum - 1)

            return True
        return False
Example #12
0
 def set_sound_source(self, x, y, z):
     """
     Sets the visual position of the sound source.
     """
     self.sound_source = Vec3(x, y, z)
     self.update()
Example #13
0
    def __init__(self, fileName):
        self.vertices = np.empty((0), dtype=Vec3)
        self.normals = np.empty((0), dtype=Vec3)
        self.faces = np.empty((0), dtype=Face)

        # Parse file and construct list of vertices, faces, and face normals
        try:
            file = open(fileName)
            for line in file:
                if line.startswith("v "):
                    line = line.strip().split()
                    vertex = Vec3(line[1], line[2], line[3])

                    self.vertices = np.append(self.vertices, vertex)

                elif line.startswith("vn"):
                    line = line.strip().split()
                    normal = Vec3(line[1], line[2], line[3])

                    self.normals = np.append(self.normals, normal)

                elif line.startswith("f"):
                    if "/" in line:
                        line = line.strip().split()
                        faceData = [
                            line[1].split("/"),
                            line[2].split("/"),
                            line[3].split("/"),
                        ]
                        vertRef = [
                            int(faceData[0][0]),
                            int(faceData[1][0]),
                            int(faceData[2][0]),
                        ]
                        vertices = np.array(
                            [
                                self.vertices[vertRef[0] - 1],
                                self.vertices[vertRef[1] - 1],
                                self.vertices[vertRef[2] - 1],
                            ]
                        )
                        # Calculate face normal using vertex normals
                        faceNorm = None
                        if len(self.normals) > 0:
                            faceNorm = (
                                np.sum(
                                    np.array(
                                        [
                                            self.normals[int(faceData[0][2]) - 1].vec,
                                            self.normals[int(faceData[1][2]) - 1].vec,
                                            self.normals[int(faceData[2][2]) - 1].vec,
                                        ],
                                        dtype=float,
                                    ),
                                    axis=0,
                                )
                                / 3
                            )
                            faceNorm = Vec3(*(-faceNorm))
                    else:
                        line = line.strip().split()
                        vertices = (int(line[1]), int(line[2]), int(line[3]))
                        faceNorm = Vec3(0, 0, 0)

                    self.faces = np.append(self.faces, Face(vertices, faceNorm))

            file.close()
        except IOError:
            print(".obj file not found.")