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