예제 #1
0
func (rt *Raytracer) traceScanLines(job *rtJob) {
	cfg := &rt.cfg
	idx := job.idx
	img := cfg.Images[idx]
	depth := rt.depth[idx]
	size := img.Bounds().Max

	testDepth := cfg.Depth
	nodeScale := cfg.TreeScale
	nodePos := vec3.T(cfg.TreePosition)
	viewDist := cfg.ViewDist

	jitter, step := 0, 1
	if cfg.Jitter {
		jitter = 1
		step = 2
		size.X *= 2
	}

	xInc, yInc, bottomLeft := rt.calcIncVectors(job.camera, size)
	eyePoint := vec3.T(job.camera.Position())

	var (
		col  color.RGBA
		dist float32
	)

	for h := job.from; h < job.to; h++ {
		start := ((h + idx) % 2) * jitter

		for w := start; w < size.X; w += step {
			x := xInc.Scaled(float32(w))
			y := yInc.Scaled(float32(h))

			x = vec3.Add(&x, &y)
			viewPlanePoint := vec3.Add(&bottomLeft, &x)

			dir := vec3.Sub(&viewPlanePoint, &eyePoint)
			dir.Normalize()

			ray := infiniteRay{eyePoint, dir}
			dx, dy := w/step, size.Y-h

			if testDepth {
				max := (float32(depth.Gray16At(dx, dy).Y) / math.MaxUint16) * viewDist
				dist, col = rt.intersectTree(job.tree, &ray, &nodePos, nodeScale, max, job.maxDepth, 0, 0)
				d := color.Gray16{uint16(math.MaxUint16 * (dist / viewDist))}
				depth.SetGray16(dx, dy, d)
			} else {
				_, col = rt.intersectTree(job.tree, &ray, &nodePos, nodeScale, viewDist, job.maxDepth, 0, 0)
			}
			img.SetRGBA(dx, dy, col)
		}
	}
}
예제 #2
0
func (c *FreeFlightCamera) Strafe(dist float32) {
	position := vec3.T(c.Pos)
	right := vec3.T(c.Right())

	right.Scale(dist)
	c.Pos = Vec3(vec3.Add(&position, &right))
}
예제 #3
0
func (c *FreeFlightCamera) Move(dist float32) {
	position := vec3.T(c.Pos)
	forward := vec3.T(c.Forward())

	forward.Scale(dist)
	c.Pos = Vec3(vec3.Add(&position, &forward))
}
예제 #4
0
func (c *FreeFlightCamera) Lift(dist float32) {
	position := vec3.T(c.Pos)
	forward := vec3.T(c.Forward())
	right := vec3.T(c.Right())
	up := vec3.Cross(&forward, &right)

	up.Scale(dist)
	c.Pos = Vec3(vec3.Add(&position, &up))
}
예제 #5
0
func (c *FreeFlightCamera) LookAt() Vec3 {
	forward := vec3.T{0, 0, -1}
	position := vec3.T(c.Pos)

	quat := quaternion.FromEulerAngles(c.XRot, c.YRot, 0)
	quat.RotateVec3(&forward)

	return Vec3(vec3.Add(&position, &forward))
}
예제 #6
0
func (rt *Raytracer) intersectTree(tree []octreeNode, ray *infiniteRay, nodePos *vec3.T, nodeScale, length, maxDepth float32, nodeIndex, treeDepth uint32) (float32, color.RGBA) {
	var (
		color = rt.clear
		node  = tree[nodeIndex]

		// Declare this here to avoid runtime allocation.
		pos vec3.T
	)

	box := vec3.Box{*nodePos, vec3.T{nodePos[0] + nodeScale, nodePos[1] + nodeScale, nodePos[2] + nodeScale}}
	boxDist := intersectBox(ray, length, &box)

	if boxDist == length {
		return length, color
	}

	{
		d := (boxDist / rt.cfg.ViewDist)
		if treeDepth > uint32(maxDepth*(1-d*d)) {
			return boxDist, node.getColor()
		}
	}

	numChild := 0
	childScale := nodeScale * 0.5
	childDepth := treeDepth + 1

	for i := range node {
		childIndex := node.getChild(i)

		if childIndex != 0 {
			numChild++
			scaled := childPositions[i].Scaled(childScale)
			pos = vec3.Add(nodePos, &scaled)

			if ln, col := rt.intersectTree(tree, ray, &pos, childScale, length, maxDepth, childIndex, childDepth); ln < length {
				length = ln
				color = col
			}
		}
	}

	if numChild == 0 {
		return boxDist, node.getColor()
	}

	return length, color
}