shape.go 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  1. package tamias
  2. type SegmentQueryInfo struct {
  3. // shape that was hit, nil if no collision
  4. shape * Shape
  5. // Distance along query segment, will always be in the range [0, 1].
  6. t Float
  7. // normal of hit surface
  8. n Vect
  9. }
  10. // Collision type, etc
  11. type CollisionType int
  12. type GroupType int
  13. type LayerType int
  14. // Enumeration of shape types.
  15. type ShapeType int
  16. const (
  17. CIRCLE_SHAPE = ShapeType(0)
  18. SEGMENT_SHAPE = ShapeType(1)
  19. POLY_SHAPE = ShapeType(2)
  20. NUM_SHAPES = ShapeType(3)
  21. NO_GROUP = GroupType(0)
  22. )
  23. const (
  24. LAYER_0 = 1 << iota
  25. LAYER_1 = 1 << iota
  26. LAYER_2 = 1 << iota
  27. LAYER_3 = 1 << iota
  28. LAYER_4 = 1 << iota
  29. LAYER_5 = 1 << iota
  30. LAYER_6 = 1 << iota
  31. LAYER_7 = 1 << iota
  32. LAYER_8 = 1 << iota
  33. LAYER_9 = 1 << iota
  34. LAYER_10 = 1 << iota
  35. LAYER_11 = 1 << iota
  36. LAYER_12 = 1 << iota
  37. LAYER_13 = 1 << iota
  38. LAYER_14 = 1 << iota
  39. LAYER_15 = 1 << iota
  40. LAYER_16 = 1 << iota
  41. ALL_LAYERS = -1
  42. )
  43. // Shape class is probably not needed, but used for now for storng
  44. // typeinfo
  45. type ShapeClass struct {
  46. Type ShapeType
  47. }
  48. // Basic shape struct that the others inherit from.
  49. type Shape struct {
  50. // The "class" of a shape as defined above
  51. * ShapeClass
  52. // cpBody that the shape is attached to.
  53. * Body
  54. // Cached BBox for the shape.
  55. * BB
  56. // Sensors invoke callbacks, but do not generate collisions
  57. sensor bool
  58. // *** Surface properties.
  59. // Coefficient of restitution. (elasticity)
  60. e Float;
  61. // Coefficient of friction.
  62. u Float;
  63. // Surface velocity used when solving for friction.
  64. surface_v Vect;
  65. // *** User Definable Fields
  66. // User defined data pointer for the shape.
  67. data DataPointer
  68. // User defined collision type for the shape.
  69. collision_type CollisionType
  70. // User defined collision group for the shape.
  71. group GroupType
  72. // User defined layer bitmask for the shape.
  73. layers LayerType
  74. // *** Internally Used Fields
  75. // Unique id used as the hash value.
  76. hashid HashValue
  77. }
  78. // Circle shape structure.
  79. type CircleShape struct {
  80. * Shape
  81. // Center in body space coordinates
  82. c Vect
  83. // Radius.
  84. r Float
  85. // Transformed center. (world space coordinates)
  86. tc Vect;
  87. }
  88. // Segment shape structure.
  89. type SegmentShape struct {
  90. * Shape
  91. // Endpoints and normal of the segment. (body space coordinates)
  92. a, b, n Vect
  93. // Radius of the segment. (Thickness)
  94. r Float
  95. // Transformed endpoints and normal. (world space coordinates)
  96. ta, tb, tn Vect
  97. }
  98. // Returns true if a shape was hit, false if not
  99. func (info *SegmentQueryInfo) Hit() (bool) {
  100. return info.shape != nil
  101. }
  102. func (info *SegmentQueryInfo) HitPoint(start, end Vect) (Vect) {
  103. return start.Lerp(end, info.t)
  104. }
  105. func (info *SegmentQueryInfo) HitDist(start Vect, end Vect) (Float) {
  106. return start.Dist(end) * info.t
  107. }
  108. var (
  109. SHAPE_ID_COUNTER HashValue = HashValue(0)
  110. )
  111. func ResetShapeIdCounter() {
  112. SHAPE_ID_COUNTER = HashValue(0)
  113. }
  114. func (shape * Shape) Init(klass *ShapeClass, body *Body) (*Shape){
  115. shape.ShapeClass = klass
  116. shape.hashid = SHAPE_ID_COUNTER
  117. SHAPE_ID_COUNTER++
  118. shape.Body = body
  119. shape.sensor = false
  120. shape.e = Float(0.0)
  121. shape.u = Float(0.0)
  122. shape.surface_v = VZERO
  123. shape.collision_type = 0
  124. shape.group = NO_GROUP
  125. shape.layers = ALL_LAYERS
  126. shape.data = nil
  127. return shape;
  128. }
  129. func ShapeNew(klass *ShapeClass, body *Body) (*Shape) {
  130. return new(Shape).Init(klass, body)
  131. }
  132. func (shape * Shape) CacheBB(p Vect, rot Vect) (BB) {
  133. return BBMake(p.X, p.Y, p.X, p.Y)
  134. }
  135. func (shape * Shape) GetBB() (*BB) {
  136. return shape.BB
  137. }
  138. func (shape * Shape) Destroy() {
  139. }
  140. func (shape * Shape) Free() {
  141. }
  142. /* These are done differently in Go language
  143. cpBB
  144. cpShapeCacheBB(cpShape *shape)
  145. {
  146. cpBody *body = shape->body;
  147. shape->bb = shape->klass->cacheData(shape, body->p, body->rot);
  148. return shape->bb;
  149. }
  150. int
  151. cpShapePointQuery(cpShape *shape, cpVect p){
  152. return shape->klass->pointQuery(shape, p);
  153. }
  154. int
  155. cpShapeSegmentQuery(cpShape *shape, cpVect a, cpVect b, cpSegmentQueryInfo *info){
  156. cpSegmentQueryInfo blank = {NULL, 0.0f, cpvzero};
  157. (*info) = blank;
  158. shape->klass->segmentQuery(shape, a, b, info);
  159. return (info->shape != NULL);
  160. }
  161. void
  162. cpSegmentQueryInfoPrint(cpSegmentQueryInfo *info)
  163. {
  164. printf("Segment Query:\n");
  165. printf("\tt: %f\n", info->t);
  166. // printf("\tdist: %f\n", info->dist);
  167. // printf("\tpoint: %s\n", cpvstr(info->point));
  168. printf("\tn: %s\n", cpvstr(info->n));
  169. }
  170. */
  171. func CircleShapeAlloc() (* CircleShape) {
  172. return &CircleShape{};
  173. }
  174. func bbFromCircle(c Vect, r Float) (BB) {
  175. return BBMake(c.X-r, c.Y-r, c.X+r, c.Y+r);
  176. }
  177. func (circle * CircleShape) CacheBB(p Vect, rot Vect) (BB) {
  178. circle.tc = p.Add(circle.c.Rotate(rot))
  179. return bbFromCircle(circle.tc, circle.r)
  180. }
  181. func (circle * CircleShape) PointQuery(p Vect) (bool) {
  182. return circle.tc.Near(p, circle.r)
  183. }
  184. func CircleSegmentQuery(shape *Shape, center Vect, r Float, a, b Vect) (info * SegmentQueryInfo) {
  185. // umm... gross I normally frown upon such things (sic)
  186. aa := a.Sub(center);
  187. bb := b.Sub(center);
  188. qa := aa.Dot(aa) - Float(2.0)*aa.Dot(bb) + bb.Dot(bb)
  189. qb := Float(-2.0)*aa.Dot(aa) + Float(2.0)*aa.Dot(bb)
  190. qc := aa.Dot(aa) - r*r;
  191. det:= qb*qb - Float(4.0)*qa*qc
  192. info= &SegmentQueryInfo{}
  193. if det >= Float(0.0) {
  194. t := (-qb - det.Sqrt())/(Float(2.0)*qa);
  195. if Float(0.0) <= t && t <= Float(1.0) {
  196. info.shape = shape
  197. info.t = t
  198. info.n = a.Lerp(b, t).Normalize()
  199. }
  200. }
  201. return info
  202. }
  203. func (circle * CircleShape) SegmentQuery(a, b Vect) (info * SegmentQueryInfo) {
  204. return CircleSegmentQuery(circle.Shape, circle.c, circle.r, a, b)
  205. }
  206. var CircleShapeClass *ShapeClass = &ShapeClass{ CIRCLE_SHAPE }
  207. func (circle * CircleShape) Init(body * Body, radius Float, offset Vect) (* CircleShape) {
  208. circle.c = offset;
  209. circle.r = radius;
  210. circle.Shape.Init(CircleShapeClass, body);
  211. return circle;
  212. }
  213. func CircleShapeNew(body * Body, radius Float, offset Vect) (*CircleShape) {
  214. return CircleShapeAlloc().Init(body, radius, offset)
  215. }
  216. func (circle * CircleShape) Radius() (Float) {
  217. return circle.r
  218. }
  219. func (circle * CircleShape) Offset() (Vect) {
  220. return circle.c
  221. }
  222. func SegmentShapeAlloc() (*SegmentShape) {
  223. return &SegmentShape{}
  224. }
  225. func (seg * SegmentShape) CacheBB(p, rot Vect) (BB) {
  226. var l, r, s, t Float
  227. seg.ta = p.Add(seg.a.Rotate(rot));
  228. seg.tb = p.Add(seg.b.Rotate(rot));
  229. seg.tn = p.Add(seg.n.Rotate(rot));
  230. if(seg.ta.X < seg.tb.X){
  231. l = seg.ta.X
  232. r = seg.tb.X
  233. } else {
  234. l = seg.tb.X
  235. r = seg.ta.X
  236. }
  237. if(seg.ta.Y < seg.tb.Y){
  238. s = seg.ta.Y
  239. t = seg.tb.Y
  240. } else {
  241. s = seg.tb.Y
  242. t = seg.ta.Y
  243. }
  244. rad := seg.r
  245. return BBMake(l - rad, s - rad, r + rad, t + rad)
  246. }
  247. func (seg * SegmentShape) PointQuery(p Vect) (bool) {
  248. if !seg.BB.ContainsVect(p) {
  249. return false
  250. }
  251. // Calculate normal distance from segment.
  252. dn := seg.tn.Dot(p) - seg.ta.Dot(seg.tn)
  253. dist := dn.Abs() - seg.r
  254. if dist > 0.0 {
  255. return false
  256. }
  257. // Calculate tangential distance along segment.
  258. dt := - seg.tn.Cross(p)
  259. dtMin := - seg.tn.Cross(seg.ta)
  260. dtMax := - seg.tn.Cross(seg.tb)
  261. // Decision tree to decide which feature of the segment to collide with.
  262. if dt <= dtMin {
  263. if dt < (dtMin - seg.r) {
  264. return false
  265. } else {
  266. return seg.ta.Sub(p).Lengthsq() < (seg.r * seg.r)
  267. }
  268. } else {
  269. if dt < dtMax {
  270. return true;
  271. } else {
  272. if dt < (dtMax + seg.r) {
  273. return seg.tb.Sub(p).Lengthsq() < (seg.r * seg.r)
  274. } else {
  275. return false
  276. }
  277. }
  278. }
  279. return true
  280. }
  281. func (seg * SegmentShape) SegmentQuery(center Vect, a, b Vect) (info * SegmentQueryInfo) {
  282. n := seg.tn;
  283. // flip n if a is behind the axis
  284. if a.Dot(n) < seg.ta.Dot(n) {
  285. n = n.Neg()
  286. }
  287. info = &SegmentQueryInfo{}
  288. an := a.Dot(n)
  289. bn := b.Dot(n)
  290. d := seg.ta.Dot(n) + seg.r
  291. t := (d - an)/(bn - an)
  292. if Float(0.0) < t && t < Float(1.0) {
  293. point := a.Lerp(b,t)
  294. dt := - seg.tn.Cross(point)
  295. dtMin := - seg.tn.Cross(seg.ta)
  296. dtMax := - seg.tn.Cross(seg.tb)
  297. if(dtMin < dt && dt < dtMax){
  298. info.shape = seg.Shape
  299. info.t = t;
  300. info.n = n;
  301. return info; // don't continue on and check endcaps
  302. }
  303. }
  304. if seg.r > 0.0 {
  305. info1 := CircleSegmentQuery(seg.Shape, seg.ta, seg.r, a, b)
  306. info2 := CircleSegmentQuery(seg.Shape, seg.tb, seg.r, a, b)
  307. if info1.Hit() && !info2.Hit() {
  308. info = info1
  309. } else if info2.Hit() && !info1.Hit() {
  310. info = info2
  311. } else if info1.Hit() && info2.Hit() {
  312. if info1.t < info2.t {
  313. info = info1;
  314. } else {
  315. info = info2;
  316. }
  317. }
  318. }
  319. // return empty info
  320. return info
  321. }
  322. var SegmentShapeClass * ShapeClass = &ShapeClass {SEGMENT_SHAPE}
  323. func (seg *SegmentShape) Init(body * Body, a, b Vect, r Float) (*SegmentShape) {
  324. seg.a = a
  325. seg.b = b
  326. seg.n = b.Sub(a).Normalize().Perp()
  327. seg.r = r;
  328. seg.Shape.Init(SegmentShapeClass, body)
  329. return seg;
  330. }
  331. func SegmentShapeNew(body * Body, a, b Vect, r Float) (*SegmentShape) {
  332. return SegmentShapeAlloc().Init(body, a, b, r)
  333. }
  334. func (seg * SegmentShape) A() (Vect) {
  335. return seg.a
  336. }
  337. func (seg * SegmentShape) B() (Vect) {
  338. return seg.b
  339. }
  340. func (seg * SegmentShape) Normal() (Vect) {
  341. return seg.n
  342. }
  343. func (seg * SegmentShape) Radius() (Float) {
  344. return seg.r
  345. }
  346. // Unsafe API
  347. func (circle * CircleShape) SetRadius(r Float) (Float) {
  348. circle.r = r
  349. return circle.r
  350. }
  351. func (circle * CircleShape) SetOffset(o Vect) (Vect) {
  352. circle.c = o
  353. return circle.c
  354. }
  355. func (seg * SegmentShape) Setendpoints(a, b Vect) {
  356. seg.a = a
  357. seg.b = b
  358. seg.n = b.Sub(a).Normalize().Perp()
  359. }
  360. func (seg * SegmentShape) SetRadius(r Float) (Float) {
  361. seg.r = r
  362. return seg.r
  363. }