Beispiel #1
0
 def __init__(self, points):
     self.n = points[1].minus(points[0]).normalized().cross_product(
         points[2].minus(points[0]).normalized()).normalized()
     self.p0 = points[0]
     self.boundary_points = points
     self.albedo = (0, 255, 0)
     self.transform = Transform()
Beispiel #2
0
    def __init__(self, radius):
        self.radius = radius

        self.albedo = Color(1.0, 0.0, 0.0, 1.0)

        self.transform = Transform()

        self.material = None
Beispiel #3
0
    def __init__(self):
        self.mode = Camera.PERSPECTIVE
        self.fov = 60

        self.near = 0.01
        self.far = 1000

        self.transform = Transform()
Beispiel #4
0
class Plane:
    def __init__(self, points):
        self.n = points[1].minus(points[0]).normalized().cross_product(
            points[2].minus(points[0]).normalized()).normalized()
        self.p0 = points[0]
        self.boundary_points = points
        self.albedo = (0, 255, 0)
        self.transform = Transform()

    def pre_render(self):
        points = []

        for p in self.boundary_points:
            points.append(self.transform.apply_transform(p))

        self.n = points[1].minus(points[0]).normalized().cross_product(
            points[2].minus(points[0]).normalized()).normalized()
        self.p0 = points[0]

        self.points = points

    def intercepts(self, ray):

        points = self.points

        # https://www.scratchapixel.com/lessons/3d-basic-rendering/minimal-ray-tracer-rendering-simple-shapes/ray-plane-and-ray-disk-intersection
        denom = self.n.dot_product(ray.direction)
        # print(str(denom))
        if np.abs(denom) > 1e-6:
            if denom < 0:
                self.n.multiply(-1, False)
            p0l0 = self.p0.minus(ray.origin)
            t = p0l0.dot_product(self.n)

            if t >= 0:
                intersection_point = ray.origin.add(ray.direction.multiply(t))

                a = points[0].minus(intersection_point).normalized()
                b = points[1].minus(intersection_point).normalized()

                N = a.cross_product(b).normalized()

                for i in range(1, len(points)):
                    p = points[i]
                    if intersection_point.equals(p):
                        return (True, intersection_point)
                    a = points[i].minus(intersection_point).normalized()
                    b = points[(i + 1) % len(points)].minus(
                        intersection_point).normalized()
                    Nt = a.cross_product(b).normalized()
                    if N.dot_product(Nt) < 0:
                        return (False, Vector3.zero())
                    # print('Passed on ' + str(i))

                return (True, intersection_point)

        return (False, Vector3.zero())
Beispiel #5
0
    def __init__(self):
        self.name = ""
        self.is_active = True
        self.children = {}
        self.behaviours = {}

        #all game objects should have a transform
        #used the GameObject's own add_behaviour
        #functionality, to ensure consistency
        self.add_behaviour(Transform())
Beispiel #6
0
    def __init__(self, v1, v2, v3):

        ref_pos1 = v1.multiply(-0.5).add(v2.multiply(-0.5)).add(
            v3.multiply(-0.5))
        ref_pos2 = v1.multiply(0.5).add(v2.multiply(0.5)).add(v3.multiply(0.5))

        v1p = v1.multiply(-1)
        v2p = v2.multiply(-1)
        v3p = v3.multiply(-1)

        self.albedo = (255, 0, 0)

        self.transform = Transform()
        self.planes = [
            Plane([
                ref_pos1,
                ref_pos1.add(v1),
                ref_pos1.add(v1.add(v2)),
                ref_pos1.add(v2)
            ]),
            Plane([
                ref_pos1,
                ref_pos1.add(v1),
                ref_pos1.add(v1.add(v3)),
                ref_pos1.add(v3)
            ]),
            Plane([
                ref_pos1,
                ref_pos1.add(v2),
                ref_pos1.add(v2.add(v3)),
                ref_pos1.add(v2)
            ]),
            Plane([
                ref_pos2,
                ref_pos2.add(v1p),
                ref_pos2.add(v1p.add(v2p)),
                ref_pos2.add(v2p)
            ]),
            Plane([
                ref_pos2,
                ref_pos2.add(v1p),
                ref_pos2.add(v1p.add(v3p)),
                ref_pos2.add(v3p)
            ]),
            Plane([
                ref_pos2,
                ref_pos2.add(v3p),
                ref_pos2.add(v3p.add(v2p)),
                ref_pos2.add(v2p)
            ]),
        ]

        for p in self.planes:
            p.albedo = (random.randint(20, 255), random.randint(20, 255),
                        random.randint(20, 255))
Beispiel #7
0
    def __init__(self, name_="", layer=-1):
        self.name = name_
        self._id = GameObject.id_tracker
        GameObject.id_tracker += 1

        self._layer = layer
        self._parent = None

        self.is_started = False
        self.is_active = True

        self._behaviours = {}
        self._children = {}

        self.transform = Transform()
    def __init__(self):
        #Each game object should have a unique name
        self.name = ""
        self.parent = None
        self.is_active = True

        #Following other engines' architectures, Game
        #Objects are basically containers for behaviours
        #and other Game Objects.
        self.behaviours = {}
        self.children = {}

        #all game objects should have a transform
        #used the GameObject's own add_behaviour
        #functionality, to ensure consistency
        self.add_behaviour(Transform())
 def get_transform(self):
     """ Returns the Transform object that execute this object's translate, rotate and scale (very usefull to apply to polygons like hit boxes)"""
     (x, y) = self.__position.x, self.__position.y
     (sx, sy) = self.__scale.x, self.__scale.y
     (mx, my) = self.__origin.x, self.__origin.y
     if self.__tr_need_up:  #If it doesn't need to be updated it means it has already been computed -> if a fondamental attribute changes it needs to be recomputed
         angle = -self.__rotation
         cosine = np.cos(angle)
         sine = np.sin(angle)
         sxc = sx * cosine
         syc = sy * cosine  #Trigo formulas
         sxs = sx * sine
         sys = sy * sine
         tx = -mx * sxc - my * sys + x
         ty = mx * sxs - my * syc + y
         self.__transform = Transform(
             np.array([[sxc, sys, tx], [-sxs, syc, ty], [0, 0, 1]]))
         self.__tr_need_up = False
     # Error : returned None at 'get_transform' because the transform_matrix
     # was None and __tr_need_up == False
     assert self.__transform is not None
     return self.__transform
Beispiel #10
0
class Sphere:
    def __init__(self, radius):
        self.radius = radius

        self.albedo = Color(1.0, 0.0, 0.0, 1.0)

        self.transform = Transform()

        self.material = None

    def pre_render(self):
        pass

    def set_material(self, material):
        self.material = material

    def render(self, scene, interception):
        if self.material != None:
            return self.material.render(scene, interception)

        light = scene.get_light()

        if light is None:
            return self.albedo
        else:
            render_color = self.albedo.clone()

            light_direction = light.transform.position.minus(
                interception['hit_point']).normalized()
            dotNL = light_direction.dot_product(interception['normal'])
            # print("Dot light and normal: " + str(dotNL))
            rgb_value = render_color.rgb().multiply(max(0.0, dotNL))
            rgb_value = rgb_value.multiply(light.intensity)
            render_color.set_rgb(rgb_value)

            return render_color

        return self.albedo

    def intercepts(self, ray):
        # geometric solution
        # https://www.scratchapixel.com/lessons/3d-basic-rendering/minimal-ray-tracer-rendering-simple-shapes/ray-sphere-intersection

        # print('Sphere intercepts ray ' + str(ray))

        radius2 = self.radius * self.radius

        L = self.transform.position.minus(ray.origin)
        tca = L.dot_product(ray.direction)

        d2 = L.dot_product(L) - tca * tca
        if d2 > radius2:
            return {
                'result': False,
                'hit_point': Vector3.zero,
                'normal': None,
                'uv': Vector2.zero
            }
        thc = np.sqrt(radius2 - d2)
        t0 = tca - thc
        t1 = tca + thc

        if t0 > t1:
            tmp = t1
            t1 = t0
            t0 = tmp

        if t0 < 0:
            t0 = t1  # if t0 is negative, let's use t1 instead
            if t0 < 0:
                return {
                    'result': False,
                    'hit_point': Vector3.zero,
                    'normal': None,
                    'uv': Vector2.zero
                }  # both t0 and t1 are negative
        t = t0

        hit_point = ray.origin.add(ray.direction.multiply(t))
        normal = hit_point.minus(self.transform.position).normalized()

        v = normal

        v = self.transform.apply_transform_to_direction(v)

        longlat = Vector2(np.arctan2(v.x, v.z) + np.pi, np.arccos(-v.y))
        uv = Vector2(longlat.x / (2 * np.pi), longlat.y / np.pi)
        # uv.y = 1f - uv.y;
        # uv.x = 1f - uv.x;

        return {
            'result': True,
            'hit_point': hit_point,
            'normal': normal,
            'uv': uv
        }
Beispiel #11
0
 def __init__(self, color, intensity=1.0):
     self.color = color
     self.intensity = intensity
     self.transform = Transform()
Beispiel #12
0
 def __init__(self, size):
     self.size = size
     self.transform = Transform()
     self.color = Color.random()
Beispiel #13
0
 def rotate(self, angle):
     """ Rotates this polygon (side effect) """
     t = Transform()
     t.rotate(angle)
     p = self.apply_transform(t)
     self.__init__(p.get_points())