func random() (r gfx.Bounds) { f := func() float64 { return (rand.Float64() * 2.0) - 1.0 } size := .013123 posScale := .5123213 r.Min = math.Vec3{ f() * size, f() * size, f() * size, } r.Max = r.Min.Add(math.Vec3{ rand.Float64() * size, rand.Float64() * size, rand.Float64() * size, }) // Random position pos := math.Vec3{f(), f(), f()} pos = pos.MulScalar(posScale) r.Max = r.Max.Add(pos) r.Min = r.Min.Add(pos) return r }
// Takes a child node position and returns it's bounds. func (n *Node) childBounds(pos, divisor math.Vec3) math.Rect3 { size := n.childSize(divisor) cb := math.Rect3{ Min: pos, Max: pos.Add(size), } if !n.bounds.Contains(cb.Min) || !n.bounds.Contains(cb.Max) { fmt.Println(pos) fmt.Println(n.bounds) fmt.Println(n.bounds.Contains(cb.Min)) fmt.Println(n.bounds.Contains(cb.Max)) panic("not contained") } if !cb.In(n.bounds) { //fmt.Println("pos ", pos) //fmt.Println("size ", size) //fmt.Println("child ", cb) //fmt.Println("parent", n.bounds) //panic("") } return math.Rect3{ Min: pos, Max: pos.Add(size), } }
// Takes a child node position and returns it's bounds. func (n *Node) childBounds(pos, divisor math.Vec3) math.Rect3 { size := n.childSize(divisor) return math.Rect3{ Min: pos, Max: pos.Add(size), } }
func randomAABB(size, posScale float64) (r gfx.AABB) { f := func() float64 { return (rand.Float64() * 2.0) - 1.0 } max := f() * size min := f() * size r.Max = math.Vec3{max, max, max} r.Min = math.Vec3{ max - min, max - min, max - min, } // Center center := r.Center() r.Min = r.Min.Sub(center) r.Max = r.Max.Sub(center) // Random position pos := math.Vec3{f(), f(), f()} pos = pos.MulScalar(posScale) r.Max = r.Max.Add(pos) r.Min = r.Min.Add(pos) return r }
// Index returns the data index for the given point in space. func (t *Table) Index(p gmath.Vec3) int { p.X *= primeX p.Y *= primeY p.Z *= primeZ x := int(math.Abs(p.X)) % t.Size y := int(math.Abs(p.Y)) % t.Size z := int(math.Abs(p.Z)) % t.Size return x + t.Size*(y+t.Size*z) }
func sortEntries(p gmath.Vec3, entries []entry) ([]entry, []float64) { sorted := make([]entry, len(entries)) dists := make([]float64, len(entries)) for i := 0; i < len(entries); i++ { sorted[i] = entries[i] bounds := entries[i].bounds dists[i] = p.Sub(bounds.Min).LengthSq() } sort.Sort(entrySlice{sorted, dists, p}) return sorted, dists }
func random() gfx.Spatial { o := math.Vec3{ rand.Float64() * float64(rand.Int()), rand.Float64() * float64(rand.Int()), rand.Float64() * float64(rand.Int()), } min := math.Vec3{rand.Float64(), rand.Float64(), rand.Float64()} max := min.Add(math.Vec3{rand.Float64(), rand.Float64(), rand.Float64()}) min = min.Add(o) max = max.Add(o) return gfx.Bounds{min, max} }
func (t *Tree) nearestNeighbors(k int, p gmath.Vec3, n *node, dists []float64, nearest []gfx.Spatial) ([]gfx.Spatial, []float64) { if n.leaf { for _, e := range n.entries { dist := p.Sub(e.bounds.Min).Length() dists, nearest = insertNearest(k, dists, nearest, dist, e.obj) } } else { branches, branchDists := sortEntries(p, n.entries) branches = pruneEntries(p, branches, branchDists) for _, e := range branches { nearest, dists = t.nearestNeighbors(k, p, e.child, dists, nearest) } } return nearest, dists }
func pruneEntries(p gmath.Vec3, entries []entry, minDists []float64) []entry { minMinMaxDist := math.MaxFloat64 for i := range entries { minMaxDist := p.Sub(entries[i].bounds.Max).LengthSq() if minMaxDist < minMinMaxDist { minMinMaxDist = minMaxDist } } // remove all entries with minDist > minMinMaxDist pruned := []entry{} for i := range entries { if minDists[i] <= minMinMaxDist { pruned = append(pruned, entries[i]) } } return pruned }
func (t *Tree) nearestNeighbor(p gmath.Vec3, n *node, d float64, nearest gfx.Spatial) (gfx.Spatial, float64) { if n.leaf { for _, e := range n.entries { dist := p.Sub(e.bounds.Min).Length() if dist < d { d = dist nearest = e.obj } } } else { branches, dists := sortEntries(p, n.entries) branches = pruneEntries(p, branches, dists) for _, e := range branches { subNearest, dist := t.nearestNeighbor(p, e.child, d, nearest) if dist < d { d = dist nearest = subNearest } } } return nearest, d }
func LineVerts(start, end math.Vec3, width float64, result []gfx.Vec3) []gfx.Vec3 { hw := math.Vec3Zero.AddScalar(width).DivScalar(2.0) start = start.Sub(hw) end = end.Add(hw) return CubeVerts(start, end, result) }
// Closest returns the closest point on the plane p nearest to the point q. // // Implemented as described in: // Real-Time Collision Detection, 5.1.1 "Closest Point on Plane to Point". func (p Plane3) Closest(q math.Vec3) math.Vec3 { t := p.Normal.Dot(q) - p.Pos return q.Sub(t).Mul(p.Normal) }
// Dist calculates the signed distance of q to the plane p. // // Implemented as described in: // Real-Time Collision Detection, 5.1.1 "Closest Point on Plane to Point". func (p Plane3) Dist(q math.Vec3) float64 { return q.Dot(p.Normal) - p.Pos }
// gfxLoop is responsible for drawing things to the window. This loop must be // independent of the Chippy main loop. func gfxLoop(w *chippy.Window, r gfx.Renderer) { // Load the Ice file. scene, err := ice.LoadFile(os.Args[1]) if err != nil { log.Fatal(err) } // Setup a camera to use a perspective projection. camera := gfx.NewCamera() camFOV := 75.0 camNear := 0.1 camFar := 100.0 camera.SetPersp(r.Bounds(), camFOV, camNear, camFar) // Move the camera -2 on the Y axis (back two units away from the triangle // object). //camera.SetPos(math.Vec3{0, -50, 10}) //camera.SetPos(math.Vec3{0, -5, 2}) camera.SetPos(math.Vec3{0, -7, 3}) // Create a simple shader. shader := gfx.NewShader("SimpleShader") shader.GLSLVert = glslVert shader.GLSLFrag = glslFrag // Preload the shader (useful for seeing shader errors, if any). onLoad := make(chan *gfx.Shader, 1) r.LoadShader(shader, onLoad) go func() { <-onLoad shader.RLock() if !shader.Loaded { log.Println(string(shader.Error)) } shader.RUnlock() }() // Assign the shader to each object in the scene. for _, o := range scene.Objects { o.Shader = shader o.State.FaceCulling = gfx.NoFaceCulling //var verts = make([]gfx.Vec3, 0, len(o.Meshes[0].Indices)) //for _, v := range o.Meshes[0].Indices { // verts = append(verts, o.Meshes[0].Vertices[v]) //} //o.Meshes[0].Vertices = verts //o.Meshes[0].Indices = nil //if len(o.Meshes[0].Indices) > 5 { // log.Println(name, len(o.Meshes[0].Indices)) // bad := o.Meshes[0].Indices[743] // log.Println(o.Meshes[0].Vertices[bad]) // o.Meshes[0].Indices = o.Meshes[0].Indices[744-3:744] //} } // Start a goroutine to handle window events and move the camera around. go func() { event := w.Events() for { select { case e := <-event: switch ev := e.(type) { case keyboard.TypedEvent: if ev.Rune == 'm' { // Toggle MSAA now. msaa := !r.MSAA() r.SetMSAA(msaa) log.Println("MSAA Enabled?", msaa) } case mouse.Event: if ev.Button == mouse.Left && ev.State == mouse.Down { w.SetCursorGrabbed(!w.CursorGrabbed()) } } } } }() event := w.Events() for { camEvents: for { select { case e := <-event: switch ev := e.(type) { case chippy.ResizedEvent: // Update the camera's projection matrix for the new width and // height. camera.Lock() camera.SetPersp(r.Bounds(), camFOV, camNear, camFar) camera.Unlock() case chippy.CursorPositionEvent: if w.CursorGrabbed() { dt := r.Clock().Dt() camera.Lock() camRot := camera.Rot() camRot.Z -= 4 * ev.X * dt camRot.X -= 4 * ev.Y * dt camera.SetRot(camRot) camera.Unlock() } } default: break camEvents } } // Move the camera now. if w.CursorGrabbed() { dt := r.Clock().Dt() var local, parent math.Vec3 speed := 16.0 if w.Keyboard.Down(keyboard.A) { local.X -= speed * dt } if w.Keyboard.Down(keyboard.D) { local.X += speed * dt } if w.Keyboard.Down(keyboard.W) { local.Y += speed * dt } if w.Keyboard.Down(keyboard.S) { local.Y -= speed * dt } if w.Keyboard.Down(keyboard.LeftCtrl) { parent.Z -= speed * dt } if w.Keyboard.Down(keyboard.LeftShift) { parent.Z += speed * dt } camera.Lock() worldSpace := camera.ConvertPos(local, gfx.LocalToWorld) parentSpace := camera.ConvertPos(worldSpace, gfx.WorldToParent) camera.SetPos(parentSpace.Add(parent)) camera.Unlock() } // Clear the entire area (empty rectangle means "the whole area"). r.Clear(image.Rect(0, 0, 0, 0), gfx.Color{1, 1, 1, 1}) r.ClearDepth(image.Rect(0, 0, 0, 0), 1.0) // Draw each model in the scene. for _, o := range scene.Objects { r.Draw(image.Rect(0, 0, 0, 0), o, camera) } // Render the whole frame. r.Render() } }