public static IEnumerable <Part> AttachParts(ParallelSpaceshipParameters param, IEnumerable <Part> parts, IEnumerable <Part> prefabs) { var attached = new List <Part>(); foreach (var part in parts) { foreach (var point in part.attachmentPoints) { if (!point.Blocked && param.attachmentProbability >= Random.value) { var modules = new List <Part>(prefabs.Where(p => p.type == PartType.Attachment)); var i = Random.Range(0, modules.Count); var module = modules.ElementAt(i); var rotation = part.transform.rotation * point.rotation; var position = part.transform.TransformPoint(point.position); var attachment = Object.Instantiate(module, position, rotation) as Part; attached.Add(attachment); if (point.symmetric) { var negPos = point.position; negPos.x = -negPos.x; position = part.transform.TransformPoint(negPos); attachment = Object.Instantiate(module, position, rotation) as Part; attached.Add(attachment); } } } } return(attached); }
public static Transform GenerateSpaceship(int seed, Part[] partPrefabs, ParallelSpaceshipParameters parameters) { Random.seed = seed; var rootNode = SkeletonGenerator.GenerateSkeleton(parameters); var parts = new List <Part>(); parts.AddRange(PartPlacer.PlaceParts(parameters, rootNode, partPrefabs)); parts.AddRange(PartAttacher.AttachParts(parameters, parts, partPrefabs)); parts.AddRange(Mirror(parts)); var ship = new GameObject("Spaceship"); ship.transform.position = rootNode.transform.position; ship.transform.rotation = rootNode.transform.rotation; foreach (var p in parts) { p.transform.parent = ship.transform; } rootNode.KillAllNodes(); return(ship.transform); }
public static IEnumerable <Part> PlaceParts(ParallelSpaceshipParameters param, SkeletonNode rootNode, IEnumerable <Part> prefabs) { var parts = new List <Part>(); parts.AddRange(PlaceSupports(rootNode, prefabs)); parts.AddRange(PlaceStructurals(param, rootNode, prefabs)); return(parts); }
static IEnumerable <Part> PlaceStructurals(ParallelSpaceshipParameters param, SkeletonNode parent, IEnumerable <Part> prefabs) { var placedParts = new List <Part>(); placedParts.AddRange(RecursivePlaceStructural(param, parent, prefabs)); foreach (var wing in parent.wingNodes) { placedParts.AddRange(PlaceStructurals(param, wing, prefabs)); } return(placedParts); }
public static SkeletonNode GenerateSkeleton(ParallelSpaceshipParameters param) { // base node var scalefactor = Random.Range(1 - param.scalefactor, 1 + param.scalefactor); var rootNode = SkeletonNode.Create(new Vector3(0, 0, 0), scalefactor, PartType.Engine); // rear wing shape RecursiveCreateWings(param, rootNode, param.maxWidth); // front nodes RecursiveCreateFronts(param, rootNode, param.maxLength); // create mirrored skeleton for visualisation // rootNode.Mirror (); return(rootNode); }
/// <summary> /// Creates the central structure and duplicates the rear shape of the wings /// </summary> /// <param name="param">Parameter.</param> /// <param name="parent">Parent.</param> static void RecursiveCreateFronts(ParallelSpaceshipParameters param, SkeletonNode parent, int leftLength) { // create new SkeletonNode var scalefactor = Random.Range(1 - param.scalefactor, 1 + param.scalefactor); var distance = Random.Range(param.minDistance, param.maxDistance); var position = parent.transform.position + parent.transform.forward * distance; // select node type PartType type; if (leftLength > 0 && parent.wingNodes.Count > 0 && param.structuralProbability >= Random.value) { type = PartType.Intersection; } else { type = PartType.Cockpit; } var frontNode = SkeletonNode.Create(position, scalefactor, type); parent.AddFront(frontNode); // create subwing structure foreach (var wing in parent.wingNodes) { if (type == PartType.Cockpit) { distance = Random.Range(param.minDistance, param.maxDistance); } RecursiveCreateSubwings(param, wing, parent, distance); } // prevent unwinged intersections if (parent.wingNodes.Count == 0) { frontNode.type = PartType.Cockpit; } // recursive create next frontNode else if (type == PartType.Intersection) { RecursiveCreateFronts(param, frontNode, leftLength - 1); } }
/// <summary> /// Duplicates the shape of the wings for each row /// </summary> /// <param name="param">Parameter.</param> /// <param name="parent">Parent.</param> /// <param name="gParent">G parent.</param> /// <param name="distance">Distance.</param> static void RecursiveCreateSubwings(ParallelSpaceshipParameters param, SkeletonNode parent, SkeletonNode gParent, float distance) { var scalefactor = Random.Range(1 - param.scalefactor, 1 + param.scalefactor); var position = parent.transform.position + parent.transform.forward * distance; // select node type PartType type; if (gParent.frontNode.type != PartType.Intersection || param.structuralProbability <= Random.value) { type = PartType.Cockpit; } else { type = PartType.Intersection; } var subwingNode = SkeletonNode.Create(position, scalefactor, type); parent.AddFront(subwingNode); // add connection if (type == PartType.Intersection) { gParent.frontNode.AddWing(subwingNode); } // recursive create subwings foreach (var wing in parent.wingNodes) { if (type == PartType.Cockpit) { distance = Random.Range(param.minDistance, param.maxDistance); } RecursiveCreateSubwings(param, wing, parent, distance); } }
/// <summary> /// Creates the shape of the wings at the rear section of the skeleton /// </summary> /// <param name="param">Parameter.</param> /// <param name="parent">Parent.</param> static void RecursiveCreateWings(ParallelSpaceshipParameters param, SkeletonNode parent, int leftWings) { var nWings = param.maxWings; while (nWings > 0 && leftWings > 0 && param.wingProbability >= Random.value) { var scalefactor = Random.Range(1 - param.scalefactor, 1 + param.scalefactor); var distance = Random.Range(param.minDistance, param.maxDistance); var xRot = Random.Range(param.minXAngle, param.maxXAngle); var yRot = Random.Range(param.minYAngle, param.maxYAngle) + 90F; var zRot = 0F; // ! var position = parent.transform.position + (Quaternion.Euler(xRot, yRot, zRot) * parent.transform.forward * distance); parent.AddWing(SkeletonNode.Create(position, scalefactor, PartType.Engine)); nWings--; } foreach (var wing in parent.wingNodes) { RecursiveCreateWings(param, wing, leftWings - 1); } }
static IEnumerable <Part> RecursivePlaceStructural(ParallelSpaceshipParameters param, SkeletonNode parent, IEnumerable <Part> prefabs, Part rear = null) { var placedParts = new List <Part>(); var frontPosition = parent.frontNode.transform.position; var rearPosition = parent.transform.position; var vector = frontPosition - rearPosition; var rotation = parent.transform.rotation; // place rear connector & engine by probability if (rear == null) { var intersection = GetRandomPart(prefabs, PartType.Intersection); if (intersection == null) { return(placedParts); } rear = Instantiate(intersection, rearPosition, rotation, placedParts, parent.scalefactor); if (param.engineProbability > Random.value) { // place engine var engine = GetRandomPart(prefabs, PartType.Engine); if (engine == null) { return(placedParts); } var enginePos = rearPosition - vector.normalized * (rear.radius + engine.radius * parent.scalefactor); Instantiate(engine, enginePos, rotation, placedParts, parent.scalefactor); } } // place front depending on type PartType frontType; if (parent.frontNode.type == PartType.Intersection) { frontType = parent.frontNode.type; } else if (param.cockpitProbability >= Random.value) { frontType = PartType.Cockpit; } else { frontType = PartType.Ending; } var frontPart = GetRandomPart(prefabs, frontType); if (frontPart == null) { return(placedParts); } var front = Instantiate(frontPart, frontPosition, rotation, placedParts, parent.frontNode.scalefactor); // update positions & vector rearPosition += vector.normalized * rear.radius; frontPosition -= vector.normalized * front.radius; vector = frontPosition - rearPosition; // calculate median scaling of vector parts var scale = (parent.scalefactor + parent.frontNode.scalefactor) / 2; // virtualize parts for vector var fillers = new List <Part>(); var filled = 0F; do { var part = GetRandomPart(prefabs, PartType.Structural); if (part == null) { return(placedParts); } fillers.Add(part); filled += 2 * part.radius * scale; } while (filled < (vector.magnitude - filled) * fillers.Count * 2); // median part radius > left space // calculate final scalefactor scale *= vector.magnitude / filled; // fill vector with parts foreach (var prefab in fillers) { var partPos = rearPosition + vector.normalized * prefab.radius * scale; var part = Instantiate(prefab, partPos, rotation, placedParts, scale); // reposition insert point rearPosition += vector.normalized * 2 * part.radius; } // call next if (parent.frontNode.frontNode != null) { placedParts.AddRange(RecursivePlaceStructural(param, parent.frontNode, prefabs, front)); } return(placedParts); }