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 (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) 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) calcIncVectors(camera Camera, size image.Point) (vec3.T, vec3.T, vec3.T) { width := float32(size.X) height := float32(size.Y) lookAtPoint := vec3.T(camera.LookAt()) eyePoint := vec3.T(camera.Position()) up := vec3.T(camera.Up()) viewDirection := vec3.Sub(&lookAtPoint, &eyePoint) u := vec3.Cross(&viewDirection, &up) v := vec3.Cross(&u, &viewDirection) u.Normalize() v.Normalize() viewPlaneHalfWidth := float32(math.Tan(float64(rt.cfg.FieldOfView / 2))) aspectRatio := height / width viewPlaneHalfHeight := aspectRatio * viewPlaneHalfWidth sV := v.Scaled(viewPlaneHalfHeight) sU := u.Scaled(viewPlaneHalfWidth) lookV := vec3.Sub(&lookAtPoint, &sV) viewPlaneBottomLeftPoint := vec3.Sub(&lookV, &sU) xIncVector := u.Scaled(2 * viewPlaneHalfWidth) yIncVector := v.Scaled(2 * viewPlaneHalfHeight) xIncVector[0] /= width xIncVector[1] /= width xIncVector[2] /= width yIncVector[0] /= height yIncVector[1] /= height yIncVector[2] /= height return xIncVector, yIncVector, viewPlaneBottomLeftPoint }
func (c *FreeFlightCamera) Right() Vec3 { up := vec3.T(c.Up()) forward := vec3.T(c.Forward()) return Vec3(vec3.Cross(&up, &forward)) }
func (c *FreeFlightCamera) Forward() Vec3 { lookAt := vec3.T(c.LookAt()) position := vec3.T(c.Pos) return Vec3(vec3.Sub(&lookAt, &position)) }