Hello guys,
So I’ve almost finished this code about boids. I only couldn’t figure this part out:
I created boids randomly across a surface moved them by a certain vector and then I project
the points with time the position updates.
the problem is: I can’t make the point to bounce back to the surface with they reach boundary
of the surface.
Here is the code:
using System.Collections.Generic;
using Grasshopper.GUI.Widgets;
using Rhino.Geometry;namespace SurfaceTrails2.FlockingOnSrf2
{
public class FlockAgent
{
public Point3d Position;
public Vector3d Velocity;
public FlockSystem FlockSystem;
private Vector3d desiredVelocity = new Vector3d(0,0,0);public FlockAgent(Point3d position, Vector3d velocity) { Position = position; Velocity = velocity; } public void UpdateVelocityAndPosition() { double maxVelocity = 0.02667 * FlockSystem.BoundingBox; double minVelocity = 0.1333 * FlockSystem.BoundingBox; Velocity = 0.97 * Velocity + 0.03 * desiredVelocity; if (Velocity.Length > maxVelocity) Velocity *= maxVelocity / Velocity.Length; else if (Velocity.Length < minVelocity) Velocity *= minVelocity / Velocity.Length; Position += Velocity * FlockSystem.Timestep; double u; double v; //var nu = (Position.X - 0) / (BoundingBox - 0); //var nv = (Position.Y - 0) / (BoundingBox - 0); FlockSystem.Surface.ClosestPoint(Position, out u, out v); Position = FlockSystem.Surface.PointAt(u, v); } public void ComputeDesiredVelocity(List<FlockAgent> neighbours/*, Surface surface*/) { // First, reset the desired velocity to 0 desiredVelocity = new Vector3d(FlockSystem.Surface.Domain(0).T0, FlockSystem.Surface.Domain(1).T0, 0.0); var bounceMultiplier = 30; // =============================================================================== // Pull the agent back if it gets out of the bounding box // =============================================================================== var xMin = FlockSystem.Surface.PointAt(FlockSystem.Surface.Domain(0).T0, FlockSystem.Surface.Domain(1).T0).X; var xMax = FlockSystem.Surface.PointAt(FlockSystem.Surface.Domain(0).T1, FlockSystem.Surface.Domain(1).T0).X; var yMin = FlockSystem.Surface.PointAt(FlockSystem.Surface.Domain(0).T0, FlockSystem.Surface.Domain(1).T0).Y; var yMax = FlockSystem.Surface.PointAt(FlockSystem.Surface.Domain(0).T0, FlockSystem.Surface.Domain(1).T1).Y; //if (Position.X < xMin) // desiredVelocity += new Vector3d((FlockSystem.BoundingBox - Position.X) * bounceMultiplier, 0.0, 0.0); //else if (Position.X > xMax) // desiredVelocity += new Vector3d(-Position.X * bounceMultiplier, 0.0, 0.0); //if (Position.Y < yMin) // desiredVelocity += new Vector3d(0.0, (FlockSystem.BoundingBox - Position.Y) * bounceMultiplier, 0.0); //else if (Position.Y > yMax) // desiredVelocity += new Vector3d(0.0, (-Position.Y) * bounceMultiplier, 0.0); //if (Position.X < xMin) // desiredVelocity += new Vector3d((xMax - Position.X) * bounceMultiplier, 0.0, 0.0); //else if (Position.X > xMax) // desiredVelocity += new Vector3d(-Position.X * bounceMultiplier, 0.0, 0.0); //if (Position.Y < yMin) // desiredVelocity += new Vector3d(0.0, (yMax - Position.Y) * bounceMultiplier, 0.0); //else if (Position.Y > yMax) // desiredVelocity += new Vector3d(0.0, (-Position.Y) * bounceMultiplier, 0.0); //if (Position.Z < 0.0) // desiredVelocity += new Vector3d(0.0, 0.0, -Position.Z); //else if (Position.Z > boundingBoxSize) // desiredVelocity += new Vector3d(0.0, 0.0, boundingBoxSize - Position.Z); double u; double v; FlockSystem.Surface.ClosestPoint(Position, out u, out v); var closestPoint = FlockSystem.Surface.PointAt(u, v); if (Position.DistanceTo(closestPoint) < 0.1) { //desiredVelocity.Reverse(); ////desiredVelocity.Transform(FlockSystem.Orient); //desiredVelocity += desiredVelocity * bounceMultiplier; var reverse = Point3d.Subtract(Position, FlockSystem.Surface.PointAt(u, v)); //reverse.Reverse(); desiredVelocity += reverse * bounceMultiplier; } // =============================================================================== // If there are no neighbours nearby, the agent will maintain its veloctiy, // else it will perform the "alignment", "cohension" and "separation" behaviours // =============================================================================== if (neighbours.Count == 0) desiredVelocity += Velocity; // maintain the current velocity else { // ------------------------------------------------------------------------------- // "Alignment" behavior // ------------------------------------------------------------------------------- Vector3d alignment = Vector3d.Zero; foreach (FlockAgent neighbour in neighbours) alignment += neighbour.Velocity; // We divide by the number of neighbours to actually get their average velocity alignment /= neighbours.Count; desiredVelocity += FlockSystem.AlignmentStrength * alignment; // ------------------------------------------------------------------------------- // "Cohesion" behavior // ------------------------------------------------------------------------------- Point3d centre = Point3d.Origin; foreach (FlockAgent neighbour in neighbours) centre += neighbour.Position; // We divide by the number of neighbours to actually get their centre of mass centre /= neighbours.Count; Vector3d cohesion = centre - Position; desiredVelocity += FlockSystem.CohesionStrength * cohesion; // ------------------------------------------------------------------------------- // "Separation" behavior // ------------------------------------------------------------------------------- Vector3d separation = Vector3d.Zero; foreach (FlockAgent neighbour in neighbours) { double distanceToNeighbour = Position.DistanceTo(neighbour.Position); if (distanceToNeighbour < FlockSystem.SeparationDistance) { Vector3d getAway = Position - neighbour.Position; /* We scale the getAway vector by inverse of distanceToNeighbour to make the getAway vector bigger as the agent gets closer to its neighbour */ separation += getAway / (getAway.Length * distanceToNeighbour); } } desiredVelocity += FlockSystem.SeparationStrength * separation; } // =============================================================================== // Avoiding the obstacles (repellers) // =============================================================================== foreach (Circle repeller in FlockSystem.Repellers) { double distanceToRepeller = Position.DistanceTo(repeller.Center); Vector3d repulsion = Position - repeller.Center; // Repulstion gets stronger as the agent gets closer to the repeller repulsion /= (repulsion.Length * distanceToRepeller); // Repulsion strength is also proportional to the radius of the repeller circle/sphere // This allows the user to tweak the repulsion strength by tweaking the radius repulsion *= 30.0 * repeller.Radius; desiredVelocity += repulsion; } } }
}
Any help would be much appreaciated.
Thank you .