Skip to content

Instantly share code, notes, and snippets.

@andrewzimmer906
Created January 21, 2017 15:49
Show Gist options
  • Save andrewzimmer906/3411d7f0903769fe0b1ab6706aca78c1 to your computer and use it in GitHub Desktop.
Save andrewzimmer906/3411d7f0903769fe0b1ab6706aca78c1 to your computer and use it in GitHub Desktop.
3D Model Generation for a Cloud Object
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
enum Direction {Up, Down, West, East, North, South};
public class Cloud : MonoBehaviour {
public int cloudSizeX = 2;
public int cloudSizeY = 2;
public int cloudSizeZ = 2;
private float centerX;
private float centerY;
private float centerZ;
private Mesh mesh;
private List<Vector3> verticies = new List<Vector3>();
private List<int> triangles = new List<int>();
private int squareCount;
public int maxTurbulence = 20;
public float turbulenceHeight = 1.2f;
public float turbulenceScale = 1f;
public float turbulenceSpeed = 0.05f;
public float startSeed = 0f;
private int[,,] turbulenceData;
public bool update = false;
void Start() {
mesh = GetComponent<MeshFilter> ().mesh;
CreateNoise ();
GenerateCloud ();
}
void CreateNoise() {
// we use plus 1 to account for the extra vertex
turbulenceData = new int[cloudSizeX + 1,cloudSizeY + 1, cloudSizeZ + 1];
for (int x = 0; x <= cloudSizeX; x++) {
for (int y = 0; y <= cloudSizeY; y++) {
for (int z = 0; z <= cloudSizeZ; z++) {
turbulenceData [x, y, z] = PerlinNoise (x, y, z, turbulenceScale, maxTurbulence, 0);
}
}
}
}
void GenerateCloud() {
centerX = (float)cloudSizeX / 2f;
centerY = (float)cloudSizeY / 2f;
centerZ = (float)cloudSizeZ / 2f;
for (int x = 0; x < cloudSizeX; x++) {
for (int y = 0; y < cloudSizeY; y++) {
for (int z = 0; z < cloudSizeZ; z++) {
if (x == 0) {
AddSquare (x, y, z, Direction.West);
} else if (x == cloudSizeX - 1) {
AddSquare (x, y, z, Direction.East);
}
if (y == 0) {
AddSquare (x, y, z, Direction.Down);
} else if (y == cloudSizeY - 1) {
AddSquare (x, y, z, Direction.Up);
}
if (z == 0) {
AddSquare (x, y, z, Direction.South);
} else if (z == cloudSizeZ - 1) {
AddSquare (x, y, z, Direction.North);
}
}
}
}
UpdateMesh ();
}
/* -- Geometry -- */
void AddSquare (int x, int y, int z, Direction direction) {
if (direction == Direction.Up ||
direction == Direction.Down) {
AddFaceForTopBottom (x, y, z, direction);
} else if (direction == Direction.North ||
direction == Direction.South) {
AddFaceForNorthSouth (x, y, z, direction);
} else if (direction == Direction.West ||
direction == Direction.East) {
AddFaceForWestEast (x, y, z, direction);
}
squareCount++; // Add this line
}
void AddFaceForTopBottom(int x, int y, int z, Direction direction) {
if (direction == Direction.Up) {
y += 1;
}
verticies.Add (VertexForIndex (x, y , z + 1));
verticies.Add (VertexForIndex (x + 1, y , z + 1));
verticies.Add (VertexForIndex (x + 1, y, z));
verticies.Add (VertexForIndex (x, y, z));
if (direction == Direction.Up) {
AddLatestTriangles (true);
} else {
AddLatestTriangles (false);
}
}
void AddFaceForWestEast(int x, int y, int z, Direction direction) {
if (direction == Direction.East) {
x += 1;
}
verticies.Add (VertexForIndex (x, y + 1, z));
verticies.Add (VertexForIndex (x, y + 1, z + 1));
verticies.Add (VertexForIndex (x, y, z + 1));
verticies.Add (VertexForIndex (x, y, z));
if (direction == Direction.East) {
AddLatestTriangles (true);
} else {
AddLatestTriangles (false);
}
}
void AddFaceForNorthSouth(int x, int y, int z, Direction direction) {
if (direction == Direction.North) {
z += 1;
}
verticies.Add (VertexForIndex (x, y + 1, z));
verticies.Add (VertexForIndex (x + 1, y + 1, z));
verticies.Add (VertexForIndex (x + 1, y, z));
verticies.Add (VertexForIndex (x, y, z));
if (direction == Direction.South) {
AddLatestTriangles (true);
} else {
AddLatestTriangles (false);
}
}
Vector3 VertexForIndex(int x, int y, int z) {
return new Vector3 (
x - centerX + turbulenceAtVertex(x, y, z),
y - centerY + turbulenceAtVertex(x, y, z),
z - centerZ + turbulenceAtVertex(x, y, z));
}
void AddLatestTriangles(bool clockwise) {
if (clockwise) {
triangles.Add(squareCount * 4 ); // 1
triangles.Add(squareCount * 4 + 1 ); // 2
triangles.Add(squareCount * 4 + 2 ); // 3
triangles.Add(squareCount * 4 ); // 1
triangles.Add(squareCount * 4 + 2 ); // 3
triangles.Add(squareCount * 4 + 3 ); // 4
} else {
triangles.Add(squareCount * 4 + 2 ); // 3
triangles.Add(squareCount * 4 + 1 ); // 2
triangles.Add(squareCount * 4 ); // 1
triangles.Add(squareCount * 4 + 3 ); // 4
triangles.Add(squareCount * 4 + 2 ); // 3
triangles.Add(squareCount * 4 ); // 1
}
}
float turbulenceAtVertex(int x, int y, int z) {
int turbulenceDataAtVertex = turbulenceData [x, y, z];
float tav = ((float)turbulenceDataAtVertex / (float)maxTurbulence) * turbulenceHeight;
return tav;
}
/* -- Updates -- */
void UpdateMesh () {
mesh.Clear ();
mesh.vertices = verticies.ToArray();
mesh.triangles = triangles.ToArray();
mesh.Optimize ();
mesh.RecalculateNormals ();
// Reset back to factory
verticies.Clear();
triangles.Clear();
squareCount = 0;
}
void FixedUpdate() {
CreateNoise ();
GenerateCloud ();
transform.position = new Vector3 (transform.position.x + 0.005f, transform.position.y, transform.position.z + .005f);
}
/* -- Noise Creation -- */
int PerlinNoise(int x, int y, int z, float scale, float height, float power){
float rValue;
rValue = Noise.Noise.GetNoise (((double)x) / scale + (Time.timeSinceLevelLoad * turbulenceSpeed) + startSeed,
((double)y)/ scale + (Time.timeSinceLevelLoad * turbulenceSpeed) + startSeed,
((double)z)/ scale + (Time.timeSinceLevelLoad * turbulenceSpeed) + startSeed) - 0.5f;
rValue *= height;
if(power != 0){
rValue=Mathf.Pow( rValue, power);
}
return (int) rValue;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment