func circle2circleQuery(p1, p2 vect.Vect, r1, r2 vect.Float, con *Contact) int { minDist := r1 + r2 delta := vect.Sub(p2, p1) distSqr := delta.LengthSqr() if distSqr >= minDist*minDist { return 0 } dist := vect.Float(math.Sqrt(float64(distSqr))) pDist := dist if dist == 0.0 { pDist = vect.Float(math.Inf(1)) } pos := vect.Add(p1, vect.Mult(delta, 0.5+(r1-0.5*minDist)/pDist)) norm := vect.Vect{1, 0} if dist != 0.0 { norm = vect.Mult(delta, 1.0/dist) } con.reset(pos, norm, dist-minDist, 0) return 1 }
func (this *Segment) GetStartingPositions(pieces int) []vect.Vect { xDif := (this.Point2.X - this.Point1.X) / vect.Float(pieces+1) yDif := (this.Point2.Y - this.Point1.Y) / vect.Float(pieces+1) places := make([]vect.Vect, pieces) for x := 0; x < pieces; x++ { places[x].X = this.Point1.X + (xDif * vect.Float(x+1)) places[x].Y = this.Point1.Y + (yDif * vect.Float(x+1)) } return places }
func (this *Race) StartRace() { this.Started = true startPoints := this.Track.Goal.GetStartingPositions(len(this.Racers)) for x, racer := range this.Racers { racer.player.Ship.Body.SetPosition(startPoints[x]) racer.Position = startPoints[x] racer.player.Ship.Body.SetAngle(vect.Float(this.Track.StartingAngle * 2 * math.Pi)) racer.Angle = vect.Float(this.Track.StartingAngle * 2 * math.Pi) this.Space.AddBody(racer.player.Ship.Body) } }
func addBall() { x := rand.Intn(1135) + 115 //ball := chipmunk.NewCircle(vect.Vector_Zero, vect.Float(ballRadius)) ball := chipmunk.NewBox(vect.Vector_Zero, 50, 50) ball.SetElasticity(0.9) body := chipmunk.NewBody(vect.Float(10000000), ball.Moment(vect.Float(100000000))) body.SetPosition(vect.Vect{vect.Float(x), 100.0}) body.SetAngle(vect.Float(rand.Float64() * 2 * math.Pi)) // t := 2 // if(rand.Intn(2) == 1){ // t *= -1 // } // body.AddTorque(vect.Float(t)) body.AddShape(ball) space.AddBody(body) balls = append(balls, &Ship{x, ball}) }
// Creates a new CircleShape with the given center and radius. func NewCircle(pos vect.Vect, radius vect.Float) *Shape { shape := newShape() circle := &CircleShape{ Position: pos, Radius: vect.Float(radius), Shape: shape, } shape.ShapeClass = circle return shape }
func k_tensor(a, b *Body, r1, r2 vect.Vect, k1, k2 *vect.Vect) { // calculate mass matrix // If I wasn't lazy and wrote a proper matrix class, this wouldn't be so gross... m_sum := a.m_inv + b.m_inv // start with I*m_sum k11 := vect.Float(m_sum) k12 := vect.Float(0) k21 := vect.Float(0) k22 := vect.Float(m_sum) // add the influence from r1 a_i_inv := a.i_inv r1xsq := r1.X * r1.X * a_i_inv r1ysq := r1.Y * r1.Y * a_i_inv r1nxy := -r1.X * r1.Y * a_i_inv k11 += r1ysq k12 += r1nxy k21 += r1nxy k22 += r1xsq // add the influnce from r2 b_i_inv := b.i_inv r2xsq := r2.X * r2.X * b_i_inv r2ysq := r2.Y * r2.Y * b_i_inv r2nxy := -r2.X * r2.Y * b_i_inv k11 += r2ysq k12 += r2nxy k21 += r2nxy k22 += r2xsq // invert determinant := (k11 * k22) - (k12 * k21) if determinant == 0 { panic("Unsolvable constraint.") } det_inv := 1.0 / determinant *k1 = vect.Vect{k22 * det_inv, -k12 * det_inv} *k2 = vect.Vect{-k21 * det_inv, k11 * det_inv} }
// step advances the physics engine and cleans up any balls that are off-screen func step(dt float32) { space.Step(vect.Float(dt)) for i := 0; i < len(balls); i++ { p := balls[i].Shape.Body.Position() if p.Y > 1500 { space.RemoveBody(balls[i].Shape.Body) balls = append(balls[:i], balls[i+1:]...) i-- // consider same index again } } }
func (poly *PolygonShape) Moment(mass vect.Float) vect.Float { sum1 := vect.Float(0) sum2 := vect.Float(0) println("using bad Moment calculation") offset := vect.Vect{0, 0} for i := 0; i < poly.NumVerts; i++ { v1 := vect.Add(poly.Verts[i], offset) v2 := vect.Add(poly.Verts[(i+1)%poly.NumVerts], offset) a := vect.Cross(v2, v1) b := vect.Dot(v1, v1) + vect.Dot(v1, v2) + vect.Dot(v2, v2) sum1 += a * b sum2 += a } return (vect.Float(mass) * sum1) / (6.0 * sum2) }
// Calculates the transformed vertices and axes and the bounding box. func (poly *PolygonShape) update(xf transform.Transform) AABB { //transform axes { src := poly.Axes dst := poly.TAxes for i := 0; i < poly.NumVerts; i++ { n := xf.RotateVect(src[i].N) dst[i].N = n dst[i].D = vect.Dot(xf.Position, n) + src[i].D } /* fmt.Println("") fmt.Println("Started Axes") fmt.Println(xf.Rotation, xf.Position) for i:=0;i<poly.NumVerts;i++ { fmt.Println(src[i], dst[i]) } */ } //transform verts { inf := vect.Float(math.Inf(1)) aabb := AABB{ Lower: vect.Vect{inf, inf}, Upper: vect.Vect{-inf, -inf}, } src := poly.Verts dst := poly.TVerts for i := 0; i < poly.NumVerts; i++ { v := xf.TransformVect(src[i]) dst[i] = v aabb.Lower.X = vect.FMin(aabb.Lower.X, v.X) aabb.Upper.X = vect.FMax(aabb.Upper.X, v.X) aabb.Lower.Y = vect.FMin(aabb.Lower.Y, v.Y) aabb.Upper.Y = vect.FMax(aabb.Upper.Y, v.Y) } /* fmt.Println("Verts") for i:=0;i<poly.NumVerts;i++ { fmt.Println(src[i], dst[i]) } */ return aabb } }
func NewSpace() (space *Space) { space = &Space{} space.Iterations = 20 space.Gravity = vect.Vector_Zero space.damping = 0.8 space.collisionSlop = 0.5 space.collisionBias = vect.Float(math.Pow(1.0-0.1, 60)) space.collisionPersistence = 3 space.Constraints = make([]Constraint, 0) space.Bodies = make([]*Body, 0) space.deleteBodies = make([]*Body, 0) space.sleepingComponents = make([]*Body, 0) space.staticShapes = NewBBTree(nil) space.activeShapes = NewBBTree(space.staticShapes) space.cachedArbiters = make(map[HashPair]*Arbiter) space.Arbiters = make([]*Arbiter, 0) space.ArbiterBuffer = make([]*Arbiter, ArbiterBufferSize) for i := 0; i < len(space.ArbiterBuffer); i++ { space.ArbiterBuffer[i] = newArbiter() } space.ContactBuffer = make([][]*Contact, ContactBufferSize) for i := 0; i < len(space.ContactBuffer); i++ { var contacts []*Contact = make([]*Contact, MaxPoints) for i := 0; i < MaxPoints; i++ { contacts[i] = &Contact{} } space.ContactBuffer[i] = contacts } /* for i := 0; i < 8; i++ { go space.MultiThreadTest() } */ return }
func (tree *BBTree) GetBB(obj Indexable) AABB { v, ok := obj.Velocity() if ok { bb := obj.AABB() coef := vect.Float(0.1) l := bb.Lower.X b := bb.Lower.Y r := bb.Upper.X t := bb.Upper.Y x := (r - l) * coef y := (t - b) * coef v = vect.Mult(v, 0.1) return NewAABB(l+vect.FMin(-x, v.X), b+vect.FMin(-y, v.Y), r+vect.FMax(x, v.X), t+vect.FMax(y, v.Y)) } return obj.AABB() }
func bias_coef(errorBias, dt vect.Float) vect.Float { return vect.Float(1.0 - math.Pow(float64(errorBias), float64(dt))) }
func (body *Body) Moment() vect.Float { return vect.Float(body.i) }
func (box *BoxShape) Moment(mass vect.Float) vect.Float { return (vect.Float(mass) * (box.Width*box.Width + box.Height*box.Height) / 12.0) }
func (body *Body) Rot() (rx, ry vect.Float) { return vect.Float(body.rot.X), vect.Float(body.rot.Y) }
func (body *Body) SetAngularVelocity(w vect.Float) { body.w = vect.Float(w) }
func (body *Body) SetForce(x, y vect.Float) { body.f.X = vect.Float(x) body.f.Y = vect.Float(y) }
func (space *Space) ProcessComponents(dt vect.Float) { sleep := math.IsInf(float64(space.sleepTimeThreshold), 0) bodies := space.Bodies _ = bodies if sleep { dv := space.idleSpeedThreshold dvsq := vect.Float(0) if dv == 0 { dvsq = dv * dv } else { dvsq = space.Gravity.LengthSqr() * dt * dt } for _, body := range space.Bodies { keThreshold := vect.Float(0) if dvsq != 0 { keThreshold = body.m * dvsq } body.node.IdleTime = 0 if body.KineticEnergy() <= keThreshold { body.node.IdleTime += dt } } } for _, arb := range space.Arbiters { a, b := arb.BodyA, arb.BodyB _, _ = a, b if sleep { } } /* // Awaken any sleeping bodies found and then push arbiters to the bodies' lists. cpArray *arbiters = space->arbiters; for(int i=0, count=arbiters->num; i<count; i++){ cpArbiter *arb = (cpArbiter*)arbiters->arr[i]; cpBody *a = arb->body_a, *b = arb->body_b; if(sleep){ if((cpBodyIsRogue(b) && !cpBodyIsStatic(b)) || cpBodyIsSleeping(a)) cpBodyActivate(a); if((cpBodyIsRogue(a) && !cpBodyIsStatic(a)) || cpBodyIsSleeping(b)) cpBodyActivate(b); } cpBodyPushArbiter(a, arb); cpBodyPushArbiter(b, arb); } if(sleep){ // Bodies should be held active if connected by a joint to a non-static rouge body. cpArray *constraints = space->constraints; for(int i=0; i<constraints->num; i++){ cpConstraint *constraint = (cpConstraint *)constraints->arr[i]; cpBody *a = constraint->a, *b = constraint->b; if(cpBodyIsRogue(b) && !cpBodyIsStatic(b)) cpBodyActivate(a); if(cpBodyIsRogue(a) && !cpBodyIsStatic(a)) cpBodyActivate(b); } // Generate components and deactivate sleeping ones for(int i=0; i<bodies->num;){ cpBody *body = (cpBody*)bodies->arr[i]; if(ComponentRoot(body) == NULL){ // Body not in a component yet. Perform a DFS to flood fill mark // the component in the contact graph using this body as the root. FloodFillComponent(body, body); // Check if the component should be put to sleep. if(!ComponentActive(body, space->sleepTimeThreshold)){ cpArrayPush(space->sleepingComponents, body); CP_BODY_FOREACH_COMPONENT(body, other) cpSpaceDeactivateBody(space, other); // cpSpaceDeactivateBody() removed the current body from the list. // Skip incrementing the index counter. continue; } } i++; // Only sleeping bodies retain their component node pointers. body->node.root = NULL; body->node.next = NULL; } } */ }
func (body *Body) AngularVelocity() vect.Float { return vect.Float(body.w) }
func (body *Body) SetWBias(w vect.Float) { body.w_bias = vect.Float(w) }
func (body *Body) WBias() vect.Float { return vect.Float(body.w_bias) }
func (body *Body) AddAngle(angle vect.Float) { body.SetAngle(vect.Float(angle) + body.Angle()) }
func (body *Body) AddTorque(t vect.Float) { body.t += vect.Float(t) }
func (body *Body) SetVelocity(x, y vect.Float) { body.v.X = vect.Float(x) body.v.Y = vect.Float(y) }
func (body *Body) AddVelocity(x, y vect.Float) { body.v.X += vect.Float(x) body.v.Y += vect.Float(y) }
func (body *Body) SetTorque(t vect.Float) { body.t = vect.Float(t) }
func (space *Space) Step(dt vect.Float) { // don't step if the timestep is 0! if dt == 0 { return } stepStart := time.Now() bodies := space.Bodies for _, arb := range space.Arbiters { arb.state = arbiterStateNormal } space.Arbiters = space.Arbiters[0:0] prev_dt := space.curr_dt space.curr_dt = dt space.stamp++ for _, body := range bodies { if body.Enabled { body.UpdatePosition(dt) } } for _, body := range bodies { if body.Enabled { body.UpdateShapes() } } start := time.Now() space.activeShapes.ReindexQuery(func(a, b Indexable) { SpaceCollideShapes(a.Shape(), b.Shape(), space) }) space.ReindexQueryTime = time.Since(start) //axc := space.activeShapes.SpatialIndexClass.(*BBTree) //PrintTree(axc.root) for h, arb := range space.cachedArbiters { ticks := space.stamp - arb.stamp deleted := (arb.BodyA.deleted || arb.BodyB.deleted) disabled := !(arb.BodyA.Enabled || arb.BodyB.Enabled) if (ticks >= 1 && arb.state != arbiterStateCached) || deleted || disabled { arb.state = arbiterStateCached if arb.BodyA.CallbackHandler != nil { arb.BodyA.CallbackHandler.CollisionExit(arb) } if arb.BodyB.CallbackHandler != nil { arb.BodyB.CallbackHandler.CollisionExit(arb) } } if ticks > time.Duration(space.collisionPersistence) || deleted { delete(space.cachedArbiters, h) space.ArbiterBuffer = append(space.ArbiterBuffer, arb) c := arb.Contacts if c != nil { space.ContactBuffer = append(space.ContactBuffer, c) } } } slop := space.collisionSlop biasCoef := vect.Float(1.0 - math.Pow(float64(space.collisionBias), float64(dt))) invdt := vect.Float(1 / dt) for _, arb := range space.Arbiters { arb.preStep(invdt, slop, biasCoef) } for _, con := range space.Constraints { con.PreSolve() con.PreStep(dt) } damping := vect.Float(math.Pow(float64(space.damping), float64(dt))) for _, body := range bodies { if body.Enabled { if body.IgnoreGravity { body.UpdateVelocity(vect.Vector_Zero, damping, dt) continue } body.UpdateVelocity(space.Gravity, damping, dt) } } dt_coef := vect.Float(0) if prev_dt != 0 { dt_coef = dt / prev_dt } for _, arb := range space.Arbiters { arb.applyCachedImpulse(dt_coef) } for _, con := range space.Constraints { con.ApplyCachedImpulse(dt_coef) } //fmt.Println("STEP") start = time.Now() //fmt.Println("Arbiters", len(space.Arbiters), biasCoef, dt) //spew.Config.MaxDepth = 3 //spew.Config.Indent = "\t" for i := 0; i < space.Iterations; i++ { for _, arb := range space.Arbiters { arb.applyImpulse() //spew.Dump(arb) //spew.Printf("%+v\n", arb) } for _, con := range space.Constraints { con.ApplyImpulse() } } //fmt.Println("####") //fmt.Println("") //MultiThreadGo() //for i:=0; i<8; i++ { // <-done //} space.ApplyImpulsesTime = time.Since(start) for _, con := range space.Constraints { con.PostSolve() } for _, arb := range space.Arbiters { if arb.ShapeA.Body.CallbackHandler != nil { arb.ShapeA.Body.CallbackHandler.CollisionPostSolve(arb) } if arb.ShapeB.Body.CallbackHandler != nil { arb.ShapeB.Body.CallbackHandler.CollisionPostSolve(arb) } } if len(space.deleteBodies) > 0 { for _, body := range space.deleteBodies { space.removeBody(body) } space.deleteBodies = space.deleteBodies[0:0] } stepEnd := time.Now() space.StepTime = stepEnd.Sub(stepStart) }
func (body *Body) AddAngularVelocity(w vect.Float) { body.w += vect.Float(w) }
func (body *Body) Torque() vect.Float { return vect.Float(body.t) }
func (body *Body) AddForce(x, y vect.Float) { body.f.X += vect.Float(x) body.f.Y += vect.Float(y) }