public void Update() { //for (int i = 0; i < Compatible.Count; i++) Parallel.For(0, Compatible.Count, (i) => { var transform = Compatible[i].GetComponent <TransformComponent>(); var nose = Compatible[i].GetComponent <NoseComponent>(); var nearby = _grid.GetNearbyEntities(transform.WorldPosition, nose.NoseRange, (e) => e.HasComponent <EdibleComponent>()); nose.CosActivation = 0; nose.SinActivation = 0; float closestFound = nose.NoseRangeSquared + 1; foreach (var(distSqr, entity) in nearby) { if (distSqr <= 0) { continue; } // if the closest only setting is on, only report smell of closest food. if (nose.ClosestOnly) { if (distSqr > closestFound) { continue; } closestFound = distSqr; // reset the other activations nose.CosActivation = 0; nose.SinActivation = 0; } // Inverse square law // Activation is inverseley proportional to the square of the distance of the object from the eye // In this case we take it as the normalised distance (n) // n = d/r // We want to calculate 1/n^2. // -> n^2 = d^2/r^2 // -> 1/n^2 = r^2/d^2, so we don't have to do any sqrts and only one division! var targetTransform = entity.GetComponent <TransformComponent>(); float angleBetween = Angles.AngleBetweenPoints(transform.WorldPosition, targetTransform.WorldPosition); float diffAngle = Angles.CalculateAngleDiff(angleBetween, transform.WorldRotation.Theta); // Take into account direction. // If the angle difference is small then the Cosine of teh angle will be large. // This means the scent will be stronger when looking at the edible. var distMult = (nose.NoseRangeSquared / distSqr); if (!nose.ConsiderRange) { distMult = 1; } nose.CosActivation += (float)(Math.Cos(diffAngle) * distMult); nose.SinActivation += (float)(Math.Sin(diffAngle) * distMult); #if DEBUG // Debug.WriteLine($"Activated"); #endif } if (nose.ConsiderRange) { nose.CosActivation = (float)ActivationFunctions.Softsign(nose.CosActivation); nose.SinActivation = (float)ActivationFunctions.Softsign(nose.SinActivation); } if (Compatible[i].TryGetComponent <GraphicsComponent>(out GraphicsComponent graphics)) { var newCol = new Color( (float)Math.Max(nose.CosActivation, 0.3), (float)Math.Max(nose.CosActivation, 0.3), (float)Math.Max(nose.CosActivation, 0.3)); graphics.Color = Color.Lerp(graphics.Color, newCol, 0.1f); } });
public void Update() { Parallel.For(0, Compatible.Count, (i) => //for (int i = 0; i < Compatible.Count; i++) { var transform = Compatible[i].GetComponent <TransformComponent>(); var eye = Compatible[i].GetComponent <EyeComponent>(); var nearby = _grid.GetNearbyEntities(transform.WorldPosition, eye.EyeRange, (e) => e.HasComponent <VisibleColourComponent>()); eye.ActivationR = 0; eye.ActivationG = 0; eye.ActivationB = 0; foreach (var(distSqr, entity) in nearby) { if (distSqr <= 0) { continue; } // Inverse square law // Activation is inverseley proportional to the square of the distance of the object from the eye // In this case we take it as the normalised distance (n) // n = d/r // We want to calculate 1/n^2. // -> n^2 = d^2/r^2 // -> 1/n^2 = r^2/d^2, so we don't have to do any sqrts and only one division! var targetTransform = entity.GetComponent <TransformComponent>(); float angleBetween = Angles.AngleBetweenPoints(transform.WorldPosition, targetTransform.WorldPosition); float diffAngle = Angles.CalculateAngleDiff(angleBetween, transform.WorldRotation.Theta); //eyeRot: {MathHelper.ToDegrees(transform.WorldRotation.Theta)}, diffAngle: {MathHelper.ToDegrees(diffAngle)}, #if DEBUG // Debug.WriteLine($"Diff {diffAngle}"); //Debug.WriteLine($"angleBetween {MathHelper.ToDegrees(angleBetween)}"); #endif // Check in fov // if not continue; if (Math.Abs(diffAngle) > eye.Fov / 2) { #if DEBUG //Debug.WriteLine($"Out of fov"); #endif continue; } var targetColour = entity.GetComponent <VisibleColourComponent>(); var distMult = (eye.EyeRangeSquared / distSqr); eye.ActivationR += distMult * targetColour.RealR; eye.ActivationG += distMult * targetColour.RealG; eye.ActivationB += distMult * targetColour.RealB; if (eye.BinaryMode && eye.ActivationR > 0 && eye.ActivationG > 0 && eye.ActivationB > 0) { break; } #if DEBUG // Debug.WriteLine($"Activated"); #endif } if (eye.BinaryMode) { eye.ActivationR = eye.ActivationR > 0 ? 1 : 0; eye.ActivationG = eye.ActivationG > 0 ? 1 : 0; eye.ActivationB = eye.ActivationB > 0 ? 1 : 0; } else { eye.ActivationR = (float)ActivationFunctions.Softsign(eye.ActivationR); eye.ActivationG = (float)ActivationFunctions.Softsign(eye.ActivationG); eye.ActivationB = (float)ActivationFunctions.Softsign(eye.ActivationB); } if (Compatible[i].TryGetComponent <GraphicsComponent>(out GraphicsComponent graphics)) { var newCol = new Color( (float)Math.Max(eye.ActivationR, 0.1), (float)Math.Max(eye.ActivationG, 0.1), (float)Math.Max(eye.ActivationB, 0.1)); graphics.Color = Color.Lerp(graphics.Color, newCol, 0.1f); } });