Example #1
0
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
}
Example #2
0
// 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),
	}
}
Example #3
0
// 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),
	}
}
Example #4
0
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
}
Example #5
0
// 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)
}
Example #6
0
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
}
Example #7
0
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}
}
Example #8
0
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
}
Example #9
0
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
}
Example #10
0
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
}
Example #11
0
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)
}
Example #12
0
// 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)
}
Example #13
0
// 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
}
Example #14
0
// 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()
	}
}