作者:pombredann
项目:ran
func (t *Table) Remove(s gfx.Spatial) {
sb := s.Bounds()
// Remove minimum.
i := t.Index(sb.Min)
for ki, k := range t.Data[i] {
if k == s {
t.Data[i] = append(t.Data[i][ki:], t.Data[i][ki+1:]...)
}
}
// Remove center.
i = t.Index(sb.Center())
for ki, k := range t.Data[i] {
if k == s {
t.Data[i] = append(t.Data[i][ki:], t.Data[i][ki+1:]...)
}
}
// Remove maximum.
i = t.Index(sb.Max)
for ki, k := range t.Data[i] {
if k == s {
t.Data[i] = append(t.Data[i][ki:], t.Data[i][ki+1:]...)
}
}
return
}
作者:pombredann
项目:ran
// Remove tries to remove the given spatial from the N tree.
//
// It should be explicitly noted that it is only possible to remove a spatial
// if Bounds() returns the same identical bounds as when it was added, this is
// for efficiency reasons. Clients wishing to not have to keep track can just
// use a map of spatials to their gfx.Bounds of when they where added to the N
// tree.
//
// This method returns true if the spatial was removed or false if it could not
// be located in the tree due to:
// 1. The spatial's bounds having changed since the last time it was added.
// 2. The spatial having already been removed.
func (t *Tree) Remove(s gfx.Spatial) bool {
if t.Root == nil {
return false
}
sb := s.Bounds()
found := t.Root.find(sb)
if found == nil {
goto outside
}
for i, o := range found.Objects {
if o == s {
found.Objects = append(found.Objects[:i], found.Objects[i+1:]...)
t.count--
return true
}
}
outside:
for i, o := range t.outside {
if o == s {
t.outside = append(t.outside[:i], t.outside[i+1:]...)
t.count--
return true
}
}
return false
}
作者:pombredann
项目:ran
// findLeaf finds the leaf node containing obj.
func (t *Tree) findLeaf(n *node, obj gfx.Spatial) *node {
if n.leaf {
return n
}
// if not leaf, search all candidate subtrees
objBounds := obj.Bounds()
for _, e := range n.entries {
fmt.Printf("\nin %p\n", n, objBounds.In(e.bounds))
fmt.Println("objBounds", objBounds)
fmt.Println("e.bounds", e.bounds)
if objBounds.In(e.bounds) {
leaf := t.findLeaf(e.child, obj)
if leaf == nil {
continue
}
// check if the leaf actually contains the object
for _, leafEntry := range leaf.entries {
if leafEntry.obj == obj {
return leaf
}
}
}
}
return nil
}
作者:pombredann
项目:ran
// Add adds the spatial to the tree.
func (t *Tree) Add(s gfx.Spatial) {
t.count++
sb := s.Bounds()
if sb.Empty() {
panic("Tree.Add(): cannot add empty spatial")
}
if t.root == nil {
t.root = &Node{
parent: t.root,
bounds: sb,
Objects: []gfx.Spatial{s},
}
return
}
n := t.root.findNode(sb)
if n != nil {
n.place(sb, s)
return
}
t.root.place(sb, s)
t.root.sanitizeBounds()
return
}
作者:pombredann
项目:ran
// Insert inserts the given spatial object into the tree.
func (t *Tree) Insert(s gfx.Spatial) {
t.size++
e := entry{
bounds: s.Bounds(),
obj: s,
}
t.insert(e, 1)
}
作者:pombredann
项目:ran
// Add adds the given spatial to the N tree.
func (t *Tree) Add(s gfx.Spatial) {
t.count++
sb := s.Bounds()
if t.Root == nil {
size := sb.Size()
if size.Y > size.X {
size.X = size.X
size.Y = size.X
size.Z = size.X
}
if size.Z > size.X {
size.X = size.X
size.Y = size.X
size.Z = size.X
}
s := t.startScale
t.Root = &Node{
bounds: math.Rect3{
Min: sb.Min.MulScalar(s),
Max: sb.Min.Add(size).MulScalar(s),
},
}
}
for !sb.In(t.Root.bounds) {
rootBounds := t.Root.bounds
rootSize := rootBounds.Size()
if t.Root.Level < -t.maxExpand {
break
}
expanded := &Node{
Level: t.Root.Level - 1,
bounds: math.Rect3{
Min: rootBounds.Min.Sub(rootSize),
Max: rootBounds.Max.Add(rootSize),
},
Children: []*Node{t.Root},
}
t.Root = expanded
}
// Create a path of nodes, subdividings as needed to insert the object into
// the tree.
p := t.Root.createPath(t.divisor, t.maxDepth, sb)
if p == nil {
// Doesn't fit in the tree.
t.outside = append(t.outside, s)
return
}
p.Objects = append(p.Objects, s)
}
作者:pombredann
项目:ran
func (t *Table) Add(s gfx.Spatial) {
sb := s.Bounds()
// Add minimum.
i := t.Index(sb.Min)
t.Data[i] = append(t.Data[i], s)
// Add center.
i = t.Index(sb.Center())
t.Data[i] = append(t.Data[i], s)
// Add maximum.
i = t.Index(sb.Max)
t.Data[i] = append(t.Data[i], s)
}
作者:pombredann
项目:ran
func (o *Octant) add(b gfx.Spatial, maxDepth int) {
if o.Depth+1 <= maxDepth {
bounds := b.Bounds()
childIndex := o.childFits(bounds)
fmt.Println("\n\nChild fits")
fmt.Println("Boundable:", b)
fmt.Println("Child:", childIndex, o.childBounds(childIndex))
if childIndex != -1 {
child := &Octant{
Bounds: o.childBounds(childIndex),
Depth: o.Depth + 1,
}
o.Children[childIndex] = child
child.add(b, maxDepth)
return
}
}
o.Objects = append(o.Objects, b)
fmt.Printf("add %v %p\n", b, o)
return
}
作者:pombredann
项目:ran
func (s *Shash) Add(sp gfx.Spatial) {
// Find the distance from the center of the spatial's bounding box to the
// center of the world.
b := sp.Bounds()
dist := b.Center().Sub(math.Vec3Zero)
s.AvgLengthSq += dist.LengthSq()
s.AvgLengthSq /= 2.0
// Find the angle between the spatial's position in space relative to the
// center of the world.
angle, _ := dist.Normalized()
// Computer the start and end indices.
start := s.AngleIndex(angle)
end := s.AngleIndex(angle)
distStart := s.DistIndex(b.Min)
distEnd := s.DistIndex(b.Max)
if start > end || distStart > distEnd {
panic("ups")
}
//fmt.Println(start, end, "|", distStart, distEnd)
_ = fmt.Println
// Insert into table.
for a := start; a <= end; a *= len(s.Table) {
ak := a % len(s.Table)
for d := distStart; d <= distEnd; d *= len(s.Table) {
dk := d % len(s.Table)
s.Table[ak][dk] = append(s.Table[ak][dk], Index{
AvgLengthSq: s.AvgLengthSq,
S: sp,
})
}
}
}