github.com/df-mc/dragonfly@v0.9.13/server/block/cube/trace/block.go (about) 1 package trace 2 3 import ( 4 "github.com/df-mc/dragonfly/server/block/cube" 5 "github.com/df-mc/dragonfly/server/world" 6 "github.com/go-gl/mathgl/mgl64" 7 "math" 8 ) 9 10 // BlockResult is the result of a ray trace collision with a block's model. 11 type BlockResult struct { 12 bb cube.BBox 13 pos mgl64.Vec3 14 face cube.Face 15 16 blockPos cube.Pos 17 } 18 19 // BBox returns the BBox that was collided within the block's model. 20 func (r BlockResult) BBox() cube.BBox { 21 return r.bb 22 } 23 24 // Position ... 25 func (r BlockResult) Position() mgl64.Vec3 { 26 return r.pos 27 } 28 29 // Face returns the hit block face. 30 func (r BlockResult) Face() cube.Face { 31 return r.face 32 } 33 34 // BlockPosition returns the block that was collided with. 35 func (r BlockResult) BlockPosition() cube.Pos { 36 return r.blockPos 37 } 38 39 // BlockIntercept performs a ray trace and calculates the point on the block model's edge nearest to the start position 40 // that the ray collided with. 41 // BlockIntercept returns a BlockResult with the block collided with and with the colliding vector closest to the start position, 42 // if no colliding point was found, a zero BlockResult is returned and ok is false. 43 func BlockIntercept(pos cube.Pos, w *world.World, b world.Block, start, end mgl64.Vec3) (result BlockResult, ok bool) { 44 bbs := b.Model().BBox(pos, w) 45 if len(bbs) == 0 { 46 return 47 } 48 49 var ( 50 hit Result 51 dist = math.MaxFloat64 52 ) 53 54 for _, bb := range bbs { 55 next, ok := BBoxIntercept(bb.Translate(pos.Vec3()), start, end) 56 if !ok { 57 continue 58 } 59 60 nextDist := next.Position().Sub(start).LenSqr() 61 if nextDist < dist { 62 hit = next 63 dist = nextDist 64 } 65 } 66 67 if hit == nil { 68 return result, false 69 } 70 71 return BlockResult{bb: hit.BBox(), pos: hit.Position(), face: hit.Face(), blockPos: pos}, true 72 }