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