func intersectBox(ray *infiniteRay, lenght float32, box *vec3.Box) float32 { origin := ray[0] direction := ray[1] oMin := vec3.Sub(&box.Min, &origin) oMax := vec3.Sub(&box.Max, &origin) oMin[0] /= direction[0] oMin[1] /= direction[1] oMin[2] /= direction[2] oMax[0] /= direction[0] oMax[1] /= direction[1] oMax[2] /= direction[2] mMax := vec3.Max(&oMax, &oMin) mMin := vec3.Min(&oMax, &oMin) final := math.Min(float64(mMax[0]), math.Min(float64(mMax[1]), float64(mMax[2]))) start := math.Max(math.Max(float64(mMin[0]), 0.0), math.Max(float64(mMin[1]), float64(mMin[2]))) dist := float32(math.Min(final, start)) if final > start && dist < lenght { return dist } return lenght }
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 (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) Forward() Vec3 { lookAt := vec3.T(c.LookAt()) position := vec3.T(c.Pos) return Vec3(vec3.Sub(&lookAt, &position)) }