public virtual void Update(float elapsed) { // TODO: it would be nicer if this were notified when the // membrane changes to not recheck this constantly Vector3 middle = Hex.AxialToCartesian(new Hex(0, 0)); var relativeOrganellePosition = middle - organellePos; if (relativeOrganellePosition == Vector3.Zero) { relativeOrganellePosition = DefaultVisualPos; } Vector3 exit = middle - relativeOrganellePosition; var membraneCoords = organelle !.ParentMicrobe !.Membrane.GetVectorTowardsNearestPointOfMembrane(exit.x, exit.z); if (!membraneCoords.Equals(lastCalculatedPosition) || NeedsUpdateAnyway()) { float angle = GetAngle(relativeOrganellePosition); var rotation = MathUtils.CreateRotationForExternal(angle); OnPositionChanged(rotation, angle, membraneCoords); lastCalculatedPosition = membraneCoords; } }
/// <summary> /// Calculates a world pos for emitting compounds /// </summary> private Vector3 CalculateNearbyWorldPosition() { // The back of the microbe var exit = Hex.AxialToCartesian(new Hex(0, 1)); var membraneCoords = Membrane.GetVectorTowardsNearestPointOfMembrane(exit.x, exit.z); // Get the distance to eject the compounds var ejectionDistance = Membrane.EncompassingCircleRadius; // The membrane radius doesn't take being bacteria into account if (Species.IsBacteria) { ejectionDistance *= 0.5f; } float angle = 180; // Find the direction the microbe is facing var yAxis = Transform.basis.y; var microbeAngle = Mathf.Atan2(yAxis.x, yAxis.y); if (microbeAngle < 0) { microbeAngle += 2 * Mathf.Pi; } microbeAngle = microbeAngle * 180 / Mathf.Pi; // Take the microbe angle into account so we get world relative degrees var finalAngle = (angle + microbeAngle) % 360; var s = Mathf.Sin(finalAngle / 180 * Mathf.Pi); var c = Mathf.Cos(finalAngle / 180 * Mathf.Pi); var ejectionDirection = new Vector3(-membraneCoords.x * c + membraneCoords.z * s, 0, membraneCoords.x * s + membraneCoords.z * c); return(Translation + (ejectionDirection * ejectionDistance)); }
/// <summary> /// This method calculates the relative rotation and translation this microbe should have to its microbe parent. /// <a href="https://randomthrivefiles.b-cdn.net/documentation/fixed_colony_rotation_explanation_image.png"> /// Visual explanation /// </a> /// </summary> /// <remarks> /// <para> /// Storing the old global translation and rotation, re-parenting and then reapplying the stored values is /// worse than this code because this code utilizes GetVectorTowardsNearestPointOfMembrane. This reduces the /// visual gap between the microbes in a colony. /// </para> /// </remarks> /// <returns>Returns relative translation and rotation</returns> private (Vector3 Translation, Vector3 Rotation) GetNewRelativeTransform() { // Gets the global rotation of the parent var globalParentRotation = ColonyParent.GlobalTransform.basis.GetEuler(); // A vector from the parent to me var vectorFromParent = GlobalTransform.origin - ColonyParent.GlobalTransform.origin; // A vector from me to the parent var vectorToParent = -vectorFromParent; // TODO: using quaternions here instead of assuming that rotating about the up/down axis is right would be nice // This vector represents the vectorToParent as if I had no rotation. // This works by rotating vectorToParent by the negative value (therefore Down) of my current rotation // This is important, because GetVectorTowardsNearestPointOfMembrane only works with non-rotated microbes var vectorToParentWithoutRotation = vectorToParent.Rotated(Vector3.Down, Rotation.y); // This vector represents the vectorFromParent as if the parent had no rotation. var vectorFromParentWithoutRotation = vectorFromParent.Rotated(Vector3.Down, globalParentRotation.y); // Calculates the vector from the center of the parent's membrane towards me with canceled out rotation. // This gets added to the vector calculated one call before. var correctedVectorFromParent = ColonyParent.Membrane .GetVectorTowardsNearestPointOfMembrane(vectorFromParentWithoutRotation.x, vectorFromParentWithoutRotation.z).Rotated(Vector3.Up, globalParentRotation.y); // Calculates the vector from my center to my membrane towards the parent. // This vector gets rotated back to cancel out the rotation applied two calls above. // -= to negate the vector, so that the two membrane vectors amplify correctedVectorFromParent -= Membrane .GetVectorTowardsNearestPointOfMembrane(vectorToParentWithoutRotation.x, vectorToParentWithoutRotation.z) .Rotated(Vector3.Up, Rotation.y); // Rotated because the rotational scope is different. var newTranslation = correctedVectorFromParent.Rotated(Vector3.Down, globalParentRotation.y); return(newTranslation, Rotation - globalParentRotation); }