Exemple #1
0
func (p Sphere) Intersect(ray, origin glm.Vec3) (b bool, raylen float64, normal glm.Vec3) {
	normal = glm.Vec3{}
	line := *p.Pos.Subtract(&origin)
	// Solve using cosine law for scalar coefficient of ray.
	raylens := quadraticRoots(ray.Dot(&ray), 2*line.Dot(&ray), line.Dot(&line)-p.Rad*p.Rad)
	switch len(raylens) {
	case 0:
		return false, 0, normal
	case 1:
		return ray_epsilon_check(-raylens[0], ray, line)
	case 2:
		if raylens[0] > raylens[1] { // NOTE: negative inversion
			tmp := raylens[0]
			raylens[0] = raylens[1]
			raylens[1] = tmp
		}
		if b, raylen, normal = ray_epsilon_check(-raylens[1], ray, line); b {
			return b, raylen, normal
		} else {
			return ray_epsilon_check(-raylens[0], ray, line)
		}
	}
	return false, 0, normal
}
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
}
Exemple #3
0
func same_side(a, b, c, test glm.Vec3) bool {
	t := b.Subtract(&a)
	return t.Cross(test.Subtract(&a)).Dot(t.Cross(c.Subtract(&a))) > Epsilon
}
Exemple #4
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
}