Created
August 21, 2020 12:02
-
-
Save andybak/bdb66899015ed6b7ab9d04034580909a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using Conway; | |
using Johnson; | |
using UnityEngine; | |
using Random = UnityEngine.Random; | |
[ExecuteInEditMode] | |
[RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))] | |
public class RandomSpaceshipGenerator : MonoBehaviour | |
{ | |
public Material material; | |
[Range(3, 10)] | |
public int numSides = 4; | |
[Range(2, 5)] | |
public int numSections = 4; | |
[Range(0, 3)] | |
public float NoseLength = 1; | |
[Range(0, 1)] | |
public float NoseSharpness = 1; | |
public bool NoseVariant; | |
public bool EngineVariant; | |
public int seed = 12345; | |
[Range(0f, 1f)] | |
public float ChanceOfSimpleSegment = 0.85f; | |
[Range(0f, 1f)] | |
public float ChanceOfLaceSegment = 0.75f; | |
[Range(0f, 1f)] | |
public float ChanceOfTruncateSegment = 0.75f; | |
[Range(0f, 1f)] | |
public float ChanceOfFins = 0.5f; | |
[Range(0f, 1f)] | |
public float ChanceOfWings = 0.25f; | |
public float foo = 0f; | |
public float bar = 0f; | |
private float loftLow = -.25f; | |
private float loftHigh = 0.75f; | |
void Start() | |
{ | |
Generate(); | |
} | |
private void OnValidate() | |
{ | |
Generate(); | |
} | |
[ContextMenu("Generate")] | |
public void Generate() | |
{ | |
Random.seed = seed; | |
var spaceship = JohnsonPoly.Prism(numSides); | |
var wings = new ConwayPoly(); | |
float angleCorrection = 180f / numSides; | |
if (numSides % 2 != 0) angleCorrection /= 2f; | |
spaceship = spaceship.Rotate(Vector3.up, angleCorrection); | |
spaceship = spaceship.Rotate(Vector3.left, -90); | |
for (int i = 0; i < 2; i++) // Loop twice - once for the back and once for the front. | |
{ | |
for (int j = 0; j <= numSections; j++) | |
{ | |
spaceship = MakeSection(spaceship); | |
} | |
// Second time through loop: | |
// Flip the spaceship around ready to generate the back sections | |
spaceship = spaceship.Rotate(Vector3.up, 180); | |
// Change random range for front sections | |
loftLow = -0.35f; | |
loftHigh = 0.15f; | |
} | |
// Nose | |
if (NoseLength > 0) | |
{ | |
spaceship = spaceship.Loft(new OpParams {valueA = .2f, valueB = 0, facesel = FaceSelections.FacingStraightForward}); | |
spaceship = spaceship.FaceSlide(new OpParams{valueA = .12f, facesel = FaceSelections.Existing}); | |
if (NoseVariant) | |
{ | |
spaceship = spaceship.Lace(new OpParams{valueA = NoseSharpness, valueB = NoseLength, facesel = FaceSelections.Existing}); | |
} | |
else | |
{ | |
spaceship = spaceship.Loft(new OpParams{valueA = NoseSharpness, valueB = NoseLength, facesel = FaceSelections.Existing}); | |
} | |
} | |
// Add Panel Ridges to everything | |
spaceship = spaceship.Loft(new OpParams{valueA = 0.1f, valueB = 0.025f}); | |
// Engines | |
spaceship = spaceship.Loft(new OpParams{valueA = Random.Range(.3f, .4f), valueB = Random.Range(-.2f, .2f), facesel = FaceSelections.FacingStraightBackward}); | |
if (EngineVariant) | |
{ | |
var engines = spaceship.Duplicate(); | |
spaceship = spaceship.FaceRemove(new OpParams{facesel = FaceSelections.Existing}); | |
engines = engines.FaceKeep(new OpParams{facesel = FaceSelections.Existing}); | |
engines = engines.Ortho(new OpParams{valueA = 0}); | |
engines = engines.Loft(new OpParams{valueA = Random.Range(0, .25f), valueB = -.5f, facesel = FaceSelections.All}); | |
spaceship.Append(engines); | |
} | |
else | |
{ | |
spaceship = spaceship.Loft(new OpParams{valueA = Random.Range(.5f, .5f), valueB = Random.Range(.2f, .5f), facesel = FaceSelections.Existing}); | |
spaceship = spaceship.Loft(new OpParams{valueA = Random.Range(.1f, .3f), valueB = Random.Range(-.3f, -.7f), facesel = FaceSelections.AllNew}); | |
} | |
wings = wings.Loft(new OpParams{valueA = 0.1f, valueB = 0.025f}); | |
spaceship.Append(wings); | |
var mesh = PolyMeshBuilder.BuildMeshFromConwayPoly(spaceship, false); | |
GetComponent<MeshFilter>().mesh = mesh; | |
GetComponent<MeshRenderer>().material = material; | |
} | |
private ConwayPoly MakeSection(ConwayPoly spaceship) | |
{ | |
if (Random.value < ChanceOfSimpleSegment) | |
{ | |
spaceship = spaceship.Loft(new OpParams{valueA = Random.Range(loftLow, loftHigh), valueB = Random.Range(.2f, .5f), facesel = FaceSelections.FacingStraightForward}); | |
} | |
else | |
{ | |
if (Random.value < ChanceOfLaceSegment) | |
{ | |
spaceship = spaceship.Lace(new OpParams{valueA = Random.Range(loftLow, loftHigh), facesel = FaceSelections.FacingStraightForward, valueB = Random.Range(.2f, .5f)}); | |
} | |
else if (Random.value < ChanceOfTruncateSegment) | |
{ | |
spaceship = spaceship.Truncate(new OpParams{valueA = Random.Range(loftLow, loftHigh), facesel = FaceSelections.FacingForward}); | |
} | |
else | |
{ | |
spaceship = RibbedExtrude(spaceship, Random.Range(2, 7)); | |
} | |
spaceship = MakeWings(spaceship); | |
} | |
if (Random.value < ChanceOfFins) | |
{ | |
spaceship = spaceship.Loft(new OpParams{valueA = Random.Range(.5f, 0), valueB = Random.Range(0.05f, 1.3f), facesel = FaceSelections.AllNew}); | |
} | |
spaceship = spaceship.FaceSlide(new OpParams{valueA = Random.Range(-.3f, .3f), valueB = 0, facesel = FaceSelections.FacingStraightForward}); | |
return spaceship; | |
} | |
private ConwayPoly RibbedExtrude(ConwayPoly poly, int numRibs) | |
{ | |
float translateForwardsPerRib = Random.Range(0.02f, 0.2f); | |
float ribDepth = Random.Range(0.02f, 0.2f); | |
for (int i=0; i<numRibs; i++) | |
{ | |
poly = poly.Loft(new OpParams{valueA = ribDepth, valueB = translateForwardsPerRib * 0.25f, facesel = FaceSelections.FacingStraightForward}); | |
poly = poly.Loft(new OpParams{valueA = 0, valueB = translateForwardsPerRib * 0.5f, facesel = FaceSelections.FacingStraightForward}); | |
poly = poly.Loft(new OpParams{valueA = -ribDepth, valueB = translateForwardsPerRib * 0.25f, facesel = FaceSelections.FacingStraightForward}); | |
poly = poly.Loft(new OpParams{valueA = 0, valueB = translateForwardsPerRib * 0.25f, facesel = FaceSelections.FacingStraightForward}); | |
} | |
return poly; | |
} | |
private ConwayPoly MakeWings(ConwayPoly spaceship) | |
{ | |
if (Random.value < ChanceOfWings) | |
{ | |
Func<FilterParams, bool> sideFaceFilter = p => Math.Abs(p.poly.Faces[p.index].Normal.y) < 180f / numSides; | |
var wingFaces = spaceship.Duplicate(); | |
wingFaces = wingFaces.FaceKeep(new OpParams{facesel = FaceSelections.AllNew}); | |
wingFaces = wingFaces.FaceKeep(new OpParams{filterFunc = sideFaceFilter}); | |
wingFaces = wingFaces.FaceScale(new OpParams{facesel = FaceSelections.All, valueA = Random.Range(0, 0.5f)}); | |
wingFaces = wingFaces.Loft(new OpParams{valueA = Random.Range(0, 1f), valueB = Random.Range(.5f, 2f)}); | |
for (int i=0; i<Random.Range(0, 3); i++) | |
{ | |
wingFaces = wingFaces.Loft(new OpParams{valueA = Random.Range(0, 1f), valueB = Random.Range(.15f, 1.5f), facesel = FaceSelections.Existing}); | |
if (Random.value < 0.5f) | |
{ | |
wingFaces = wingFaces.FaceSlide(new OpParams{valueA = Random.Range(-.5f, .5f), valueB = Random.Range(-1, .25f), facesel = FaceSelections.Existing}); | |
} | |
} | |
spaceship.Append(wingFaces); | |
} | |
return spaceship; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment