func (b *body) setMaterial(mass, bounciness float64) *body { b.imass = 0 // static unless there is mass. if !lin.AeqZ(mass) { b.imass = 1.0 / mass // only need inverse mass b.iit = b.shape.Inertia(mass, b.iit) // shape inertia if lin.AeqZ(b.iit.X) { // inverse shape inertia b.iit.X = 0 } else { b.iit.X = 1.0 / b.iit.X } if lin.AeqZ(b.iit.Y) { b.iit.Y = 0 } else { b.iit.Y = 1.0 / b.iit.Y } if lin.AeqZ(b.iit.Z) { b.iit.Z = 0 } else { b.iit.Z = 1.0 / b.iit.Z } } b.restitution = bounciness b.movable = b.imass != 0 return b }
// castRayPlane calculates the point of collision between ray:a and // plane:b. The contact point is returned if there is an intersection. func castRayPlane(a, b Body) (hit bool, x, y, z float64) { sa, sb := a.Shape().(*ray), b.Shape().(*plane) la, lb := a.World().Loc, b.World().Loc rdir := b.(*body).v0.SetS(sa.dx, sa.dy, sa.dz).Unit() // ray direction. nrm := a.(*body).v0.SetS(sb.nx, sb.ny, sb.nz).Unit() // plane normal. nrm.MultQ(nrm, b.World().Rot) // apply world spin to plane normal. denom := rdir.Dot(nrm) if lin.AeqZ(denom) || denom < 0 { return false, 0, 0, 0 // plane is behind ray or ray is parallel to plane. } // calculate the difference from a point on the plane to the ray origin. dx, dy, dz := rdir.X, rdir.Y, rdir.Z diff := b.(*body).v0.SetS(lb.X-la.X, lb.Y-la.Y, lb.Z-la.Z) dlen := diff.Dot(nrm) / denom if dlen < 0 { return false, 0, 0, 0 } // Get contact point by scaling the ray direction with the contact distance // and adding the ray origin. x, y, z = dx*dlen+la.X, dy*dlen+la.Y, dz*dlen+la.Z return true, x, y, z }