def render():
    print "Ray Tracing Started"
    HRES = IMAGE_SIZE[0]
    VRES = IMAGE_SIZE[1]
    
    aspect_ratio = float(HRES) / VRES

    #Camera parameters to be abstracted away later
    fovy = 45.0 * (pi / 180.0)
    #UNIT_Y is up
    eye = Vector3(0, 0, 0)
    look_at = Vector3(0, 0, -10)
    d = 1 / tan(fovy/2)
    #End camera parameters
    
    #Calculate orthonormal basis
    l = look_at - eye
    l.normalise()
    
    v = cross_product(l, UNIT_Y)
    v.normalise()
    
    #Note that u is a unit vector!
    u = cross_product(v, l)
    #Note: v is right and u is up on the image plane
    
    #Find the lower left corner
    #look_at is the center of the image plane...
    ll = eye +  l * d - v * aspect_ratio   - u
    #End calculations
        
    rays = []
    v_step = 2.0 / VRES
    h_step = 2.0 * aspect_ratio / HRES
    height = IMAGE_SIZE[1]
    width = IMAGE_SIZE[0]
    image_buf = []
    for x in xrange(width):
        if x == (width * 0.25): 
            print "25% complete..."
          
        if x == (width * 0.5): 
            print "50% complete..." 
        
        if x == (width * 0.75): 
            print "75% complete..."

        if x == (width - 1): 
            print "100% complete..."
           
        for y in xrange(height):
            p = ll + v * h_step * float(x)  + u * v_step * float(y)
            d = p - eye
            d.normalise()
            primary_ray = Ray(eye, d)
            color = ray_trace(primary_ray)
            image_buf.append(clamp(color))
    return image_buf
Ejemplo n.º 2
0
    def update(self, delta_time):
        """Animates the missile."""
        # Moves missile based on its direction (the forward vector)
        velocity = self.forward() * self.missile_speed
        self.position += velocity * delta_time

        # Rotate missile towards the player - Figure out where it is pointing and
        # where do we want to point it
        current_dir = self.forward()
        desired_dir = (Vector3(0, 0, 0) - self.position).normalized()
        # Find the angle between these two directions
        dp = max(-1, min(1, dot_product(current_dir, desired_dir)))
        angle = math.acos(dp)

        # If the angle is larger than the ammount we can rotate a single frame,
        # given by the time elapsed and the missile rotation speed, we need to
        # clamp the value of the angle
        if abs(angle) > self.missile_rotation_speed * delta_time:
            angle = self.missile_rotation_speed * delta_time * math.copysign(
                1, angle)

        # Figure out the rotation axis to point the missile towards the desired direction
        axis = cross_product(current_dir, desired_dir)
        axis.normalize()

        if (angle > 0.01):
            # Rotate the missile towards the player
            q = Quaternion.AngleAxis(axis, angle)
            self.rotation = q * self.rotation
def generate_rays():
    HRES = IMAGE_SIZE[0]
    VRES = IMAGE_SIZE[1]
    
    aspect_ratio = float(HRES) / VRES

    #Camera parameters to be abstracted away later
    fovy = 45.0 * (pi / 180.0)
    #UNIT_Y is up
    eye = Vector3(0, 0, 0)
    look_at = Vector3(0, 0, -10)
    d = 1 / tan(fovy/2)
    #End camera parameters
    
    #Calculate orthonormal basis
    l = look_at - eye
    l.normalise()
    
    v = cross_product(l, UNIT_Y)
    v.normalise()
    
    #Note that u is a unit vector!
    u = cross_product(v, l)
    #Note: v is right and u is up on the image plane
    
    #Find the lower left corner
    #look_at is the center of the image plane...
    ll = eye +  l * d - v * aspect_ratio   - u
    #End calculations
        
    rays = []
    v_step = 2.0 / VRES
    h_step = 2.0 * aspect_ratio / HRES
    for x in xrange(HRES):
        for y in xrange(VRES):
            p = ll + v * h_step * float(x)  + u * v_step * float(y)
            d = p - eye
            d.normalise()
            ray = Ray(eye, d)
            rays.append(ray)
    return rays
Ejemplo n.º 4
0
def create_terrain():
    """Creates a terrain, composed of different meshes (one per each type of material)
    It support snow, water, grassland and cliffsize, based on hard-coded parameters"""

    # Size of the terrain
    size_x = 4
    size_z = 4
    # Number of divisions of the terrain. Vertex count scales with the square of this
    div = 40
    # Paramters for water and snow height/depth
    water_depth = -0.1
    snow_height = 0.15

    px = size_x / div
    pz = size_z / div

    # For centering the terrain on the object center
    origin = Vector3(-size_x * 0.5, 0, -size_z * 0.5)

    # Create the meshes for each type of terrain
    grass_mesh = Mesh("Terrain_Grass")
    snow_mesh = Mesh("Terrain_Snow")
    cliff_mesh = Mesh("Terrain_Cliff")
    water_mesh = Mesh("Terrain_Water")

    for dz in range(0, div):
        for dx in range(0, div):
            p1 = Vector3(dx * px, 0, dz * pz) + origin
            p2 = Vector3((dx + 1) * px, 0, dz * pz) + origin
            p3 = Vector3((dx + 1) * px, 0, (dz + 1) * pz) + origin
            p4 = Vector3(dx * px, 0, (dz + 1) * pz) + origin

            p1.y = sample_height(p1.x, p1.z)
            p2.y = sample_height(p2.x, p2.z)
            p3.y = sample_height(p3.x, p3.z)
            p4.y = sample_height(p4.x, p4.z)

            # Check if any of the points is underwater
            water = clamp_to_water(p1, water_depth)
            water |= clamp_to_water(p2, water_depth)
            water |= clamp_to_water(p3, water_depth)
            water |= clamp_to_water(p4, water_depth)

            # Create the polygons
            poly = []
            poly.append(p1)
            poly.append(p2)
            poly.append(p3)
            poly.append(p4)

            if water:
                # Polygon was under water, add it to that mesh
                water_mesh.polygons.append(poly)
            else:
                # Check for snow height
                avg_y = (p1.y + p2.y + p3.y + p4.y) * 0.25
                if avg_y > snow_height:
                    # The polygon was above a certain point
                    snow_mesh.polygons.append(poly)
                else:
                    # Check for cliff face, check the normal
                    normal = cross_product((p3 - p1).normalized(),
                                           (p2 - p1).normalized())
                    if dot_product(normal, Vector3(0, 1, 0)) < 0.5:
                        cliff_mesh.polygons.append(poly)
                    else:
                        grass_mesh.polygons.append(poly)

    # Create materials for the terrain
    grass_material = Material(Color(0.1, 0.6, 0.1, 1), "GrassMaterial")
    snow_material = Material(Color(0.8, 0.8, 0.8, 1), "SnowMaterial")
    cliff_material = Material(Color(0.4, 0.4, 0.4, 1), "CliffMaterial")
    water_material = Material(Color(0, 0.5, 0.7, 1), "WaterMaterial")

    # Return meshes and materials
    meshes = [grass_mesh, snow_mesh, cliff_mesh, water_mesh]
    materials = [grass_material, snow_material, cliff_material, water_material]

    return meshes, materials