コード例 #1
0
ファイル: scene.go プロジェクト: ssalbiz/gray
func (p Box) Intersect(ray, origin glm.Vec3) (b bool, raylen float64, normal glm.Vec3) {
	min := p.Pos
	max := p.Pos.Add(glm.NewVec3(p.Rad, p.Rad, p.Rad))
	raylen_near := -100000.0
	raylen_far := 100000.0
	// Assume parallel intersections are not a thing.
	for i, raydir := range ray.Elem {
		if math.Abs(raydir) < Epsilon && (origin.Elem[i] < min.Elem[i] || origin.Elem[i] > max.Elem[i]) {
			return false, 0, glm.Vec3{}
		}
		t1 := (min.Elem[i] - origin.Elem[i]) / raydir
		t2 := (max.Elem[i] - origin.Elem[i]) / raydir
		flip := false
		if t1 > t2 {
			t := t1
			t1 = t2
			t2 = t
			flip = true
		}
		if t1 > raylen_near {
			raylen_near = t1
			normal = *glm.NewVec3(0.0, 0.0, 0.0)
			if flip {
				normal.Elem[i] = p.Rad
			} else {
				normal.Elem[i] = -p.Rad
			}
		}
		raylen_far = math.Min(raylen_far, t2)
		if raylen_far < raylen_near || raylen_far < Epsilon {
			return false, 0, normal
		}
	}
	return true, raylen_near, normal
}
コード例 #2
0
ファイル: scene.go プロジェクト: ssalbiz/gray
func NewMesh(verts [][3]float64, faces [][3]int, mat Material) *Mesh {
	vec_verts := make([]glm.Vec3, len(verts))
	m := &Mesh{}
	min := [3]float64{verts[0][0], verts[0][1], verts[0][2]}
	max := [3]float64{verts[0][0], verts[0][1], verts[0][2]}

	for i, v := range verts {
		for j := 0; j < 3; j++ {
			min[j] = math.Min(min[j], v[j])
			max[j] = math.Max(max[j], v[j])
		}
		vec_verts[i] = *glm.NewVec3(v[0], v[1], v[2])
	}
	m.Verts = vec_verts
	m.Faces = faces
	// Generate plane normals for all faces.
	m.Normals = make([]glm.Vec3, len(faces))
	for i, f := range faces {
		v1 := vec_verts[f[0]].Subtract(&vec_verts[f[1]])
		v2 := vec_verts[f[0]].Subtract(&vec_verts[f[2]])
		m.Normals[i] = *v1.Cross(v2)
	}
	m.Bound.Pos = *glm.NewVec3(min[0], min[1], min[2])
	diff := glm.NewVec3(max[0], max[1], max[2]).Subtract(&m.Bound.Pos)
	m.Bound.Rad = math.Max(math.Max(diff.Elem[0], diff.Elem[1]), diff.Elem[2])
	m.Bound.Mat = mat
	m.Mat = mat
	return m
}
コード例 #3
0
ファイル: scene.go プロジェクト: ssalbiz/gray
func drop_axis(v glm.Vec3, axis int) (ret glm.Vec3) {
	switch axis {
	case 0:
		ret = *glm.NewVec3(v.Elem[1], v.Elem[2], 0.0)
	case 1:
		ret = *glm.NewVec3(v.Elem[0], v.Elem[2], 0.0)
	case 2:
		ret = *glm.NewVec3(v.Elem[0], v.Elem[1], 0.0)
	}
	return
}
コード例 #4
0
ファイル: gray.go プロジェクト: ssalbiz/gray
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
}
コード例 #5
0
ファイル: scene.go プロジェクト: ssalbiz/gray
func CreateScene() (scene *Scene, err error) {
	scene = &Scene{}
	scene.Lights = []Light{
		Light{*glm.NewVec3(-100.0, 150.0, 400.0), *glm.NewVec3(0.7, 0.7, 0.7), *glm.NewVec3(1.0, 0.0, 0.0)},
		Light{*glm.NewVec3(400.0, 100.0, 150.0), *glm.NewVec3(0.7, 0.0, 0.7), *glm.NewVec3(1.0, 0.0, 0.0)},
	}
	mat1 := Material{
		*glm.NewVec3(0.7, 1.0, 0.7), *glm.NewVec3(0.7, 1.0, 0.7), *glm.NewVec3(0.5, 0.7, 0.5), 25.0, 0.3,
	}
	mat2 := Material{
		*glm.NewVec3(0.5, 0.5, 0.5), *glm.NewVec3(0.5, 0.5, 0.5), *glm.NewVec3(0.5, 0.7, 0.5), 25.0, 0.3,
	}
	mat3 := Material{
		*glm.NewVec3(1.0, 0.6, 0.1), *glm.NewVec3(1.0, 0.6, 0.1), *glm.NewVec3(0.5, 0.7, 0.5), 25.0, 0.3,
	}
	mat4 := Material{
		*glm.NewVec3(0.7, 0.6, 1.0), *glm.NewVec3(0.7, 0.6, 1.0), *glm.NewVec3(0.5, 0.4, 0.8), 25.0, 0.3,
	}

	scene.Primitives = make([]Primitive, 7)
	scene.Primitives[0] = Sphere{*glm.NewVec3(0.0, 0.0, -400.0), 100.0, mat1}
	scene.Primitives[1] = Sphere{*glm.NewVec3(200.0, 50.0, -100.0), 150.0, mat1}
	scene.Primitives[2] = Sphere{*glm.NewVec3(0.0, -1200.0, -500.0), 1000.0, mat2}
	scene.Primitives[3] = Sphere{*glm.NewVec3(-100.0, 25.0, -300.0), 50.0, mat3}
	scene.Primitives[4] = Sphere{*glm.NewVec3(0.0, 100.0, -250.0), 25.0, mat1}
	scene.Primitives[5] = Box{*glm.NewVec3(-200.0, -125.0, 0.0), 100, mat4}
	steldodec.Mat = mat3
	scene.Primitives[6] = *steldodec

	scene.Eye = *glm.NewVec3(0.0, 0.0, 800.0)
	scene.View = *glm.NewVec3(0.0, 0.0, -1.0)
	scene.Up = *glm.NewVec3(0.0, 1.0, 0.0)
	scene.Ambient = *glm.NewVec3(0.3, 0.3, 0.3)
	scene.FOV = 50
	scene.Width = 512
	scene.Height = 512
	fmt.Println("Here we go!")
	return scene, nil
}
コード例 #6
0
ファイル: scene.go プロジェクト: ssalbiz/gray
func ray_epsilon_check(raylen float64, ray glm.Vec3, line glm.Vec3) (b bool, retlen float64, normal glm.Vec3) {
	if raylen > Epsilon {
		return true, raylen, *ray.Scale(raylen).Subtract(&line)
	}
	return false, 0, *glm.NewVec3(0, 0, 0)
}
コード例 #7
0
ファイル: gray.go プロジェクト: ssalbiz/gray
func background() *glm.Vec3 {
	return glm.NewVec3(0.1, 0.1, 0.1)
}