Exemple #1
0
func trace(root []scene.Primitive, ambient glm.Vec3, ray, origin *glm.Vec3, lights []scene.Light, depth int) (*glm.Vec3, bool) {
	if hit, node, raylen, normal := intersectNodes(root, ray, origin); hit {
		// ambient silhouette
		mat := root[node].GetMaterial()
		colour := glm.NewVec3(ambient.Elem[0]*mat.Ambient.Elem[0], ambient.Elem[1]*mat.Ambient.Elem[1], ambient.Elem[2]*mat.Ambient.Elem[2])
		// setup for casting secondary (shadow) rays.
		intersection := origin.Add(ray.Scale(raylen))
		diffuse := glm.Vec3{}
		specular := glm.Vec3{}
		ray.Normalize()
		normal.Normalize()

		// cast shadow ray.
		for _, light := range lights {
			shadow_ray := light.Pos.Subtract(intersection)
			if hit, _, _, _ = intersectNodes(root, shadow_ray, intersection); !hit {
				shadow_ray.Normalize()
				// add diffuse/specular components.
				diffuse_coef := normal.Dot(shadow_ray)
				if diffuse_coef > 0.00001 {
					fmt.Println(diffuse_coef)
					diffuse_tmp := mat.Diffuse.Scale(diffuse_coef)
					diffuse.Iadd(glm.NewVec3(diffuse_tmp.Elem[0]*light.Colour.Elem[0], diffuse_tmp.Elem[1]*light.Colour.Elem[1], diffuse_tmp.Elem[2]*light.Colour.Elem[2]))
				}
				reflected_shadow_ray := shadow_ray.Subtract(normal.Scale(2 * diffuse_coef))
				specular_coef := math.Abs(math.Pow(reflected_shadow_ray.Dot(ray), mat.Shininess))
				if specular_coef > 0.00001 {
					specular_tmp := mat.Specular.Scale(specular_coef)
					specular.Iadd(glm.NewVec3(specular_tmp.Elem[0]*light.Colour.Elem[0], specular_tmp.Elem[1]*light.Colour.Elem[1], specular_tmp.Elem[2]*light.Colour.Elem[2]))
				}
			}
		}
		colour.Iadd(&diffuse).Iadd(&specular)
		// cast reflectance ray.
		if REFLECTIONS {
			reflected := ray.Subtract(normal.Scale(2 * normal.Dot(ray)))
			if depth < MAX_DEPTH {
				if reflected_color, hit := trace(root, ambient, reflected, intersection, lights, depth+1); hit {
					colour.Iscale(1 - mat.Mirror).Iadd(reflected_color.Scale(mat.Mirror))
				}
			}
		}
		return colour, true
	}
	return &glm.Vec3{}, false
}
Exemple #2
0
func (p Mesh) Intersect(ray, origin glm.Vec3) (b bool, raylen float64, normal glm.Vec3) {
	// If we're debugging just draw the bounding box.
	if ONLY_DRAW_BOUNDS {
		return p.Bound.Intersect(ray, origin)
	}
	// Check bounding box.
	if b, _, _ := p.Bound.Intersect(ray, origin); !b {
		return false, 0, glm.Vec3{}
	}
	// Go through faces and do face intersections.
	raylen = 10000000.0
	for i, f := range p.Faces {
		ray_proj := p.Normals[i].Dot(&ray) // Intersect the ray with the plane.
		if math.Abs(ray_proj) > Epsilon {
			new_raylen := p.Verts[f[0]].Subtract(&origin).Dot(&p.Normals[i]) / ray_proj
			// check that the ray origin is not coincident with the plane
			if new_raylen > Epsilon {
				// project face to 2D
				maj_axis := major_axis(p.Normals[i])
				verts2d := project_2dface(f, p.Verts, maj_axis)
				test_pt := drop_axis(*origin.Add(ray.Scale(new_raylen)), maj_axis)
				// clip the ray to the bounds of the 2D face.
				if same_side(verts2d[0], verts2d[1], verts2d[2], test_pt) &&
					same_side(verts2d[1], verts2d[2], verts2d[0], test_pt) &&
					same_side(verts2d[2], verts2d[0], verts2d[1], test_pt) {
					b = true
					if new_raylen < raylen {
						raylen = new_raylen
						normal = p.Normals[i]
					}
				}
			}
		}
	}
	return
}