//Cube Data // Makes a cube /// <summary> /// Makes a cube with data taken from X,Y,Z coords /// </summary> /// <returns></returns> private Mesh MakeCylinder(int num) { List <Color> colors = new List <Color>(); //Set hue min and Max float hue = Mathf.Lerp(hueMin, hueMax, (num / (float)iterations)); Mesh mesh = MeshTools.MakeCylinder(5); Vector3[] verts = mesh.vertices; for (int i = 0; i < mesh.vertexCount; i++) { float tempHue = hue + (1 / (float)iterations) * verts[i].y; Color color = Color.HSVToRGB(tempHue, 1, 1); colors.Add(color); } mesh.SetColors(colors); return(mesh); }
/// <summary> /// creates a stem, growing from a position /// </summary> /// <param name="number">how long should the stem be</param> /// <param name="meshes">reference to list of meshes</param> /// <param name="pos">where to start the stem</param> /// <param name="rot">rotation of the stem</param> /// <param name="top">whether or not the stem is on top of the creature, used to calculate leaf direction</param> void GrowStem(int number, List <CombineInstance> meshes, Vector3 pos, Quaternion rot, bool top) { CombineInstance inst = new CombineInstance(); inst.mesh = MeshTools.MakeCylinder(5); inst.transform = Matrix4x4.TRS(pos, rot, new Vector3(.2f, number, .2f)); meshes.Add(inst); rot *= Quaternion.Euler(0, 180, 90); if (!top) { rot *= Quaternion.Euler(180, 0, 0); } float x = .1f; while (x < 1) { if (x * 2 < 1) { x = Random.Range(2 * x, 1); } else { break; } pos = inst.transform.MultiplyPoint(Vector3.up * x); float scale = 1 + (1 - x) * 3; GrowLeaf(1, meshes, pos, rot, scale); } }
/// <summary> /// Pieces together a mesh based on a set position, rotation, and iterations. /// </summary> /// <param name="num">The number of iterations that have passed already.</param> /// <param name="meshes">Stores all the meshes this function constructs.</param> /// <param name="pos">The position of the endPoint of the previous stem segment/spawner location.</param> /// <param name="rot">The rotation of the previous stem segment/spawner location</param> private void Grow(int num, List <CombineInstance> meshes, Vector3 pos, Quaternion rot) { if (num <= 0) { return; //stop recursive function } //Adjust randomness for scale values: Vector3 tempStemScaling = (stemScaling * Random.Range(minRandomScaling, maxRandomScaling)) * objectScaling; Vector3 tempLeafScaling = (leafScaling * Random.Range(minRandomScaling, maxRandomScaling)) * objectScaling; //Adjust randomness for leaves: numberOfLeaves = Random.Range(minLeaves, maxLeaves); // Add Stem Mesh: CombineInstance stem = new CombineInstance(); stem.mesh = MeshTools.MakeCylinder(5); AddColorToVertices(stem.mesh, num); stem.transform = Matrix4x4.TRS(pos, rot, tempStemScaling); meshes.Add(stem); // Add Leaves Mesh: for (int i = 1; i <= numberOfLeaves; i++) { CombineInstance leaves = new CombineInstance(); leaves.mesh = MeshTools.MakeCube(); AddColorToVertices(leaves.mesh, num); float rotAmount = 360 / (numberOfLeaves * i); Quaternion leafRot = rot * Quaternion.Euler(leafOffsetAngleX, leafOffsetAngleY * rotAmount, leafOffsetAngleZ); leaves.transform = Matrix4x4.TRS(pos, leafRot, tempLeafScaling); meshes.Add(leaves); } // Count down number of passes: num--; // Get the position of the end of this section: pos = stem.transform.MultiplyPoint(new Vector3(0, 1, 0)); //Generate random angles based on set angle values: float randX = stemAngleX + Random.Range(minRandomAngle, maxRandomAngle); float randY = stemAngleY + Random.Range(minRandomAngle, maxRandomAngle); float randZ = stemAngleZ + Random.Range(minRandomAngle, maxRandomAngle); //Create a Quaternion to change the local transform to the world Vector3.up: Quaternion rot1 = Quaternion.FromToRotation(transform.up, Vector3.up); //Create a Quaternion using the random angles from earlier: Quaternion rot2 = Quaternion.Euler(randX, randY, randZ); //Use a slerp to create a Quaternion between rot1 and rot2, leaning more towards randomness in later segments: Quaternion finalRot = Quaternion.Slerp(rot1, rot2, (num / (float)iterations)); //Grow another segment: Grow(num, meshes, pos, finalRot); }
/// <summary> /// Grow is called to create all the mesh data to add to the spawner's mesh filter. /// </summary> /// <param name="meshes">A collection of meshes to push to the object.</param> /// <param name="pos">The x,y,z position of the object.</param> /// <param name="rot">The rotation of the object.</param> void Grow(List <CombineInstance> meshes, Vector3 pos, Quaternion rot) { //Set randomized values: numberOfArms = Random.Range(minArms, maxArms); float tempRandomScaling = Random.Range(minRandomScaling, maxRandomScaling); //Set random values to adjust arm width/height: float tempRandomArmScaleX = Random.Range(minRandomScaling, maxRandomScaling); float tempRandomArmScaleZ = Random.Range(minRandomScaling, maxRandomScaling); //Create temporary scaling for center and arms: Vector3 tempCenterScale = (centerScale * tempRandomScaling) * objectScaling; Vector3 tempArmScale = (armScale * tempRandomScaling) * objectScaling; //Add arm length & width tempArmScale.x += Random.Range(minArmWidth, maxArmWidth); tempArmScale.z += Random.Range(minArmLength, maxArmLength); //Add randomness to arm width/height: tempArmScale.x *= tempRandomArmScaleX; tempArmScale.z *= tempRandomArmScaleZ; //Make center of the sea star: CombineInstance center = new CombineInstance(); center.mesh = MeshTools.MakeCylinder(8); AddColorToVertices(center.mesh); //Adjust center values: Quaternion adjustRot = Quaternion.Euler(0, 15, 0) * rot; Vector3 adjustPos = pos; adjustPos.y += centerRiseAmount; //Set center transform: center.transform = Matrix4x4.TRS(adjustPos, adjustRot, tempCenterScale); meshes.Add(center); //Make arms of sea star: for (int i = 0; i < numberOfArms; i++) { CombineInstance arm = new CombineInstance(); arm.mesh = MeshTools.MakeTaperCube(taperAmount); AddColorToVertices(arm.mesh); float rotDegrees = (360 / numberOfArms) * i; float rotRadians = rotDegrees * (Mathf.PI / 180.0f); //Build out arm in that direction: float armX = Mathf.Sin(rotRadians) * 1f; float armZ = Mathf.Cos(rotRadians) * 1f; Vector3 armPos = pos + new Vector3(armX, 0.5f, armZ); Quaternion armRot = Quaternion.Euler(0, rotDegrees, 0) * rot; // TODO: adjust arm position by scale arm.transform = Matrix4x4.TRS(armPos, armRot, tempArmScale); meshes.Add(arm); } }
/// <summary> /// Primary recursive function used to grow segments of the body, and attached stems /// </summary> /// <param name="firstSegment">special modifier for the 'head' or first segment of the body</param> /// <param name="number">number of segments to grow, counts down to 0</param> /// <param name="meshes">reference to list of combine instances</param> /// <param name="pos">where to spawn the segment</param> /// <param name="rot">rotation of the segment</param> /// <param name="bodyScale">how much to scale each segment</param> /// <param name="switchDirection">used to change direction the segment grows in</param> /// <param name="stems">reference to list of combine instances for stems and leaves</param> void GrowBody(bool firstSegment, int number, List <CombineInstance> meshes, Vector3 pos, Quaternion rot, float bodyScale, bool switchDirection, List <CombineInstance> stems) { if (number <= 0) { return; } CombineInstance inst = new CombineInstance(); inst.mesh = MeshTools.MakeCylinder(5); inst.transform = Matrix4x4.TRS(pos, rot, new Vector3(bodyWidth, bodyScale, bodyWidth) * scale); meshes.Add(inst); //scale //rotation ; Vector3 stemRotation = new Vector3(); //calculate which way to grow the next segment if (switchDirection) {//top side rot = Quaternion.Euler(-90, 0, 0); if (!firstSegment) { stemRotation.Set(-45, 0, 0); } } else {//bottom side rot = Quaternion.Euler(-180, 0, 0); if (!firstSegment) { stemRotation.Set(135, 0, 0); } } //don't spawn stems from the first segment if (!firstSegment) { //random chance for 2 stems if (Random.Range(0, 100) < chanceForMoreStems) { stemRotation = new Vector3(stemRotation.x, stemRotation.y, -45); GrowStem(stemSize, stems, pos, Quaternion.Euler(stemRotation), switchDirection); stemRotation = new Vector3(stemRotation.x, stemRotation.y, 45); } GrowStem(stemSize, stems, pos, Quaternion.Euler(stemRotation), switchDirection); } switchDirection = !switchDirection; pos = inst.transform.MultiplyPoint(new Vector3(0, 1, 0)); //de increment iterations number--; //grow another segment GrowBody(false, number, meshes, pos, rot, bodyScale, switchDirection, stems); }