/// <summary> /// Calculates the length of the road for the given atom, taking its position and environment into account. This /// method is invoked by each <see cref="RoadAtom"/> during its production, in order to find out its length. /// </summary> /// <returns>The road length.</returns> /// <param name="currentAtom">Current atom.</param> /// <param name="gen">City generator.</param> public virtual float CalculateRoadLength(RoadAtom currentAtom, CityGenerator gen) { // Calculate how much the population density influences road length (the less population, the longer the road) float populationLengthFactor = 1f - gen.DensityAt(currentAtom.Node.position); // Calculate how much the slope of the road influences its length (the steeper, the shorter) float elevationLengthFactor = Mathf.Abs(gen.ElevationAt(currentAtom.Node.position) - gen.ElevationAt(currentAtom.Node.position + currentAtom.Forward)); elevationLengthFactor = 1f - Mathf.Clamp01(gen.slopeExaggeration * elevationLengthFactor); // Multiply them to get the final length factor. Basically the elevation factor should only influence the // population factor when the road is very steep, in other cases it should be close to 1. float lengthFactor = populationLengthFactor * elevationLengthFactor; // Calculate the road length return gen.minimumRoadLength + lengthFactor * (gen.maximumRoadLength - gen.minimumRoadLength); }
public override List<RoadAtom> SpawnRoads(BranchAtom currentAtom, CityGenerator gen) { List<RoadAtom> production = new List<RoadAtom>(); if (currentAtom.Creator != null) { // Get the orientation of the "parent" road (the one we're continuing in this production) MapNode toNode = currentAtom.Node; MapNode fromNode = currentAtom.Node.edges[0].FromNode; Vector3 parentDirection = (toNode.position - fromNode.position).normalized; // Get the elevation at the current point float currentElevation = gen.ElevationAt(currentAtom.Node.position); // Create three roads: left, right and straight with regard to the "parent" road's direction float[] angles = new float[] { -90f, 0f, 90f }; foreach (float angle in angles) { // Rotate the direction vector to get the direction we'll probe in Vector3 roadDirection = Quaternion.Euler(0f, angle, 0f) * parentDirection; // Probe elevations around the given direction and get the direction of the road which is least steep roadDirection = LeastSteepDirection(currentAtom.Node.position, roadDirection, currentElevation, gen); // Create a new RoadAtom with the given road direction RoadAtom roadAtom = new RoadAtom(roadDirection, currentAtom.Node, Rule.Type.Rectangular); // Add it to the production production.Add(roadAtom); } } else { // This is the axiom, just spawn roads in all directions production.Add(new RoadAtom(Vector3.forward, currentAtom.Node, Rule.Type.Rectangular)); production.Add(new RoadAtom(Vector3.back, currentAtom.Node, Rule.Type.Rectangular)); production.Add(new RoadAtom(Vector3.left, currentAtom.Node, Rule.Type.Rectangular)); production.Add(new RoadAtom(Vector3.right, currentAtom.Node, Rule.Type.Rectangular)); } return production; }
/// <summary> /// The prober that probes for elevation at the given position. /// </summary> /// <returns>The elevation at the given position.</returns> /// <param name="gen">City generator.</param> /// <param name="position">Position.</param> public static float ElevationProber(CityGenerator gen, Vector3 position) { return gen.ElevationAt(position); }