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
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
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