public void SimulateSpringForces(float dt) { for (int i = 0; i < kGridHeight * kGridWidth; ++i) { SpringNode node = Nodes[i]; if (node.Locked) { continue; } Spring(node, node.Left, dt, kHorizSpringDist, kSpringForceHoriz); Spring(node, node.Right, dt, kHorizSpringDist, kSpringForceHoriz); Spring(node, node.Up, dt, kHorizSpringDist, kSpringForceVert); Spring(node, node.Down, dt, kHorizSpringDist, kSpringForceVert); Spring(node, node.UL, dt, kDiagSpringDist, kSpringForceDiag); Spring(node, node.DL, dt, kDiagSpringDist, kSpringForceDiag); Spring(node, node.UR, dt, kDiagSpringDist, kSpringForceDiag); Spring(node, node.DR, dt, kDiagSpringDist, kSpringForceDiag); // Spring force back towards origin Vector3 originDelta = node.Origin - node.Pos; float originDist2 = originDelta.sqrMagnitude; if (originDist2 > 0.000001f) { // accel towards origin is proportional to distance^3 Vector3 accel = originDist2 * (originDelta * dt * kSpringForceOrigin); node.Velocity += accel; } } }
public void UnlinkRight() { if (RightGrid == null) { return; } // unlink all the nodes for (int y = 0; y < kGridHeight; ++y) { SpringNode otherNode = RightGrid.GetNode(0, y); otherNode.Left = null; otherNode = RightGrid.GetNode(0, y - 1); if (otherNode != null) { otherNode.UL = null; } otherNode = RightGrid.GetNode(0, y + 1); if (otherNode != null) { otherNode.DL = null; } } RightGrid.LeftGrid = null; RightGrid = null; }
public void LinkRight(SpringGrid rightGrid) { if (RightGrid != null) { UnlinkRight(); } RightGrid = rightGrid; RightGrid.LeftGrid = this; for (int y = 0; y < kGridHeight; ++y) { // We leave the far-rightmost grid node as a mirror of the leftmost grid node in the next grid // So link the left-side nodes from the next grid to the 2nd-from-the-right nodes in this grid SpringNode thisNode = GetNode(kGridWidth - 2, y); SpringNode otherNode = RightGrid.GetNode(0, y); otherNode.Left = thisNode; otherNode = RightGrid.GetNode(0, y - 1); if (otherNode != null) { otherNode.UL = thisNode; } otherNode = RightGrid.GetNode(0, y + 1); if (otherNode != null) { otherNode.DL = thisNode; } } }
public override void Update(TimeSpan elapsed) { SpringNode tail = skeleton.Nodes[skeleton.Nodes.Count - 1]; a += tail.Velocity.X + tail.Velocity.Z; rotation = Matrix.CreateFromYawPitchRoll(a, a / 2, a / 4); }
public void UpdateSeams() { if (RightGrid != null) { // Stitch right line of this as a copy of the left line of the adjacent mesh for (int y = 0; y < kGridHeight; ++y) { SpringNode node = GetNode(kGridWidth - 1, y); SpringNode otherNode = RightGrid.GetNode(0, y); node.Pos = otherNode.Pos; node.Velocity = otherNode.Velocity; } } }
public void CalculateVelocity(UndirecteGraph <SpringNode, Edge <SpringNode> > graph, float speed) { List <Edge <SpringNode> > connectedEdges = graph.GetConnectedEdges(this); Vector3 velocity = Vector3.zero; foreach (var edge in connectedEdges) { SpringNode connectedVertex = edge.GetOtherVertex(this); float weight = (float)edge.Weight; Vector3 direction = connectedVertex.Position - this.Position; velocity += direction * (direction.magnitude - weight); } _velocity = velocity * speed; }
public void SeaLevel(float thetaRadians, ref float prevBest) { // TODO: check if this should be 0 or kGridHeight-1 const int y = kGridHeight - 1; SpringNode prevNode = Nodes[GridIdx(0, y)]; Vector2 prevPolar = World.GetPolarCoordinate(prevNode.Pos); for (int x = 1; x < kGridWidth; ++x) { SpringNode curNode = Nodes[GridIdx(x, y)]; Vector2 curPolar = World.GetPolarCoordinate(curNode.Pos); // Check if this segment is forward facing float polarDiff = curPolar.y - prevPolar.y; if (polarDiff < -Mathf.PI) { polarDiff += Mathf.PI * 2; } if (polarDiff >= 0 && polarDiff < Mathf.PI) { // Check if the selected point is inside this line segment float pointDiff = thetaRadians - prevPolar.y; if (pointDiff < -Mathf.PI) { pointDiff += Mathf.PI * 2; } if (pointDiff >= 0 && pointDiff <= polarDiff) { // point is inside forward facing line segment, get sea level at that point float newSeaLevel = curPolar.x; if (polarDiff > 0.001f) { newSeaLevel = Mathf.Lerp(prevPolar.x, curPolar.x, pointDiff / polarDiff); } if (newSeaLevel > prevBest) { prevBest = newSeaLevel; } } } prevPolar = curPolar; } }
public void CreateNodes() { Nodes = new SpringNode[kGridHeight * kGridWidth]; // create nodes for (int y = 0; y < kGridHeight; ++y) { for (int x = 0; x < kGridWidth; ++x) { Nodes[GridIdx(x, y)] = new SpringNode(); } } const float xScale = 1.0f / (kGridWidth - 1); const float yScale = 1.0f / (kGridHeight - 1); for (int y = 0; y < kGridHeight; ++y) { for (int x = 0; x < kGridWidth; ++x) { SpringNode thisNode = GetNode(x, y); // Calculate position float theta = Mathf.Lerp(Theta, Theta + kThetaDelta, x * xScale); float height = Mathf.Lerp(kInnerRadius, kOuterRadius, y * yScale); Vector3 pos = World.GetWorldCoordinate(new Vector2(height, theta * Mathf.Deg2Rad)); thisNode.Pos = thisNode.Origin = pos; thisNode.Velocity = Vector3.zero; thisNode.Down = GetNode(x, y - 1); thisNode.Up = GetNode(x, y + 1); thisNode.Left = GetNode(x - 1, y); thisNode.Right = GetNode(x + 1, y); thisNode.DR = GetNode(x + 1, y - 1); thisNode.DL = GetNode(x - 1, y - 1); thisNode.UR = GetNode(x + 1, y + 1); thisNode.UL = GetNode(x - 1, y + 1); thisNode.Locked = (y == 0); } } }
public void AddOutwardForce(Vector2 center, float dist, float power) { Vector3 center3 = new Vector3(center.x, center.y, 0); float distSq = dist * dist; // TODO: Don't visit every node for (int i = 0; i < kGridHeight * kGridWidth; ++i) { SpringNode node = Nodes[i]; Vector3 diff = node.Pos - center3; float diffMagSq = diff.sqrMagnitude; if (diffMagSq > 0.01f && diffMagSq < distSq) { //power *= 1 - (diff.magnitude / dist); node.Velocity += power * diff.normalized; } } }
private static void Spring(SpringNode node, SpringNode other, float dt, float dist, float force) { if (other == null) { return; } Vector3 posDelta = other.Pos - node.Pos; float lengthDelta = posDelta.magnitude; float springError = lengthDelta - dist; if (springError < 0) { // TODO: force to counteract compression is higher than force to counteract expansion? springError *= 1; } Vector3 accel = posDelta * ((springError / lengthDelta) * force * dt); node.Velocity += accel; }
private static void Spring(SpringNode node, SpringNode other, float dt, float dist, float force) { if (other == null) return; Vector3 posDelta = other.Pos - node.Pos; float lengthDelta = posDelta.magnitude; float springError = lengthDelta - dist; if(springError < 0) { // TODO: force to counteract compression is higher than force to counteract expansion? springError *= 1; } Vector3 accel = posDelta * ((springError / lengthDelta) * force * dt); node.Velocity += accel; }
public void CreateNodes() { Nodes = new SpringNode[kGridHeight * kGridWidth]; // create nodes for(int y = 0; y < kGridHeight; ++y) { for(int x = 0; x < kGridWidth; ++x) { Nodes[GridIdx(x, y)] = new SpringNode(); } } const float xScale = 1.0f / (kGridWidth - 1); const float yScale = 1.0f / (kGridHeight - 1); for(int y = 0; y < kGridHeight; ++y) { for(int x = 0; x < kGridWidth; ++x) { SpringNode thisNode = GetNode(x,y); // Calculate position float theta = Mathf.Lerp(Theta, Theta + kThetaDelta, x * xScale); float height = Mathf.Lerp(kInnerRadius, kOuterRadius, y * yScale); Vector3 pos = World.GetWorldCoordinate(new Vector2(height, theta * Mathf.Deg2Rad)); thisNode.Pos = thisNode.Origin = pos; thisNode.Velocity = Vector3.zero; thisNode.Down = GetNode(x, y-1); thisNode.Up = GetNode(x, y+1); thisNode.Left = GetNode(x-1, y); thisNode.Right = GetNode(x+1, y); thisNode.DR = GetNode(x + 1, y - 1); thisNode.DL = GetNode(x - 1, y - 1); thisNode.UR = GetNode(x + 1, y + 1); thisNode.UL = GetNode(x - 1, y + 1); thisNode.Locked = (y == 0); } } }
LookAtCamera camera = null;//Camera camera = null; public override void Initialize() { base.Initialize(); skeleton.Enabled = true; skeleton.Coefficient = 0.3f; skeleton.Elasticity = 0.01f; skeleton.EnergyLoss = 0.86f; float width = 2; float height = 2; float depth = 3; float w = width / 2; float h = height / 2; float d = depth / 2; Vector3 offset = Vector3.Zero;//transform.Position; PlayingField field = GameContainer.Scene.Coordinator.Select("Playing Field")[0].Get <PlayingField>(); if (goal.PlayerIndex == PlayerIndex.One) { offset = new Vector3(-(field.Width / 2) - (goal.Extents.X / 2) + 1.5f, 1, 0); } else if (goal.PlayerIndex == PlayerIndex.Two) { // hacky, i've messed something up with positioning, so the right goal seems further away.. offset = new Vector3((field.Width / 2) + (goal.Extents.X / 2) - 3.5f, 1, 0); } // goal SpringNode a1 = null; // :> if (goal.PlayerIndex == PlayerIndex.One) { a1 = new SpringNode(offset + new Vector3(-w, -h, d)); } else if (goal.PlayerIndex == PlayerIndex.Two) { a1 = new SpringNode(offset + new Vector3(w * 3, -h, d)); } SpringNode a2 = new SpringNode(offset + new Vector3(w, -h, d)); SpringNode a3 = new SpringNode(offset + new Vector3(w, h, d)); SpringNode b1 = null; // :> if (goal.PlayerIndex == PlayerIndex.One) { b1 = new SpringNode(offset + new Vector3(-w, -h, -d)); } else if (goal.PlayerIndex == PlayerIndex.Two) { b1 = new SpringNode(offset + new Vector3(w * 3, -h, -d)); } SpringNode b2 = new SpringNode(offset + new Vector3(w, -h, -d)); SpringNode b3 = new SpringNode(offset + new Vector3(w, h, -d)); SpringNodeAnchor a1Anchor = new SpringNodeAnchor(a1); SpringNodeAnchor a2Anchor = new SpringNodeAnchor(a2); SpringNodeAnchor a3Anchor = new SpringNodeAnchor(a3); SpringNodeAnchor b1Anchor = new SpringNodeAnchor(b1); SpringNodeAnchor b2Anchor = new SpringNodeAnchor(b2); SpringNodeAnchor b3Anchor = new SpringNodeAnchor(b3); a1.Neighbors.Add(a2, Vector3.Distance(a1.Position, a2.Position)); a1.Neighbors.Add(a3, Vector3.Distance(a1.Position, a3.Position)); a1.Neighbors.Add(b1, Vector3.Distance(a1.Position, b1.Position)); a2.Neighbors.Add(a1, Vector3.Distance(a2.Position, a1.Position)); a2.Neighbors.Add(a3, Vector3.Distance(a2.Position, a3.Position)); a3.Neighbors.Add(a1, Vector3.Distance(a3.Position, a1.Position)); a3.Neighbors.Add(a2, Vector3.Distance(a3.Position, a2.Position)); a3.Neighbors.Add(b3, Vector3.Distance(a3.Position, b3.Position)); b1.Neighbors.Add(b2, Vector3.Distance(b1.Position, b2.Position)); b1.Neighbors.Add(b3, Vector3.Distance(b1.Position, b3.Position)); b1.Neighbors.Add(a1, Vector3.Distance(b1.Position, a1.Position)); b2.Neighbors.Add(b1, Vector3.Distance(b2.Position, b1.Position)); b2.Neighbors.Add(b3, Vector3.Distance(b2.Position, b3.Position)); b3.Neighbors.Add(b1, Vector3.Distance(b3.Position, b1.Position)); b3.Neighbors.Add(b2, Vector3.Distance(b3.Position, b2.Position)); b3.Neighbors.Add(a3, Vector3.Distance(b3.Position, a3.Position)); // net float dist = 0.5f; SpringNode na1 = new SpringNode(new Vector3(0, 0, 0)); SpringNode na2 = new SpringNode(new Vector3(dist, 0, 0)); SpringNode na3 = new SpringNode(new Vector3(dist * 2, 0, 0)); SpringNode na4 = new SpringNode(new Vector3(dist * 3, 0, 0)); SpringNode na5 = new SpringNode(new Vector3(0, dist, 0)); SpringNode na6 = new SpringNode(new Vector3(dist, dist, 0)); SpringNode na7 = new SpringNode(new Vector3(dist * 2, dist, 0)); SpringNode na8 = new SpringNode(new Vector3(dist * 3, dist, 0)); na1.Neighbors.Add(na2, dist); na1.Neighbors.Add(na5, dist); na2.Neighbors.Add(na1, dist); na2.Neighbors.Add(na6, dist); na2.Neighbors.Add(na3, dist); na3.Neighbors.Add(na2, dist); na3.Neighbors.Add(na4, dist); na3.Neighbors.Add(na7, dist); na4.Neighbors.Add(na3, dist); na4.Neighbors.Add(na8, dist); na5.Neighbors.Add(na1, dist); na5.Neighbors.Add(na6, dist); na6.Neighbors.Add(na5, dist); na6.Neighbors.Add(na2, dist); na6.Neighbors.Add(na7, dist); na7.Neighbors.Add(na6, dist); na7.Neighbors.Add(na3, dist); na7.Neighbors.Add(na8, dist); na8.Neighbors.Add(na7, dist); na8.Neighbors.Add(na4, dist); a1.Neighbors.Add(na4, dist); na4.Neighbors.Add(a1, dist); b1.Neighbors.Add(na1, dist); na1.Neighbors.Add(b1, dist); a3.Neighbors.Add(na8, dist); na8.Neighbors.Add(a3, dist); b3.Neighbors.Add(na5, dist); na5.Neighbors.Add(b3, dist); skeleton.Nodes.AddRange( new SpringNode[] { a1, a2, a3, b1, b2, b3, na1, na2, na3, na4, na5, na6, na7, na8 }); skeleton.Anchors.AddRange(new SpringNodeAnchor[] { a1Anchor, a2Anchor, a3Anchor, b1Anchor, b2Anchor, b3Anchor }); }