// per frame simulation update public void Update(float currentTime, float elapsedTime) { // apply steering force to our momentum ApplySteeringForce(DetermineCombinedSteering(elapsedTime), elapsedTime); // reverse direction when we reach an endpoint if (Globals.UseDirectedPathFollowing) { if (Vector3.Distance(Position, Globals.Endpoint0) < _path.Radius) { _pathDirection = true; annotation.CircleXZ(_path.Radius, Globals.Endpoint0, Color.DarkRed.ToVector3().FromXna(), 20); } if (Vector3.Distance(Position, Globals.Endpoint1) < _path.Radius) { _pathDirection = false; annotation.CircleXZ(_path.Radius, Globals.Endpoint1, Color.DarkRed.ToVector3().FromXna(), 20); } } // annotation annotation.VelocityAcceleration(this, 5, 0); _trail.Record(currentTime, Position); // notify proximity database that our position has changed _proximityToken.UpdateForNewPosition(Position); }
public Vector3 SteerToEvadeAllDefenders() { Vector3 evade = Vector3.Zero; float goalDistance = Vector3.Distance(Globals.HomeBaseCenter, Position); // sum up weighted evasion foreach (CtfEnemy e in Plugin.CtfEnemies) { Vector3 eOffset = e.Position - Position; float eDistance = eOffset.Length(); float eForwardDistance = Vector3.Dot(Forward, eOffset); float behindThreshold = Radius * 2; bool behind = eForwardDistance < behindThreshold; if ((!behind) || (eDistance < 5)) { if (eDistance < (goalDistance * 1.2)) //xxx { // const float timeEstimate = 0.5f * eDistance / e.speed;//xxx float timeEstimate = 0.15f * eDistance / e.Speed; //xxx Vector3 future = e.PredictFuturePosition(timeEstimate); annotation.CircleXZ(e.Radius, future, Globals.EvadeColor.ToVector3().FromXna(), 20); // xxx Vector3 offset = future - Position; Vector3 lateral = Vector3Helpers.PerpendicularComponent(offset, Forward); float d = lateral.Length(); float weight = -1000 / (d * d); evade += (lateral / d) * weight; } } } return(evade); }
private void UpdateState(float currentTime) { // if we reach the goal before being tagged, switch to atGoal state if (State == SeekerState.Running) { float baseDistance = Vector3.Distance(Position, Globals.HomeBaseCenter); if (baseDistance < (Radius + Plugin.BaseRadius)) { State = SeekerState.AtGoal; } } // update lastRunningTime (holds off reset time) if (State == SeekerState.Running) { _lastRunningTime = currentTime; } else { const float RESET_DELAY = 4; float resetTime = _lastRunningTime + RESET_DELAY; if (currentTime > resetTime) { // xxx a royal hack (should do this internal to CTF): Demo.QueueDelayedResetPlugInXXX(); } } }
static float TestOneObstacleOverlap(float minClearance, float r, float radius, Vector3 c, Vector3 center) { float d = Vector3.Distance(c, center); float clearance = d - (r + radius); if (minClearance > clearance) { minClearance = clearance; } return(minClearance); }
// per frame simulation update public void Update(float elapsedTime) { // if I hit the ball, kick it. float distToBall = Vector3.Distance(Position, _ball.Position); float sumOfRadii = Radius + _ball.Radius; if (distToBall < sumOfRadii) { _ball.Kick((_ball.Position - Position) * 50); } // otherwise consider avoiding collisions with others Vector3 collisionAvoidance = SteerToAvoidNeighbors(1, _allPlayers); if (collisionAvoidance != Vector3.Zero) { ApplySteeringForce(collisionAvoidance, elapsedTime); } else { float distHomeToBall = Vector3.Distance(_home, _ball.Position); if (distHomeToBall < 12) { // go for ball if I'm on the 'right' side of the ball if (_imTeamA ? Position.X > _ball.Position.X : Position.X < _ball.Position.X) { Vector3 seekTarget = SteerForSeek(_ball.Position); ApplySteeringForce(seekTarget, elapsedTime); } else { if (distHomeToBall < 12) { float z = _ball.Position.Z - Position.Z > 0 ? -1.0f : 1.0f; Vector3 behindBall = _ball.Position + (_imTeamA ? new Vector3(2, 0, z) : new Vector3(-2, 0, z)); Vector3 behindBallForce = SteerForSeek(behindBall); annotation.Line(Position, behindBall, Color.Green.ToVector3().FromXna()); Vector3 evadeTarget = SteerForFlee(_ball.Position); ApplySteeringForce(behindBallForce * 10 + evadeTarget, elapsedTime); } } } else // Go home { Vector3 seekTarget = SteerForSeek(_home); Vector3 seekHome = SteerForSeek(_home); ApplySteeringForce(seekTarget + seekHome, elapsedTime); } } }
// per frame simulation update public void Update(float currentTime, float elapsedTime) { // determine upper bound for pursuit prediction time float seekerToGoalDist = Vector3.Distance(Globals.HomeBaseCenter, Globals.Seeker.Position); float adjustedDistance = seekerToGoalDist - Radius - Plugin.BaseRadius; float seekerToGoalTime = ((adjustedDistance < 0) ? 0 : (adjustedDistance / Globals.Seeker.Speed)); float maxPredictionTime = seekerToGoalTime * 0.9f; // determine steering (pursuit, obstacle avoidance, or braking) Vector3 steer = Vector3.Zero; if (Globals.Seeker.State == SeekerState.Running) { Vector3 avoidance = SteerToAvoidObstacles(Globals.AVOIDANCE_PREDICT_TIME_MIN, AllObstacles); // saved for annotation Avoiding = (avoidance == Vector3.Zero); steer = Avoiding ? SteerForPursuit(Globals.Seeker, maxPredictionTime) : avoidance; } else { ApplyBrakingForce(Globals.BRAKING_RATE, elapsedTime); } ApplySteeringForce(steer, elapsedTime); // annotation annotation.VelocityAcceleration(this); Trail.Record(currentTime, Position); // detect and record interceptions ("tags") of seeker float seekerToMeDist = Vector3.Distance(Position, Globals.Seeker.Position); float sumOfRadii = Radius + Globals.Seeker.Radius; if (seekerToMeDist < sumOfRadii) { if (Globals.Seeker.State == SeekerState.Running) { Globals.Seeker.State = SeekerState.Tagged; } // annotation: if (Globals.Seeker.State == SeekerState.Tagged) { Color color = new Color((byte)(255.0f * 0.8f), (byte)(255.0f * 0.5f), (byte)(255.0f * 0.5f)); annotation.DiskXZ(sumOfRadii, (Position + Globals.Seeker.Position) / 2, color.ToVector3().FromXna(), 20); } } }
/** * Gets the face area * * @return face area */ public double getArea() { //area = (a * c * sen(B))/2 Point3d p1 = v1.getPosition(); Point3d p2 = v2.getPosition(); Point3d p3 = v3.getPosition(); Vector3d xy = new Vector3d(p2.X - p1.X, p2.Y - p1.Y, p2.Z - p1.Z); Vector3d xz = new Vector3d(p3.X - p1.X, p3.Y - p1.Y, p3.Z - p1.Z); double a = Vector3d.Distance(p1, p2); double c = Vector3d.Distance(p1, p3); double B = xy.Angle(xz); return((a * c * Math.Sin(B)) / 2d); }
//--------------------------------OTHERS----------------------------------------// /** * Computes the distance from the line point to another point * * @param otherPoint the point to compute the distance from the line point. The point * is supposed to be on the same line. * @return points distance. If the point submitted is behind the direction, the * distance is negative */ public double computePointToPointDistance(Point3d otherPoint) { //float distance = otherPoint.distance(point); float distance = Vector3d.Distance(otherPoint, point); Vector3d vec = Vector3d.Normalize(new Vector3d(otherPoint.X - point.X, otherPoint.Y - point.Y, otherPoint.Z - point.Z)); if (Vector3d.Dot(vec, direction) < 0) { return(-distance); } else { return(distance); } }
private void AdjustObstacleAvoidanceLookAhead(bool clearPath) { if (clearPath) { _evading = false; float goalDistance = Vector3.Distance(Globals.HomeBaseCenter, Position); bool headingTowardGoal = this.IsAhead(Globals.HomeBaseCenter, 0.98f); bool isNear = (goalDistance / Speed) < Globals.AVOIDANCE_PREDICT_TIME_MAX; bool useMax = headingTowardGoal && !isNear; Globals.AvoidancePredictTime = (useMax ? Globals.AVOIDANCE_PREDICT_TIME_MAX : Globals.AVOIDANCE_PREDICT_TIME_MIN); } else { _evading = true; Globals.AvoidancePredictTime = Globals.AVOIDANCE_PREDICT_TIME_MIN; } }
// one simulation step public void Update(float currentTime, float elapsedTime) { // when pursuer touches quarry ("wanderer"), reset its position float d = Vector3.Distance(Position, _wanderer.Position); float r = Radius + _wanderer.Radius; if (d < r) { Reset(); } const float MAX_TIME = 20; // xxx hard-to-justify value ApplySteeringForce(SteerForPursuit(_wanderer, MAX_TIME), elapsedTime); // for annotation Trail.Record(currentTime, Position); }
private void SerialNumberAnnotationUtility(ILocalSpaceBasis selected) { // display a Pedestrian's serial number as a text label near its // screen position when it is near the selected vehicle or mouse. if (selected != null) //FIXME: && IsAnnotationEnabled) { foreach (IVehicle vehicle in _crowd) { const float NEAR_DISTANCE = 6; Vector3 vp = vehicle.Position; //Vector3 np = nearMouse.Position; if ((Vector3.Distance(vp, selected.Position) < NEAR_DISTANCE) /* || * (nearMouse != null && (Vector3.Distance(vp, np) < nearDistance))*/) { String sn = String.Format("#{0}", vehicle.GetHashCode()); Color textColor = new Color((byte)(255.0f * 0.8f), (byte)(255.0f * 1), (byte)(255.0f * 0.8f)); Vector3 textOffset = new Vector3(0, 0.25f, 0); Vector3 textPos = vehicle.Position + textOffset; Drawing.Draw2dTextAt3dLocation(sn, textPos, textColor); } } } }
public void ScanRun() { if (_scanQueue.Count == 0) { return; } DestructionRequest request = _scanQueue.First(); int objectsFound = 0; foreach (BarricadeRegion region in BarricadeManager.regions) { foreach (BarricadeData data in region.barricades) { if (Vector3.Distance(request.Position, data.point.ToSystemVector()) > request.Radius) { continue; } if (_destroyQueue.ContainsKey(data.GetHashCode())) { continue; } if (request.SteamID != 0) { if (data.owner != request.SteamID) { continue; } if (request.WreckType != WreckType.Scan && _permissionProvider.CheckHasAnyPermission(_wreckPlugin.Container.Resolve <IPlayerManager> ().GetPlayer(request.SteamID.ToString()), "wreckingball.skip.barricade", "wreckingball.skip.*", "wreckingball.*") == PermissionResult.Grant) { continue; } } if (request.ItemID != 0) { if (data.barricade.id != request.ItemID) { continue; } } if (request.Filters != null) { if (!_wreckPlugin.ConfigurationInstance.Elements.Any(c => request.Filters.Contains(c.CategoryId) && c.Id == data.barricade.id || request.Filters.Contains('*'))) { continue; } } if (request.WreckType != WreckType.Scan && _permissionProvider.CheckHasAnyPermission(request.User, "wreckingball.skip.barricade", "wreckingball.skip.*", "wreckingball.*") == PermissionResult.Grant) { continue; } objectsFound++; if (request.WreckType == WreckType.Scan) { continue; } _destroyQueue.Add(data.GetHashCode(), data); } } foreach (StructureRegion region in StructureManager.regions) { foreach (StructureData data in region.structures) { if (Vector3.Distance(request.Position, data.point.ToSystemVector()) > request.Radius) { continue; } if (_destroyQueue.ContainsKey(data.GetHashCode())) { continue; } if (request.SteamID != 0) { if (data.owner != request.SteamID) { continue; } if (request.WreckType != WreckType.Scan && _permissionProvider.CheckHasAnyPermission(_wreckPlugin.Container.Resolve <IPlayerManager> ().GetPlayer(request.SteamID.ToString()), "wreckingball.skip.structure", "wreckingball.skip.*", "wreckingball.*") == PermissionResult.Grant) { continue; } } if (request.ItemID != 0) { if (data.structure.id != request.ItemID) { continue; } } if (request.Filters != null) { if (!_wreckPlugin.ConfigurationInstance.Elements.Any(c => request.Filters.Contains(c.CategoryId) && c.Id == data.structure.id || request.Filters.Contains('*'))) { continue; } } if (request.WreckType != WreckType.Scan && _permissionProvider.CheckHasAnyPermission(request.User, "wreckingball.skip.structure", "wreckingball.skip.*", "wreckingball.*") == PermissionResult.Grant) { continue; } objectsFound++; if (request.WreckType == WreckType.Scan) { continue; } _destroyQueue.Add(data.GetHashCode(), data); } } foreach (InteractableVehicle vehicle in VehicleManager.vehicles) { if (Vector3.Distance(request.Position, vehicle.transform.position.ToSystemVector()) > request.Radius) { continue; } if (_destroyQueue.ContainsKey(vehicle.GetHashCode())) { continue; } if (request.SteamID != 0) { if (vehicle.lockedOwner.m_SteamID != request.SteamID) { continue; } if (request.WreckType != WreckType.Scan && _permissionProvider.CheckHasAnyPermission(_wreckPlugin.Container.Resolve <IPlayerManager> ().GetPlayer(request.SteamID.ToString()), "wreckingball.skip.vehicle", "wreckingball.skip.*", "wreckingball.*") == PermissionResult.Grant) { continue; } } if (request.ItemID != 0) { if (vehicle.id != request.ItemID) { continue; } } if (request.Filters != null) { if (!_wreckPlugin.ConfigurationInstance.Elements.Any(c => request.Filters.Contains(c.CategoryId) && c.Id == vehicle.id || request.Filters.Contains('*'))) { continue; } } if (request.WreckType != WreckType.Scan && _permissionProvider.CheckHasAnyPermission(request.User, "wreckingball.skip.vehicle", "wreckingball.skip.*", "wreckingball.*") == PermissionResult.Grant) { continue; } objectsFound++; if (request.WreckType == WreckType.Scan) { continue; } _destroyQueue.Add(vehicle.GetHashCode(), vehicle); } if (request.Filters.Contains('A')) { foreach (Animal animal in AnimalManager.animals) { if (Vector3.Distance(request.Position, animal.transform.position.ToSystemVector()) > request.Radius) { continue; } if (_destroyQueue.ContainsKey(animal.GetHashCode())) { continue; } if (request.ItemID != 0) { if (animal.id != request.ItemID) { continue; } } objectsFound++; if (request.WreckType == WreckType.Scan) { continue; } _destroyQueue.Add(animal.GetHashCode(), animal); } } if (request.Filters.Contains('Z')) { foreach (ZombieRegion region in ZombieManager.regions) { foreach (Zombie zombie in region.zombies) { if (Vector3.Distance(request.Position, zombie.transform.position.ToSystemVector()) > request.Radius) { continue; } if (_destroyQueue.ContainsKey(zombie.GetHashCode())) { continue; } if (request.ItemID != 0) { if (zombie.id != request.ItemID) { continue; } } objectsFound++; if (request.WreckType == WreckType.Scan) { continue; } _destroyQueue.Add(zombie.GetHashCode(), zombie); } } } request.User.SendLocalizedMessage(_wreckPlugin.Translations, "wreckingball_scan", objectsFound); _scanQueue.Remove(request); if (request.WreckType == WreckType.Scan) { return; } request.User.SendLocalizedMessage(_wreckPlugin.Translations, "wreckingball_added_destruction", FormattedTimeUntilDestroyed()); }
private void Update(EvaluationContext context) { if (!(SourcePoints.GetValue(context) is StructuredList <Point> sourcePoints)) { return; } if (sourcePoints.NumElements == 0) { sourcePoints.SetLength(0); ResultList.Value = sourcePoints; return; } var spread = Spread.GetValue(context); var spreadMode = (SpreadModes)SpreadMode.GetValue(context); var indexWithinSegment = 0; var lineSegmentLength = 0f; var totalLength = 0f; var maxLength = float.NegativeInfinity; var randomizeStart = RandomizeStart.GetValue(context); var randomizeDuration = RandomizeDuration.GetValue(context); // Measure... segments.Clear(); for (var pointIndex = 0; pointIndex < sourcePoints.NumElements; pointIndex++) { if (float.IsNaN(sourcePoints.TypedElements[pointIndex].W)) { var hasAtLeastTwoPoints = indexWithinSegment > 1; if (hasAtLeastTwoPoints) { if (lineSegmentLength > maxLength) { maxLength = lineSegmentLength; } totalLength += lineSegmentLength; segments.Add(new Segment { PointIndex = pointIndex - indexWithinSegment, PointCount = indexWithinSegment, AccumulatedLength = totalLength, SegmentLength = lineSegmentLength }); } lineSegmentLength = 0; indexWithinSegment = 0; } else { if (indexWithinSegment > 0) { lineSegmentLength += Vector3.Distance(sourcePoints.TypedElements[pointIndex - 1].Position, sourcePoints.TypedElements[pointIndex].Position); } indexWithinSegment++; } } if (totalLength < 0.0001f || segments.Count < 2) { Log.Warning("Stroke animation requires at least two segments with of some length"); return; } // Write offsets... float dist = maxLength / (segments.Count - 1); _random = new Random(42); for (var segmentIndex = 0; segmentIndex < segments.Count; segmentIndex++) { var segmentOffset = ComputeOverlappingProgress(0, segmentIndex, segments.Count, spread); var lengthProgressWithingSegment = 0f; var segment = segments[segmentIndex]; // see https://www.figma.com/file/V5k13NMMIsnAnbWH651clI/Untitled?node-id=205%3A96 var stackedRange = TimeRange.FromStartAndDuration(segment.AccumulatedLength - segment.SegmentLength, segment.SegmentLength) * (1 / totalLength); var anchor = segmentIndex * segment.SegmentLength / (segments.Count - 1); var pGrid = segmentIndex * dist; var packedRange = TimeRange.FromStartAndDuration(pGrid - anchor, segment.SegmentLength) * (1 / maxLength); var range = TimeRange.Lerp(packedRange, stackedRange, spread); if (Math.Abs(randomizeStart) > 0.0001f) { var randomStart = (float)_random.NextDouble() * (1 - range.Duration); range.Start = MathUtils.Lerp(range.Start, randomStart, randomizeStart); } if (Math.Abs(randomizeDuration) > 0.0001f) { var randomDuration = (float)_random.NextDouble() * (1 - range.Start); range.Duration = MathUtils.Lerp(range.Duration, randomDuration, randomizeDuration); } for (var pointIndexInSegment = 0; pointIndexInSegment < segment.PointCount; pointIndexInSegment++) { var pi = segment.PointIndex + pointIndexInSegment; if (pointIndexInSegment > 0) { lengthProgressWithingSegment += Vector3.Distance(sourcePoints.TypedElements[pi - 1].Position, sourcePoints.TypedElements[pi].Position); } var normalizedSegmentPosition = pointIndexInSegment / (segment.PointCount - 1); float w = 0; switch (spreadMode) { case SpreadModes.IgnoreStrokeLengths: var f = lengthProgressWithingSegment / segment.SegmentLength.Clamp(0.001f, 999999f); w = (f - segmentOffset) / (segments.Count + 1); break; case SpreadModes.UseStrokeLength: w = MathUtils.Lerp(range.Start, range.End, normalizedSegmentPosition); break; case SpreadModes.Weird: w = segmentOffset * 0.2f + pointIndexInSegment / segment.PointCount / 2; break; } sourcePoints.TypedElements[pi].W = w; } } StrokeCount.Value = segments.Count; ResultList.Value = sourcePoints; StrokeCount.DirtyFlag.Clear(); ResultList.DirtyFlag.Clear(); }
public override void Redraw(float currentTime, float elapsedTime) { // selected Pedestrian (user can mouse click to select another) IVehicle selected = Demo.SelectedVehicle; // Pedestrian nearest mouse (to be highlighted) IVehicle nearMouse = Demo.VehicleNearestToMouse(); // update camera Demo.UpdateCamera(elapsedTime, selected); // draw "ground plane" if (Demo.SelectedVehicle != null) { _gridCenter = selected.Position; } Demo.GridUtility(_gridCenter); // draw and annotate each Pedestrian foreach (Pedestrian pedestrian in _crowd) { pedestrian.Draw(); } // draw the path they follow and obstacles they avoid DrawPathAndObstacles(); // highlight Pedestrian nearest mouse Demo.HighlightVehicleUtility(nearMouse); // textual annotation (at the vehicle's screen position) SerialNumberAnnotationUtility(selected); // textual annotation for selected Pedestrian if (Demo.SelectedVehicle != null) //FIXME: && annotation.IsEnabled) { Color color = new Color((byte)(255.0f * 0.8f), (byte)(255.0f * 0.8f), (byte)(255.0f * 1.0f)); Vector3 textOffset = new Vector3(0, 0.25f, 0); Vector3 textPosition = selected.Position + textOffset; Vector3 camPosition = Demo.Camera.Position; float camDistance = Vector3.Distance(selected.Position, camPosition); StringBuilder sb = new StringBuilder(); sb.AppendFormat("1: speed: {0:0.00}\n", selected.Speed); sb.AppendFormat("2: cam dist: {0:0.0}\n", camDistance); Drawing.Draw2dTextAt3dLocation(sb.ToString(), textPosition, color); } // display status in the upper left corner of the window StringBuilder status = new StringBuilder(); status.AppendFormat("[F1/F2] Crowd size: {0}\n", _population); status.Append("[F3] PD type: "); switch (_cyclePD) { case 0: status.Append("LQ bin lattice"); break; case 1: status.Append("brute force"); break; } status.Append("\n[F4] "); status.Append(Globals.UseDirectedPathFollowing ? "Directed path following." : "Stay on the path."); status.Append("\n[F5] Wander: "); status.Append(Globals.WanderSwitch ? "yes" : "no"); status.Append("\n"); Vector3 screenLocation = new Vector3(15, 50, 0); Drawing.Draw2dTextAt2dLocation(status.ToString(), screenLocation, Color.LightGray); }
// is there a clear path to the goal? private bool IsPathToGoalClear() { float sideThreshold = Radius * 8.0f; float behindThreshold = Radius * 2.0f; Vector3 goalOffset = Globals.HomeBaseCenter - Position; float goalDistance = goalOffset.Length(); Vector3 goalDirection = goalOffset / goalDistance; bool goalIsAside = this.IsAside(Globals.HomeBaseCenter, 0.5f); // for annotation: loop over all and save result, instead of early return bool xxxReturn = true; // loop over enemies foreach (CtfEnemy e in Plugin.CtfEnemies) { float eDistance = Vector3.Distance(Position, e.Position); float timeEstimate = 0.3f * eDistance / e.Speed; //xxx Vector3 eFuture = e.PredictFuturePosition(timeEstimate); Vector3 eOffset = eFuture - Position; float alongCorridor = Vector3.Dot(goalDirection, eOffset); bool inCorridor = ((alongCorridor > -behindThreshold) && (alongCorridor < goalDistance)); float eForwardDistance = Vector3.Dot(Forward, eOffset); // xxx temp move this up before the conditionals annotation.CircleXZ(e.Radius, eFuture, Globals.ClearPathColor.ToVector3().FromXna(), 20); //xxx // consider as potential blocker if within the corridor if (inCorridor) { Vector3 perp = eOffset - (goalDirection * alongCorridor); float acrossCorridor = perp.Length(); if (acrossCorridor < sideThreshold) { // not a blocker if behind us and we are perp to corridor float eFront = eForwardDistance + e.Radius; //annotation.annotationLine (position, forward*eFront, gGreen); // xxx //annotation.annotationLine (e.position, forward*eFront, gGreen); // xxx // xxx // std::ostringstream message; // message << "eFront = " << std::setprecision(2) // << std::setiosflags(std::ios::fixed) << eFront << std::ends; // draw2dTextAt3dLocation (*message.str(), eFuture, gWhite); bool eIsBehind = eFront < -behindThreshold; bool eIsWayBehind = eFront < (-2 * behindThreshold); bool safeToTurnTowardsGoal = ((eIsBehind && goalIsAside) || eIsWayBehind); if (!safeToTurnTowardsGoal) { // this enemy blocks the path to the goal, so return false annotation.Line(Position, e.Position, Globals.ClearPathColor.ToVector3().FromXna()); // return false; xxxReturn = false; } } } } // no enemies found along path, return true to indicate path is clear // clearPathAnnotation (sideThreshold, behindThreshold, goalDirection); // return true; //if (xxxReturn) ClearPathAnnotation(sideThreshold, behindThreshold, goalDirection); return(xxxReturn); }