├── Assets ├── Scenes │ ├── city_scene.unity │ └── main_scene.unity ├── Resources │ └── Textures │ │ ├── Door │ │ ├── tex_door_1.png │ │ ├── tex_door_2.png │ │ ├── tex_door_3.png │ │ ├── tex_door_4.png │ │ ├── tex_door_5.png │ │ ├── tex_door_6.png │ │ ├── tex_door_7.png │ │ ├── tex_door_8.png │ │ └── tex_door_9.png │ │ ├── Roof │ │ ├── tex_roof_1.png │ │ ├── tex_roof_10.png │ │ ├── tex_roof_2.png │ │ ├── tex_roof_3.png │ │ ├── tex_roof_4.png │ │ ├── tex_roof_6.png │ │ ├── tex_roof_7.png │ │ ├── tex_roof_8.png │ │ └── tex_roof_9.png │ │ ├── Shutter │ │ ├── tex_shutter_1.png │ │ ├── tex_shutter_2.png │ │ ├── tex_shutter_3.png │ │ ├── tex_shutter_4.png │ │ ├── tex_shutter_5.png │ │ ├── tex_shutter_6.png │ │ └── tex_shutter_7.png │ │ ├── RoofBase │ │ ├── tex_roof_base_1.png │ │ ├── tex_roof_base_2.png │ │ ├── tex_roof_base_3.png │ │ ├── tex_roof_base_4.png │ │ └── tex_roof_base_5.png │ │ ├── CompDecor │ │ ├── tex_comp_decor_1.png │ │ ├── tex_comp_decor_2.png │ │ ├── tex_comp_decor_3.png │ │ ├── tex_comp_decor_4.png │ │ ├── tex_comp_decor_5.png │ │ ├── tex_comp_decor_6.png │ │ ├── tex_comp_decor_7.png │ │ ├── tex_comp_decor_8.png │ │ └── tex_comp_decor_9.png │ │ ├── RoofDecor │ │ ├── tex_roof_decor_1.png │ │ ├── tex_roof_decor_2.png │ │ ├── tex_roof_decor_3.png │ │ └── tex_roof_decor_4.png │ │ └── CompDecorSimple │ │ └── tex_comp_decor_simple_1.png ├── Standard Assets │ ├── Shutter │ │ ├── ShutterSide.cs │ │ └── Shuter.cs │ ├── Roof │ │ ├── RoofType.cs │ │ ├── Roof.cs │ │ ├── SinglePeakRoof.cs │ │ ├── RoofBase.cs │ │ ├── FlatRoof.cs │ │ ├── RoofDecoration.cs │ │ └── DoublePeakRoof.cs │ ├── General │ │ ├── BuildMode.cs │ │ ├── ProceduralObject.cs │ │ ├── ComponentCoordinate.cs │ │ ├── TextureLine.cs │ │ ├── FaceComponent.cs │ │ ├── ComponentBody.cs │ │ ├── ProceduralTexture.cs │ │ ├── ComponentFrame.cs │ │ ├── Util.cs │ │ └── DrawableObject.cs │ ├── Door │ │ ├── DoorBody.cs │ │ └── Door.cs │ ├── Window │ │ ├── WindowBody.cs │ │ ├── Window.cs │ │ └── WindowDecor.cs │ ├── Balcony │ │ ├── BalconyBody.cs │ │ ├── BalconyFrame.cs │ │ ├── BalconyFloor.cs │ │ ├── Balcony.cs │ │ └── BalconyRail.cs │ ├── Interface │ │ ├── ICombinable.cs │ │ └── IDrawable.cs │ ├── City │ │ ├── Road.cs │ │ ├── Sidewalk.cs │ │ ├── Edge.cs │ │ ├── BuildingLot.cs │ │ └── Block.cs │ ├── Managers │ │ ├── ColorManager.cs │ │ ├── CityMapManager.cs │ │ ├── BuildingManager.cs │ │ ├── MaterialManager.cs │ │ └── TextureManager.cs │ ├── Building │ │ ├── Building.cs │ │ ├── BuildingMesh.cs │ │ └── Face.cs │ └── Editor │ │ └── Builder.cs └── Scripts │ ├── BuildingController.cs │ ├── CityMapController.cs │ └── CameraController.cs ├── ProjectSettings ├── AudioManager.asset ├── InputManager.asset ├── TagManager.asset ├── TimeManager.asset ├── EditorSettings.asset ├── NavMeshLayers.asset ├── NetworkManager.asset ├── DynamicsManager.asset ├── GraphicsSettings.asset ├── Physics2DSettings.asset ├── ProjectSettings.asset ├── QualitySettings.asset └── EditorBuildSettings.asset ├── README.md ├── MIT-LICENSE └── .gitignore /Assets/Scenes/city_scene.unity: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkaretsos/ProceduralBuildings/HEAD/Assets/Scenes/city_scene.unity -------------------------------------------------------------------------------- /Assets/Scenes/main_scene.unity: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkaretsos/ProceduralBuildings/HEAD/Assets/Scenes/main_scene.unity -------------------------------------------------------------------------------- /ProjectSettings/AudioManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkaretsos/ProceduralBuildings/HEAD/ProjectSettings/AudioManager.asset -------------------------------------------------------------------------------- /ProjectSettings/InputManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkaretsos/ProceduralBuildings/HEAD/ProjectSettings/InputManager.asset -------------------------------------------------------------------------------- /ProjectSettings/TagManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkaretsos/ProceduralBuildings/HEAD/ProjectSettings/TagManager.asset -------------------------------------------------------------------------------- /ProjectSettings/TimeManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkaretsos/ProceduralBuildings/HEAD/ProjectSettings/TimeManager.asset -------------------------------------------------------------------------------- /ProjectSettings/EditorSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkaretsos/ProceduralBuildings/HEAD/ProjectSettings/EditorSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/NavMeshLayers.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkaretsos/ProceduralBuildings/HEAD/ProjectSettings/NavMeshLayers.asset -------------------------------------------------------------------------------- /ProjectSettings/NetworkManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkaretsos/ProceduralBuildings/HEAD/ProjectSettings/NetworkManager.asset -------------------------------------------------------------------------------- /ProjectSettings/DynamicsManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkaretsos/ProceduralBuildings/HEAD/ProjectSettings/DynamicsManager.asset -------------------------------------------------------------------------------- /ProjectSettings/GraphicsSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkaretsos/ProceduralBuildings/HEAD/ProjectSettings/GraphicsSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/Physics2DSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkaretsos/ProceduralBuildings/HEAD/ProjectSettings/Physics2DSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/ProjectSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkaretsos/ProceduralBuildings/HEAD/ProjectSettings/ProjectSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/QualitySettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkaretsos/ProceduralBuildings/HEAD/ProjectSettings/QualitySettings.asset -------------------------------------------------------------------------------- /ProjectSettings/EditorBuildSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkaretsos/ProceduralBuildings/HEAD/ProjectSettings/EditorBuildSettings.asset -------------------------------------------------------------------------------- /Assets/Resources/Textures/Door/tex_door_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkaretsos/ProceduralBuildings/HEAD/Assets/Resources/Textures/Door/tex_door_1.png -------------------------------------------------------------------------------- /Assets/Resources/Textures/Door/tex_door_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkaretsos/ProceduralBuildings/HEAD/Assets/Resources/Textures/Door/tex_door_2.png -------------------------------------------------------------------------------- /Assets/Resources/Textures/Door/tex_door_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkaretsos/ProceduralBuildings/HEAD/Assets/Resources/Textures/Door/tex_door_3.png -------------------------------------------------------------------------------- /Assets/Resources/Textures/Door/tex_door_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkaretsos/ProceduralBuildings/HEAD/Assets/Resources/Textures/Door/tex_door_4.png -------------------------------------------------------------------------------- /Assets/Resources/Textures/Door/tex_door_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkaretsos/ProceduralBuildings/HEAD/Assets/Resources/Textures/Door/tex_door_5.png -------------------------------------------------------------------------------- /Assets/Resources/Textures/Door/tex_door_6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkaretsos/ProceduralBuildings/HEAD/Assets/Resources/Textures/Door/tex_door_6.png -------------------------------------------------------------------------------- /Assets/Resources/Textures/Door/tex_door_7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkaretsos/ProceduralBuildings/HEAD/Assets/Resources/Textures/Door/tex_door_7.png -------------------------------------------------------------------------------- /Assets/Resources/Textures/Door/tex_door_8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkaretsos/ProceduralBuildings/HEAD/Assets/Resources/Textures/Door/tex_door_8.png -------------------------------------------------------------------------------- /Assets/Resources/Textures/Door/tex_door_9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkaretsos/ProceduralBuildings/HEAD/Assets/Resources/Textures/Door/tex_door_9.png -------------------------------------------------------------------------------- /Assets/Resources/Textures/Roof/tex_roof_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkaretsos/ProceduralBuildings/HEAD/Assets/Resources/Textures/Roof/tex_roof_1.png -------------------------------------------------------------------------------- /Assets/Resources/Textures/Roof/tex_roof_10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkaretsos/ProceduralBuildings/HEAD/Assets/Resources/Textures/Roof/tex_roof_10.png -------------------------------------------------------------------------------- /Assets/Resources/Textures/Roof/tex_roof_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkaretsos/ProceduralBuildings/HEAD/Assets/Resources/Textures/Roof/tex_roof_2.png -------------------------------------------------------------------------------- /Assets/Resources/Textures/Roof/tex_roof_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkaretsos/ProceduralBuildings/HEAD/Assets/Resources/Textures/Roof/tex_roof_3.png -------------------------------------------------------------------------------- /Assets/Resources/Textures/Roof/tex_roof_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkaretsos/ProceduralBuildings/HEAD/Assets/Resources/Textures/Roof/tex_roof_4.png -------------------------------------------------------------------------------- /Assets/Resources/Textures/Roof/tex_roof_6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkaretsos/ProceduralBuildings/HEAD/Assets/Resources/Textures/Roof/tex_roof_6.png -------------------------------------------------------------------------------- /Assets/Resources/Textures/Roof/tex_roof_7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkaretsos/ProceduralBuildings/HEAD/Assets/Resources/Textures/Roof/tex_roof_7.png -------------------------------------------------------------------------------- /Assets/Resources/Textures/Roof/tex_roof_8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkaretsos/ProceduralBuildings/HEAD/Assets/Resources/Textures/Roof/tex_roof_8.png -------------------------------------------------------------------------------- /Assets/Resources/Textures/Roof/tex_roof_9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkaretsos/ProceduralBuildings/HEAD/Assets/Resources/Textures/Roof/tex_roof_9.png -------------------------------------------------------------------------------- /Assets/Resources/Textures/Shutter/tex_shutter_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkaretsos/ProceduralBuildings/HEAD/Assets/Resources/Textures/Shutter/tex_shutter_1.png -------------------------------------------------------------------------------- /Assets/Resources/Textures/Shutter/tex_shutter_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkaretsos/ProceduralBuildings/HEAD/Assets/Resources/Textures/Shutter/tex_shutter_2.png -------------------------------------------------------------------------------- /Assets/Resources/Textures/Shutter/tex_shutter_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkaretsos/ProceduralBuildings/HEAD/Assets/Resources/Textures/Shutter/tex_shutter_3.png -------------------------------------------------------------------------------- /Assets/Resources/Textures/Shutter/tex_shutter_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkaretsos/ProceduralBuildings/HEAD/Assets/Resources/Textures/Shutter/tex_shutter_4.png -------------------------------------------------------------------------------- /Assets/Resources/Textures/Shutter/tex_shutter_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkaretsos/ProceduralBuildings/HEAD/Assets/Resources/Textures/Shutter/tex_shutter_5.png -------------------------------------------------------------------------------- /Assets/Resources/Textures/Shutter/tex_shutter_6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkaretsos/ProceduralBuildings/HEAD/Assets/Resources/Textures/Shutter/tex_shutter_6.png -------------------------------------------------------------------------------- /Assets/Resources/Textures/Shutter/tex_shutter_7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkaretsos/ProceduralBuildings/HEAD/Assets/Resources/Textures/Shutter/tex_shutter_7.png -------------------------------------------------------------------------------- /Assets/Resources/Textures/RoofBase/tex_roof_base_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkaretsos/ProceduralBuildings/HEAD/Assets/Resources/Textures/RoofBase/tex_roof_base_1.png -------------------------------------------------------------------------------- /Assets/Resources/Textures/RoofBase/tex_roof_base_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkaretsos/ProceduralBuildings/HEAD/Assets/Resources/Textures/RoofBase/tex_roof_base_2.png -------------------------------------------------------------------------------- /Assets/Resources/Textures/RoofBase/tex_roof_base_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkaretsos/ProceduralBuildings/HEAD/Assets/Resources/Textures/RoofBase/tex_roof_base_3.png -------------------------------------------------------------------------------- /Assets/Resources/Textures/RoofBase/tex_roof_base_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkaretsos/ProceduralBuildings/HEAD/Assets/Resources/Textures/RoofBase/tex_roof_base_4.png -------------------------------------------------------------------------------- /Assets/Resources/Textures/RoofBase/tex_roof_base_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkaretsos/ProceduralBuildings/HEAD/Assets/Resources/Textures/RoofBase/tex_roof_base_5.png -------------------------------------------------------------------------------- /Assets/Resources/Textures/CompDecor/tex_comp_decor_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkaretsos/ProceduralBuildings/HEAD/Assets/Resources/Textures/CompDecor/tex_comp_decor_1.png -------------------------------------------------------------------------------- /Assets/Resources/Textures/CompDecor/tex_comp_decor_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkaretsos/ProceduralBuildings/HEAD/Assets/Resources/Textures/CompDecor/tex_comp_decor_2.png -------------------------------------------------------------------------------- /Assets/Resources/Textures/CompDecor/tex_comp_decor_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkaretsos/ProceduralBuildings/HEAD/Assets/Resources/Textures/CompDecor/tex_comp_decor_3.png -------------------------------------------------------------------------------- /Assets/Resources/Textures/CompDecor/tex_comp_decor_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkaretsos/ProceduralBuildings/HEAD/Assets/Resources/Textures/CompDecor/tex_comp_decor_4.png -------------------------------------------------------------------------------- /Assets/Resources/Textures/CompDecor/tex_comp_decor_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkaretsos/ProceduralBuildings/HEAD/Assets/Resources/Textures/CompDecor/tex_comp_decor_5.png -------------------------------------------------------------------------------- /Assets/Resources/Textures/CompDecor/tex_comp_decor_6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkaretsos/ProceduralBuildings/HEAD/Assets/Resources/Textures/CompDecor/tex_comp_decor_6.png -------------------------------------------------------------------------------- /Assets/Resources/Textures/CompDecor/tex_comp_decor_7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkaretsos/ProceduralBuildings/HEAD/Assets/Resources/Textures/CompDecor/tex_comp_decor_7.png -------------------------------------------------------------------------------- /Assets/Resources/Textures/CompDecor/tex_comp_decor_8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkaretsos/ProceduralBuildings/HEAD/Assets/Resources/Textures/CompDecor/tex_comp_decor_8.png -------------------------------------------------------------------------------- /Assets/Resources/Textures/CompDecor/tex_comp_decor_9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkaretsos/ProceduralBuildings/HEAD/Assets/Resources/Textures/CompDecor/tex_comp_decor_9.png -------------------------------------------------------------------------------- /Assets/Resources/Textures/RoofDecor/tex_roof_decor_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkaretsos/ProceduralBuildings/HEAD/Assets/Resources/Textures/RoofDecor/tex_roof_decor_1.png -------------------------------------------------------------------------------- /Assets/Resources/Textures/RoofDecor/tex_roof_decor_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkaretsos/ProceduralBuildings/HEAD/Assets/Resources/Textures/RoofDecor/tex_roof_decor_2.png -------------------------------------------------------------------------------- /Assets/Resources/Textures/RoofDecor/tex_roof_decor_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkaretsos/ProceduralBuildings/HEAD/Assets/Resources/Textures/RoofDecor/tex_roof_decor_3.png -------------------------------------------------------------------------------- /Assets/Resources/Textures/RoofDecor/tex_roof_decor_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkaretsos/ProceduralBuildings/HEAD/Assets/Resources/Textures/RoofDecor/tex_roof_decor_4.png -------------------------------------------------------------------------------- /Assets/Standard Assets/Shutter/ShutterSide.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace Thesis { 3 | 4 | public enum ShutterSide 5 | { 6 | Left, 7 | Right 8 | } 9 | 10 | } // namespace Thesis 11 | -------------------------------------------------------------------------------- /Assets/Standard Assets/Roof/RoofType.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace Thesis { 3 | 4 | public enum RoofType 5 | { 6 | Flat, 7 | SinglePeak, 8 | DoublePeak 9 | } 10 | 11 | } // namespace Thesis -------------------------------------------------------------------------------- /Assets/Resources/Textures/CompDecorSimple/tex_comp_decor_simple_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkaretsos/ProceduralBuildings/HEAD/Assets/Resources/Textures/CompDecorSimple/tex_comp_decor_simple_1.png -------------------------------------------------------------------------------- /Assets/Standard Assets/General/BuildMode.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace Thesis { 3 | 4 | public enum BuildMode 5 | { 6 | Many, 7 | Two, 8 | Three, 9 | Four, 10 | Five 11 | } 12 | 13 | } // namespace Thesis -------------------------------------------------------------------------------- /Assets/Standard Assets/General/ProceduralObject.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace Thesis { 3 | 4 | public abstract class ProceduralObject 5 | { 6 | public UnityEngine.GameObject gameObject; 7 | } 8 | 9 | } // namespace Thesis 10 | -------------------------------------------------------------------------------- /Assets/Standard Assets/Door/DoorBody.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace Thesis { 3 | 4 | public class DoorBody : ComponentBody 5 | { 6 | public DoorBody (Door parent) 7 | : base(parent) 8 | { } 9 | } 10 | 11 | } // namespace Thesis -------------------------------------------------------------------------------- /Assets/Standard Assets/Window/WindowBody.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace Thesis { 3 | 4 | public class WindowBody : ComponentBody 5 | { 6 | public WindowBody (Window parent) 7 | : base(parent) 8 | { } 9 | } 10 | 11 | } // namespace Thesis -------------------------------------------------------------------------------- /Assets/Standard Assets/Balcony/BalconyBody.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace Thesis { 3 | 4 | public class BalconyBody : ComponentBody 5 | { 6 | public BalconyBody (Balcony parent) 7 | : base(parent) 8 | { } 9 | } 10 | 11 | } // namespace Thesis -------------------------------------------------------------------------------- /Assets/Standard Assets/General/ComponentCoordinate.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace Thesis { 3 | 4 | public struct ComponentCoordinate 5 | { 6 | public int floor; 7 | 8 | public int component; 9 | 10 | public ComponentCoordinate (int floor, int component) 11 | { 12 | this.floor = floor; 13 | this.component = component; 14 | } 15 | } 16 | 17 | } // namespace Thesis -------------------------------------------------------------------------------- /Assets/Standard Assets/Balcony/BalconyFrame.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace Thesis { 3 | 4 | public class BalconyFrame : ComponentFrame 5 | { 6 | /*************** FIELDS ***************/ 7 | 8 | public float width = 0.1f; 9 | 10 | /*************** CONSTRUCTORS ***************/ 11 | 12 | public BalconyFrame (Balcony parent) 13 | : base(parent) 14 | { } 15 | } 16 | 17 | } // namespace Thesis -------------------------------------------------------------------------------- /Assets/Standard Assets/Interface/ICombinable.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace Thesis { 3 | namespace Interface { 4 | 5 | public interface ICombinable 6 | { 7 | UnityEngine.GameObject gameObject { get; } 8 | 9 | UnityEngine.MeshFilter meshFilter { get; } 10 | 11 | UnityEngine.Material material { get; } 12 | 13 | UnityEngine.Mesh mesh { get; } 14 | } 15 | 16 | } // namespace Interface 17 | } // namespace Thesis -------------------------------------------------------------------------------- /Assets/Standard Assets/Interface/IDrawable.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace Thesis { 3 | namespace Interface { 4 | 5 | public interface IDrawable : ICombinable 6 | { 7 | UnityEngine.Vector3[] vertices { get; } 8 | 9 | int[] triangles { get; } 10 | 11 | void FindVertices (); 12 | 13 | void FindTriangles (); 14 | 15 | void Draw (); 16 | 17 | void Destroy (); 18 | } 19 | 20 | } // namespace Interface 21 | } // namespace Thesis -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | This is my thesis project, in which I try to reconstruct a part of the city of 3 | Athens (Greece) procedurally. 4 | 5 | ## Video 6 | http://youtu.be/dSGm_Tw1GA8 7 | 8 | ## Keybindings 9 | B - create buildings
10 | R - recreate the map (destroys the buildings as well)
11 | G - toggle the drawing of gizmos
12 | 1 - 5 - toggle the drawing of different gizmos (different colors)
13 | -------------------------------------------------------------------------------- /Assets/Standard Assets/General/TextureLine.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace Thesis { 4 | 5 | public struct TextureLine 6 | { 7 | public Vector2 start; 8 | 9 | public Vector2 end; 10 | 11 | public Color color; 12 | 13 | public int thickness; 14 | 15 | public TextureLine (Vector2 start, Vector2 end, Color color, int thickness) 16 | { 17 | this.start = start; 18 | this.end = end; 19 | this.color = color; 20 | this.thickness = thickness; 21 | } 22 | 23 | public TextureLine (int x1, int y1, int x2, int y2, Color color, int thickness) 24 | { 25 | this.start = new Vector2(x1, y1); 26 | this.end = new Vector2(x2, y2); 27 | this.color = color; 28 | this.thickness = thickness; 29 | } 30 | } 31 | 32 | } // namespace Thesis -------------------------------------------------------------------------------- /Assets/Scripts/BuildingController.cs: -------------------------------------------------------------------------------- 1 | using Thesis; 2 | using UnityEngine; 3 | 4 | public class BuildingController : MonoBehaviour 5 | { 6 | void Update () 7 | { 8 | if (Input.GetKeyUp(KeyCode.F5)) 9 | { 10 | BuildingManager.Instance.DestroyBuildings(); 11 | BuildingManager.Instance.CreateNeoclassical(BuildMode.Two); 12 | } 13 | 14 | if (Input.GetKeyUp(KeyCode.F6)) 15 | { 16 | BuildingManager.Instance.DestroyBuildings(); 17 | BuildingManager.Instance.CreateNeoclassical(BuildMode.Three); 18 | } 19 | 20 | if (Input.GetKeyUp(KeyCode.F7)) 21 | { 22 | BuildingManager.Instance.DestroyBuildings(); 23 | BuildingManager.Instance.CreateNeoclassical(BuildMode.Four); 24 | } 25 | 26 | if (Input.GetKeyUp(KeyCode.F8)) 27 | { 28 | BuildingManager.Instance.DestroyBuildings(); 29 | BuildingManager.Instance.CreateNeoclassical(BuildMode.Five); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Assets/Standard Assets/Roof/Roof.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace Thesis { 4 | 5 | public class Roof : DrawableObject 6 | { 7 | public readonly BuildingMesh parentMesh; 8 | 9 | public RoofDecoration decor; 10 | 11 | public float width; 12 | 13 | public float height; 14 | 15 | public Roof (BuildingMesh parent) 16 | { 17 | parentMesh = parent; 18 | decor = null; 19 | } 20 | 21 | public override void Draw() 22 | { 23 | base.Draw(); 24 | 25 | gameObject.transform.parent = parentMesh.parent.gameObject.transform; 26 | gameObject.transform.position = parentMesh.meshOrigin; 27 | 28 | if (decor != null) 29 | { 30 | decor.FindVertices(); 31 | decor.FindTriangles(); 32 | decor.Draw(); 33 | } 34 | } 35 | 36 | public override void Destroy() 37 | { 38 | base.Destroy(); 39 | 40 | if (decor != null) 41 | decor.Destroy(); 42 | } 43 | } 44 | 45 | } // namespace Thesis -------------------------------------------------------------------------------- /Assets/Standard Assets/General/FaceComponent.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace Thesis { 4 | 5 | public class FaceComponent : DrawableObject 6 | { 7 | /*************** FIELDS ***************/ 8 | 9 | public readonly Face parentFace; 10 | 11 | public readonly ComponentCoordinate position; 12 | 13 | public float height; 14 | 15 | public float depth; 16 | 17 | public float width; 18 | 19 | public ComponentFrame frame; 20 | 21 | public ComponentBody body; 22 | 23 | public BuildingMesh parentBuilding 24 | { 25 | get { return parentFace.parentBuilding; } 26 | } 27 | 28 | public Vector3 normal 29 | { 30 | get { return parentFace.normal; } 31 | } 32 | 33 | /*************** CONSTRUCTORS ***************/ 34 | 35 | public FaceComponent (Face parent, ComponentCoordinate position) 36 | { 37 | parentFace = parent; 38 | this.position = position; 39 | } 40 | 41 | public override void Destroy() 42 | { 43 | base.Destroy(); 44 | 45 | frame.Destroy(); 46 | body.Destroy(); 47 | } 48 | } 49 | 50 | } // namespace Thesis -------------------------------------------------------------------------------- /MIT-LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 Thanasis Karetsos 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /Assets/Standard Assets/City/Road.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using UnityEngine; 3 | 4 | namespace Thesis { 5 | 6 | public sealed class Road : DrawableObject 7 | { 8 | public Road (Block parent) 9 | { 10 | boundaries = new Vector3[8]; 11 | for (int i = 0; i < 4; ++i) 12 | { 13 | boundaries[i] = parent.edges[i].start; 14 | boundaries[i + 4] = parent.sidewalkVerts[i]; 15 | } 16 | } 17 | 18 | public override void FindVertices() 19 | { 20 | vertices = boundaries; 21 | } 22 | 23 | public override void FindTriangles() 24 | { 25 | triangles = new int[24]; 26 | int i = 0; 27 | 28 | triangles[i++] = 0; 29 | triangles[i++] = 1; 30 | triangles[i++] = 5; 31 | 32 | triangles[i++] = 0; 33 | triangles[i++] = 5; 34 | triangles[i++] = 4; 35 | 36 | triangles[i++] = 1; 37 | triangles[i++] = 2; 38 | triangles[i++] = 6; 39 | 40 | triangles[i++] = 1; 41 | triangles[i++] = 6; 42 | triangles[i++] = 5; 43 | 44 | triangles[i++] = 2; 45 | triangles[i++] = 3; 46 | triangles[i++] = 7; 47 | 48 | triangles[i++] = 2; 49 | triangles[i++] = 7; 50 | triangles[i++] = 6; 51 | 52 | triangles[i++] = 3; 53 | triangles[i++] = 0; 54 | triangles[i++] = 4; 55 | 56 | triangles[i++] = 3; 57 | triangles[i++] = 4; 58 | triangles[i++] = 7; 59 | } 60 | } 61 | 62 | } // namespace Thesis -------------------------------------------------------------------------------- /Assets/Standard Assets/City/Sidewalk.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using UnityEngine; 3 | 4 | namespace Thesis { 5 | 6 | public sealed class Sidewalk : DrawableObject 7 | { 8 | public readonly List edges; 9 | 10 | public Sidewalk (Block parent) 11 | { 12 | boundaries = new Vector3[8]; 13 | edges = new List(); 14 | for (int i = 0; i < 4; ++i) 15 | { 16 | boundaries[i] = parent.sidewalkVerts[i]; 17 | boundaries[i + 4] = parent.lotVerts[i]; 18 | edges.Add(new Edge(parent.sidewalkVerts[i], 19 | parent.sidewalkVerts[(i + 1) % 4])); 20 | } 21 | } 22 | 23 | public override void FindVertices() 24 | { 25 | vertices = boundaries; 26 | } 27 | 28 | public override void FindTriangles() 29 | { 30 | triangles = new int[24]; 31 | int i = 0; 32 | 33 | triangles[i++] = 0; 34 | triangles[i++] = 1; 35 | triangles[i++] = 5; 36 | 37 | triangles[i++] = 0; 38 | triangles[i++] = 5; 39 | triangles[i++] = 4; 40 | 41 | triangles[i++] = 1; 42 | triangles[i++] = 2; 43 | triangles[i++] = 6; 44 | 45 | triangles[i++] = 1; 46 | triangles[i++] = 6; 47 | triangles[i++] = 5; 48 | 49 | triangles[i++] = 2; 50 | triangles[i++] = 3; 51 | triangles[i++] = 7; 52 | 53 | triangles[i++] = 2; 54 | triangles[i++] = 7; 55 | triangles[i++] = 6; 56 | 57 | triangles[i++] = 3; 58 | triangles[i++] = 0; 59 | triangles[i++] = 4; 60 | 61 | triangles[i++] = 3; 62 | triangles[i++] = 4; 63 | triangles[i++] = 7; 64 | } 65 | } 66 | 67 | } // namespace Thesis -------------------------------------------------------------------------------- /Assets/Standard Assets/Door/Door.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace Thesis { 4 | 5 | public class Door : FaceComponent 6 | { 7 | public Building masterParent 8 | { 9 | get { return parentBuilding.parent; } 10 | } 11 | 12 | public Door (Face parent, Vector3 dr, Vector3 dl, ComponentCoordinate position) 13 | : base(parent, position) 14 | { 15 | height = parentBuilding.doorHeight; 16 | depth = 0.4f; 17 | 18 | float mod = 0.4f; 19 | if (masterParent.doorWidth > 0f) 20 | mod = (masterParent.doorWidth - (dr - dl).magnitude) / 2f; 21 | 22 | dr += mod * parentFace.right; 23 | dl -= mod * parentFace.right; 24 | 25 | var ul = new Vector3(dl.x, dl.y + height, dl.z); 26 | var ur = new Vector3(dr.x, dr.y + height, dr.z); 27 | 28 | boundaries = new Vector3[4]; 29 | boundaries[0] = dr; 30 | boundaries[1] = dl; 31 | boundaries[2] = ul; 32 | boundaries[3] = ur; 33 | 34 | frame = new ComponentFrame(this); 35 | frame.name = "neo_door_frame"; 36 | frame.material = MaterialManager.Instance.Get("ComponentFrame"); 37 | parentBuilding.parent.AddCombinable(frame.material.name, frame); 38 | 39 | body = new DoorBody(this); 40 | body.name = "neo_door_body"; 41 | body.material = parentBuilding.parent.doorMaterial; 42 | parentBuilding.parent.AddCombinable(body.material.name, body); 43 | } 44 | 45 | public override void Draw () 46 | { 47 | frame.FindVertices(); 48 | frame.FindTriangles(); 49 | frame.Draw(); 50 | 51 | body.FindVertices(); 52 | body.FindTriangles(); 53 | body.Draw(); 54 | } 55 | } 56 | 57 | } // namespace Thesis -------------------------------------------------------------------------------- /Assets/Standard Assets/City/Edge.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace Thesis { 4 | 5 | public class Edge 6 | { 7 | private Vector3 _start; 8 | public Vector3 start 9 | { 10 | get { return _start; } 11 | set 12 | { 13 | _start = value; 14 | _length = Vector3.Distance(_start, _end); 15 | _middle = (_start + _end) / 2; 16 | _direction = (_end - _start).normalized; 17 | _right = Vector3.Cross(Vector3.up, _direction).normalized; 18 | } 19 | } 20 | 21 | private Vector3 _end; 22 | public Vector3 end 23 | { 24 | get { return _end; } 25 | set 26 | { 27 | _end = value; 28 | _length = Vector3.Distance(_start, _end); 29 | _middle = (_start + _end) / 2; 30 | _direction = (_end - _start).normalized; 31 | _right = Vector3.Cross(Vector3.up, _direction).normalized; 32 | } 33 | } 34 | 35 | private Vector3 _middle; 36 | public Vector3 middle 37 | { 38 | get { return _middle; } 39 | } 40 | 41 | private float _length; 42 | public float length 43 | { 44 | get { return _length; } 45 | } 46 | 47 | private Vector3 _direction; 48 | public Vector3 direction 49 | { 50 | get { return _direction; } 51 | } 52 | 53 | private Vector3 _right; 54 | public Vector3 right 55 | { 56 | get { return _right; } 57 | } 58 | 59 | private Edge () { } 60 | 61 | public Edge (Vector3 from, Vector3 to) 62 | { 63 | _start = from; 64 | _end = to; 65 | _length = Vector3.Distance(from, to); 66 | _middle = (from + to) / 2; 67 | _direction = (to - from).normalized; 68 | _right = Vector3.Cross(Vector3.up, _direction).normalized; 69 | } 70 | 71 | public bool Contains (Vector3 point) 72 | { 73 | var dist = Vector3.Distance(_start, point) + Vector3.Distance(point, _end); 74 | return Mathf.Abs(_length - dist) < 0.01f; 75 | } 76 | } 77 | 78 | } // namespace Thesis -------------------------------------------------------------------------------- /Assets/Standard Assets/General/ComponentBody.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace Thesis { 4 | 5 | public class ComponentBody : DrawableObject 6 | { 7 | /*************** FIELDS ***************/ 8 | 9 | public readonly FaceComponent parentComponent; 10 | 11 | public Face parentFace 12 | { 13 | get { return parentComponent.parentFace; } 14 | } 15 | 16 | public BuildingMesh parentBuilding 17 | { 18 | get { return parentComponent.parentBuilding; } 19 | } 20 | 21 | /*************** CONSTRUCTORS ***************/ 22 | 23 | public ComponentBody (FaceComponent parent) 24 | { 25 | parentComponent = parent; 26 | 27 | boundaries = new Vector3[4]; 28 | for (var i = 0; i < parentComponent.boundaries.Length; ++i) 29 | boundaries[i] = parentComponent.boundaries[i] - 30 | parentComponent.depth * parentComponent.normal; 31 | 32 | FindMeshOrigin(boundaries[0], 33 | boundaries[2], 34 | boundaries[1], 35 | boundaries[3]); 36 | 37 | for (var i = 0; i < boundaries.Length; ++i) 38 | boundaries[i] -= meshOrigin; 39 | } 40 | 41 | /*************** METHODS ***************/ 42 | 43 | public override void FindVertices () 44 | { 45 | vertices = boundaries; 46 | } 47 | 48 | public override void FindTriangles () 49 | { 50 | triangles = new int[] { 51 | 0, 1, 3, 52 | 1, 2, 3 53 | }; 54 | } 55 | 56 | public override void Draw () 57 | { 58 | base.Draw(); 59 | 60 | var uvs = new Vector2[mesh.vertices.Length]; 61 | uvs[1] = new Vector2(0f, 0f); 62 | uvs[0] = new Vector2(1f, 0f); 63 | uvs[2] = new Vector2(0f, 1f); 64 | uvs[3] = new Vector2(1f, 1f); 65 | 66 | mesh.uv = uvs; 67 | 68 | gameObject.transform.position = meshOrigin + parentBuilding.meshOrigin; 69 | gameObject.transform.parent = parentBuilding.parent.gameObject.transform; 70 | } 71 | } 72 | 73 | } // namespace Thesis -------------------------------------------------------------------------------- /Assets/Standard Assets/City/BuildingLot.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace Thesis { 6 | 7 | public sealed class BuildingLot : DrawableObject 8 | { 9 | // edges[0] is _always_ adjacent to a street 10 | public readonly List edges = new List(); 11 | 12 | // contains the indexes of the faces that are not 13 | // in contact with other walls or covered. 14 | public readonly List freeEdges = new List(); 15 | 16 | // key -> index of edge 17 | // value -> percentage of length that is occupied 18 | public Dictionary occupied; 19 | 20 | // key -> index of edge 21 | // value -> list that contains all the points on that edge 22 | public Dictionary> pointsInEdge; 23 | 24 | public BuildingLot (Block parent) 25 | { 26 | var edgeList = new List(); 27 | for (int i = 0; i < 4; ++i) 28 | edgeList.Add(new Edge(parent.lotVerts[i], parent.lotVerts[(i + 1) % 4])); 29 | 30 | int big = edgeList.FindIndex(delegate (Edge e) { 31 | return e.length == edgeList.Max(t => t.length); 32 | }); 33 | for (int i = 0; i < 4; ++i) 34 | edges.Add(edgeList[(big + i) % 4]); 35 | 36 | occupied = new Dictionary(); 37 | occupied.Add(0, 0f); 38 | occupied.Add(1, 0f); 39 | occupied.Add(2, 0f); 40 | occupied.Add(3, 0f); 41 | 42 | pointsInEdge = new Dictionary>(); 43 | pointsInEdge.Add(0, new List()); 44 | pointsInEdge.Add(1, new List()); 45 | pointsInEdge.Add(2, new List()); 46 | pointsInEdge.Add(3, new List()); 47 | } 48 | 49 | public BuildingLot (Vector3 p1, Vector3 p2, Vector3 p3, Vector3 p4) 50 | { 51 | edges.Add(new Edge(p1, p2)); 52 | edges.Add(new Edge(p2, p3)); 53 | edges.Add(new Edge(p3, p4)); 54 | edges.Add(new Edge(p4, p1)); 55 | } 56 | 57 | public bool isFinal () 58 | { 59 | float min = edges.Min(e => e.length); 60 | 61 | if (edges[0].length >= 2.5f * min) 62 | return false; 63 | 64 | if (edges[0].length < 16f && min < 16f) 65 | return true; 66 | 67 | return false; 68 | } 69 | 70 | public override void FindVertices() 71 | { 72 | vertices = new Vector3[4]; 73 | for (int i = 0; i < 4; ++i) 74 | vertices[i] = edges[i].start - 0.01f * Vector3.up; 75 | } 76 | 77 | public override void FindTriangles() 78 | { 79 | triangles = new int[6]; 80 | int i = 0; 81 | 82 | triangles[i++] = 0; 83 | triangles[i++] = 1; 84 | triangles[i++] = 2; 85 | 86 | triangles[i++] = 0; 87 | triangles[i++] = 2; 88 | triangles[i++] = 3; 89 | } 90 | } 91 | 92 | } // namespace Thesis -------------------------------------------------------------------------------- /Assets/Standard Assets/General/ProceduralTexture.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections.Generic; 3 | 4 | namespace Thesis { 5 | 6 | public class ProceduralTexture 7 | { 8 | public Texture2D content; 9 | 10 | public List lines; 11 | 12 | public ProceduralTexture (int width = 256, int height = 128) 13 | { 14 | content = new Texture2D(width, height); 15 | lines = new List(); 16 | } 17 | 18 | public ProceduralTexture (Texture2D texture) 19 | { 20 | content = texture; 21 | lines = new List(); 22 | } 23 | 24 | public virtual void Draw () 25 | { 26 | foreach (TextureLine line in lines) 27 | DrawLine(line.start, line.end, line.color, line.thickness); 28 | 29 | content.Apply(); 30 | } 31 | 32 | public void Clear () 33 | { 34 | for (var x = 0; x < content.width; ++x) 35 | for (var y = 0; y < content.height; ++y) 36 | content.SetPixel(x, y, Color.clear); 37 | } 38 | 39 | public void SetBackgroundColor (Color color) 40 | { 41 | for (var x = 0; x < content.width; ++x) 42 | for (var y = 0; y < content.height; ++y) 43 | content.SetPixel(x, y, color); 44 | } 45 | 46 | public void DrawLine (Vector2 p1, Vector2 p2, Color color, int thickness) 47 | { 48 | DrawLine(p1, p2, color); 49 | if (Mathf.Abs(p1.x - p2.x) > Mathf.Abs(p1.y - p2.y)) 50 | for (var tk = 1; tk < Mathf.CeilToInt((1f * thickness) / 2); ++tk) 51 | { 52 | DrawLine(p1 + tk * Vector2.up, p2 + tk * Vector2.up, color); 53 | DrawLine(p1 - tk * Vector2.up, p2 - tk * Vector2.up, color); 54 | } 55 | else 56 | for (var tk = 1; tk < Mathf.CeilToInt((1f * thickness) / 2); ++tk) 57 | { 58 | DrawLine(p1 + tk * Vector2.right, p2 + tk * Vector2.right, color); 59 | DrawLine(p1 - tk * Vector2.right, p2 - tk * Vector2.right, color); 60 | } 61 | } 62 | 63 | 64 | /// 65 | /// Implementation of Besenham's line algorithm: 66 | /// http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm#Simplification 67 | /// 68 | public void DrawLine (Vector2 p1, Vector2 p2, Color color) 69 | { 70 | int dx = Mathf.Abs((int) (p1.x - p2.x)); 71 | int dy = Mathf.Abs((int) (p1.y - p2.y)); 72 | int sx = (p1.x < p2.x) ? 1 : -1; 73 | int sy = (p1.y < p2.y) ? 1 : -1; 74 | int err = dx - dy; 75 | int err2; 76 | 77 | while (true) 78 | { 79 | content.SetPixel((int) p1.x, (int) p1.y, color); 80 | if (p1.x == p2.x && p1.y == p2.y) break; 81 | err2 = err << 1; 82 | if (err2 > -dy) 83 | { 84 | err -= dy; 85 | p1.x += sx; 86 | } 87 | 88 | if (err2 < dx) 89 | { 90 | err += dx; 91 | p1.y += sy; 92 | } 93 | } 94 | } 95 | } 96 | 97 | } // namespace Thesis -------------------------------------------------------------------------------- /Assets/Standard Assets/General/ComponentFrame.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace Thesis { 4 | 5 | public class ComponentFrame : DrawableObject 6 | { 7 | /*************** FIELDS ***************/ 8 | 9 | public readonly FaceComponent parentComponent; 10 | 11 | public Face parentFace 12 | { 13 | get { return parentComponent.parentFace; } 14 | } 15 | 16 | public BuildingMesh parentBuilding 17 | { 18 | get { return parentFace.parentBuilding; } 19 | } 20 | 21 | /*************** CONSTRUCTORS ***************/ 22 | 23 | public ComponentFrame (FaceComponent parent) 24 | { 25 | parentComponent = parent; 26 | 27 | boundaries = new Vector3[8]; 28 | for (var i = 0; i < 4; ++i) 29 | { 30 | boundaries[i] = parentComponent.boundaries[i]; 31 | // subtract a small amount to prevent overlaping triangles 32 | boundaries[i + 4] = boundaries[i] - parentComponent.depth * parentComponent.normal; 33 | } 34 | 35 | FindMeshOrigin(boundaries[0], 36 | boundaries[6], 37 | boundaries[2], 38 | boundaries[4]); 39 | 40 | for (var i = 0; i < boundaries.Length; ++i) 41 | boundaries[i] -= meshOrigin; 42 | } 43 | 44 | /*************** METHODS ***************/ 45 | 46 | public override void FindVertices () 47 | { 48 | vertices = new Vector3[boundaries.Length << 1]; 49 | for (var i = 0; i < boundaries.Length; ++i) 50 | vertices[i] = vertices[i + 8] = boundaries[i]; 51 | } 52 | 53 | public override void FindTriangles () 54 | { 55 | triangles = new int[3 * boundaries.Length]; 56 | var i = 0; 57 | 58 | // right 59 | triangles[i++] = 0; 60 | triangles[i++] = 4; 61 | triangles[i++] = 7; 62 | 63 | triangles[i++] = 0; 64 | triangles[i++] = 7; 65 | triangles[i++] = 3; 66 | 67 | // left 68 | triangles[i++] = 1; 69 | triangles[i++] = 2; 70 | triangles[i++] = 6; 71 | 72 | triangles[i++] = 1; 73 | triangles[i++] = 6; 74 | triangles[i++] = 5; 75 | 76 | // bottom 77 | triangles[i++] = 8; // 0 + 8; 78 | triangles[i++] = 9; // 1 + 8; 79 | triangles[i++] = 13; // 5 + 8; 80 | 81 | triangles[i++] = 8; // 0 + 8; 82 | triangles[i++] = 13; // 5 + 8; 83 | triangles[i++] = 12; // 4 + 8; 84 | 85 | // top 86 | triangles[i++] = 10; // 2 + 8; 87 | triangles[i++] = 11; // 3 + 8; 88 | triangles[i++] = 14; // 6 + 8; 89 | 90 | triangles[i++] = 14; // 6 + 8; 91 | triangles[i++] = 11; // 3 + 8; 92 | triangles[i++] = 15; // 7 + 8; 93 | } 94 | 95 | public override void Draw () 96 | { 97 | base.Draw(); 98 | 99 | gameObject.transform.position = meshOrigin + parentBuilding.meshOrigin; 100 | gameObject.transform.parent = parentBuilding.parent.gameObject.transform; 101 | } 102 | } 103 | 104 | } // namespace Thesis -------------------------------------------------------------------------------- /Assets/Standard Assets/Roof/SinglePeakRoof.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace Thesis { 4 | 5 | public class SinglePeakRoof : Roof 6 | { 7 | public SinglePeakRoof (BuildingMesh parent) 8 | : base(parent) 9 | { 10 | height = 1f; 11 | width = 0.2f; 12 | 13 | boundaries = new Vector3[5]; 14 | 15 | for (int i = 0; i < 4; ++i) 16 | boundaries[i] = parentMesh.roofBase.boundaries[i + 4] + 17 | width * parentMesh.faces[i].normal + 18 | width * parentMesh.faces[(i + 3) % 4].normal; 19 | 20 | FindMeshOrigin(boundaries[0], boundaries[2], 21 | boundaries[1], boundaries[3]); 22 | 23 | boundaries[4] = new Vector3(meshOrigin.x, 24 | boundaries[0].y + height, 25 | meshOrigin.z); 26 | } 27 | 28 | public override void FindVertices() 29 | { 30 | vertices = new Vector3[boundaries.Length * 5]; 31 | for (int i = 0; i < 5; ++i) 32 | System.Array.Copy(boundaries, 0, vertices, i * boundaries.Length, boundaries.Length); 33 | } 34 | 35 | public override void FindTriangles() 36 | { 37 | triangles = new int[18]; 38 | int i = 0; 39 | 40 | triangles[i++] = 0; 41 | triangles[i++] = 1; 42 | triangles[i++] = 4; 43 | 44 | // +5 45 | triangles[i++] = 6; 46 | triangles[i++] = 7; 47 | triangles[i++] = 9; 48 | 49 | // +10 50 | triangles[i++] = 12; 51 | triangles[i++] = 13; 52 | triangles[i++] = 14; 53 | 54 | // +15 55 | triangles[i++] = 18; 56 | triangles[i++] = 15; 57 | triangles[i++] = 19; 58 | 59 | triangles[i++] = 20; 60 | triangles[i++] = 23; 61 | triangles[i++] = 22; 62 | 63 | triangles[i++] = 20; 64 | triangles[i++] = 22; 65 | triangles[i++] = 21; 66 | } 67 | 68 | public override void Draw() 69 | { 70 | base.Draw(); 71 | 72 | var uvs = new Vector2[mesh.vertices.Length]; 73 | 74 | float _wdiv = material.mainTexture.width / 128f; 75 | float _hdiv = material.mainTexture.height / 128f; 76 | float _dist01 = (boundaries[0] - boundaries[1]).magnitude; 77 | float _dist12 = (boundaries[1] - boundaries[2]).magnitude; 78 | float htimes = _dist01 / _wdiv; 79 | float vtimes = Mathf.Sqrt(Mathf.Pow(_dist12 / 2, 2) + 80 | Mathf.Pow(height, 2)) / _hdiv; 81 | 82 | uvs[1] = new Vector2(0f, 0f); 83 | uvs[4] = new Vector2(htimes / 2, vtimes); 84 | uvs[0] = new Vector2(htimes, 0f); 85 | uvs[13] = new Vector2(0f, 0f); 86 | uvs[14] = new Vector2(htimes / 2, vtimes); 87 | uvs[12] = new Vector2(htimes, 0f); 88 | 89 | htimes = _dist12 / _wdiv; 90 | vtimes = Mathf.Sqrt(Mathf.Pow(_dist01 / 2, 2) + 91 | Mathf.Pow(height, 2)) / _hdiv; 92 | 93 | uvs[7] = new Vector2(0f, 0f); 94 | uvs[9] = new Vector2(htimes / 2, vtimes); 95 | uvs[6] = new Vector2(htimes, 0f); 96 | uvs[15] = new Vector2(0f, 0f); 97 | uvs[19] = new Vector2(htimes / 2, vtimes); 98 | uvs[18] = new Vector2(htimes, 0f); 99 | 100 | mesh.uv = uvs; 101 | } 102 | } 103 | 104 | } -------------------------------------------------------------------------------- /Assets/Standard Assets/Roof/RoofBase.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace Thesis { 4 | 5 | public class RoofBase : DrawableObject 6 | { 7 | /*************** FIELDS ***************/ 8 | 9 | public readonly BuildingMesh parentMesh; 10 | 11 | public float height; 12 | 13 | /*************** CONSTRUCTORS ***************/ 14 | 15 | public RoofBase (BuildingMesh parent) 16 | { 17 | parentMesh = parent; 18 | height = 0.6f; 19 | 20 | boundaries = new Vector3[8]; 21 | 22 | for (int i = 0; i < 4; ++i) 23 | { 24 | boundaries[i] = parentMesh.boundaries[i + 4]; 25 | boundaries[i + 4] = boundaries[i] + height * Vector3.up; 26 | } 27 | } 28 | 29 | public override void FindVertices() 30 | { 31 | vertices = new Vector3[boundaries.Length * 2]; 32 | for (int i = 0; i < 2; ++i) 33 | System.Array.Copy(boundaries, 0, vertices, i * boundaries.Length, boundaries.Length); 34 | } 35 | 36 | public override void FindTriangles() 37 | { 38 | triangles = new int[24]; 39 | int i = 0; 40 | 41 | // front 42 | triangles[i++] = 0; 43 | triangles[i++] = 1; 44 | triangles[i++] = 5; 45 | 46 | triangles[i++] = 0; 47 | triangles[i++] = 5; 48 | triangles[i++] = 4; 49 | 50 | // back 51 | triangles[i++] = 3; 52 | triangles[i++] = 7; 53 | triangles[i++] = 6; 54 | 55 | triangles[i++] = 3; 56 | triangles[i++] = 6; 57 | triangles[i++] = 2; 58 | 59 | // left (+8) 60 | triangles[i++] = 9; 61 | triangles[i++] = 10; 62 | triangles[i++] = 14; 63 | 64 | triangles[i++] = 9; 65 | triangles[i++] = 14; 66 | triangles[i++] = 13; 67 | 68 | // right (+8) 69 | triangles[i++] = 8; 70 | triangles[i++] = 12; 71 | triangles[i++] = 15; 72 | 73 | triangles[i++] = 8; 74 | triangles[i++] = 15; 75 | triangles[i++] = 11; 76 | } 77 | 78 | public override void Draw() 79 | { 80 | base.Draw(); 81 | 82 | var uvs = new Vector2[mesh.vertices.Length]; 83 | 84 | float _wdiv = material.mainTexture.width / 128f; 85 | int times = Mathf.CeilToInt((boundaries[0] - boundaries[1]).magnitude / _wdiv); 86 | 87 | uvs[1] = new Vector2(0f, 0f); 88 | uvs[0] = new Vector2(times, 0f); 89 | uvs[5] = new Vector2(0f, 1f); 90 | uvs[4] = new Vector2(times, 1f); 91 | 92 | uvs[3] = new Vector2(0f, 0f); 93 | uvs[2] = new Vector2(times, 0f); 94 | uvs[7] = new Vector2(0f, 1f); 95 | uvs[6] = new Vector2(times, 1f); 96 | 97 | times = Mathf.CeilToInt((boundaries[2] - boundaries[1]).magnitude / _wdiv); 98 | 99 | uvs[10] = new Vector2(0f, 0f); 100 | uvs[9] = new Vector2(times, 0f); 101 | uvs[14] = new Vector2(0f, 1f); 102 | uvs[13] = new Vector2(times, 1f); 103 | 104 | uvs[8] = new Vector2(0f, 0f); 105 | uvs[11] = new Vector2(times, 0f); 106 | uvs[12] = new Vector2(0f, 1f); 107 | uvs[15] = new Vector2(times, 1f); 108 | 109 | mesh.uv = uvs; 110 | 111 | gameObject.transform.parent = parentMesh.parent.gameObject.transform; 112 | gameObject.transform.position = parentMesh.meshOrigin; 113 | } 114 | } 115 | 116 | } // namespace Thesis -------------------------------------------------------------------------------- /Assets/Standard Assets/Roof/FlatRoof.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace Thesis { 4 | 5 | public class FlatRoof : Roof 6 | { 7 | public FlatRoof (BuildingMesh parent) 8 | : base(parent) 9 | { 10 | width = 0.1f; 11 | height = 0.05f; 12 | 13 | boundaries = new Vector3[8]; 14 | 15 | for (int i = 0; i < 4; ++i) 16 | { 17 | boundaries[i] = parentMesh.roofBase.boundaries[i + 4] + 18 | width * parentMesh.faces[i].normal + 19 | width * parentMesh.faces[(i + 3) % 4].normal; 20 | 21 | boundaries[i + 4] = boundaries[i] + height * Vector3.up; 22 | } 23 | 24 | decor = new RoofDecoration(this); 25 | if (parentMesh.parent.roofDecorMaterial == null) 26 | { 27 | var list = MaterialManager.Instance.GetCollection("mat_roof_decor"); 28 | decor.material = list[Random.Range(0, list.Count)]; 29 | } 30 | else 31 | decor.material = parentMesh.parent.roofDecorMaterial; 32 | parentMesh.parent.AddCombinable(decor.material.name, decor); 33 | } 34 | 35 | public override void FindVertices() 36 | { 37 | vertices = new Vector3[boundaries.Length * 3]; 38 | for (int i = 0; i < 3; ++i) 39 | System.Array.Copy(boundaries, 0, vertices, i * boundaries.Length, boundaries.Length); 40 | } 41 | 42 | public override void FindTriangles() 43 | { 44 | triangles = new int[36]; 45 | var i = 0; 46 | 47 | // front 48 | triangles[i++] = 0; 49 | triangles[i++] = 1; 50 | triangles[i++] = 5; 51 | 52 | triangles[i++] = 0; 53 | triangles[i++] = 5; 54 | triangles[i++] = 4; 55 | 56 | // back 57 | triangles[i++] = 2; 58 | triangles[i++] = 3; 59 | triangles[i++] = 6; 60 | 61 | triangles[i++] = 3; 62 | triangles[i++] = 7; 63 | triangles[i++] = 6; 64 | 65 | // right (+8) 66 | triangles[i++] = 11; 67 | triangles[i++] = 8; 68 | triangles[i++] = 15; 69 | 70 | triangles[i++] = 8; 71 | triangles[i++] = 12; 72 | triangles[i++] = 15; 73 | 74 | // left (+8) 75 | triangles[i++] = 9; 76 | triangles[i++] = 10; 77 | triangles[i++] = 14; 78 | 79 | triangles[i++] = 9; 80 | triangles[i++] = 14; 81 | triangles[i++] = 13; 82 | 83 | // bottom (+16) 84 | triangles[i++] = 16; 85 | triangles[i++] = 18; 86 | triangles[i++] = 17; 87 | 88 | triangles[i++] = 16; 89 | triangles[i++] = 19; 90 | triangles[i++] = 18; 91 | 92 | // top (+16) 93 | triangles[i++] = 20; 94 | triangles[i++] = 21; 95 | triangles[i++] = 22; 96 | 97 | triangles[i++] = 20; 98 | triangles[i++] = 22; 99 | triangles[i++] = 23; 100 | } 101 | 102 | public override void Draw() 103 | { 104 | base.Draw(); 105 | 106 | float _wdiv = material.mainTexture.width / 128f; 107 | float _hdiv = material.mainTexture.height / 128f; 108 | float htimes = (boundaries[0] - boundaries[1]).magnitude / _wdiv; 109 | float vtimes = (boundaries[2] - boundaries[1]).magnitude / _hdiv; 110 | 111 | var uvs = new Vector2[mesh.vertices.Length]; 112 | 113 | uvs[21] = new Vector2(0f, 0f); 114 | uvs[20] = new Vector2(htimes, 0f); 115 | uvs[22] = new Vector2(0f, vtimes); 116 | uvs[23] = new Vector2(htimes, vtimes); 117 | 118 | mesh.uv = uvs; 119 | } 120 | } 121 | 122 | } // namespace Thesis -------------------------------------------------------------------------------- /Assets/Standard Assets/Roof/RoofDecoration.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace Thesis { 4 | 5 | public class RoofDecoration : DrawableObject 6 | { 7 | public readonly Roof parentRoof; 8 | 9 | public float height; 10 | 11 | public RoofDecoration (Roof parent) 12 | { 13 | parentRoof = parent; 14 | height = 0.48f; 15 | 16 | boundaries = new Vector3[8]; 17 | 18 | if (parentRoof.boundaries.Length < 8) 19 | for (int i = 0; i < 4; ++i) 20 | { 21 | boundaries[i] = parentRoof.boundaries[i]; 22 | boundaries[i + 4] = boundaries[i] + height * Vector3.up; 23 | } 24 | else if (parentRoof.boundaries.Length == 8) 25 | for (int i = 0; i < 4; ++i) 26 | { 27 | boundaries[i] = parentRoof.boundaries[i + 4]; 28 | boundaries[i + 4] = boundaries[i] + height * Vector3.up; 29 | } 30 | } 31 | 32 | public override void FindVertices() 33 | { 34 | vertices = new Vector3[boundaries.Length * 2]; 35 | for (int i = 0; i < 2; ++i) 36 | System.Array.Copy(boundaries, 0, vertices, i * boundaries.Length, boundaries.Length); 37 | } 38 | 39 | public override void FindTriangles() 40 | { 41 | triangles = new int[24]; 42 | int i = 0; 43 | 44 | // front 45 | triangles[i++] = 0; 46 | triangles[i++] = 1; 47 | triangles[i++] = 5; 48 | 49 | triangles[i++] = 0; 50 | triangles[i++] = 5; 51 | triangles[i++] = 4; 52 | 53 | // back 54 | triangles[i++] = 3; 55 | triangles[i++] = 7; 56 | triangles[i++] = 6; 57 | 58 | triangles[i++] = 3; 59 | triangles[i++] = 6; 60 | triangles[i++] = 2; 61 | 62 | // left (+8) 63 | triangles[i++] = 9; 64 | triangles[i++] = 10; 65 | triangles[i++] = 14; 66 | 67 | triangles[i++] = 9; 68 | triangles[i++] = 14; 69 | triangles[i++] = 13; 70 | 71 | // right (+8) 72 | triangles[i++] = 8; 73 | triangles[i++] = 12; 74 | triangles[i++] = 15; 75 | 76 | triangles[i++] = 8; 77 | triangles[i++] = 15; 78 | triangles[i++] = 11; 79 | } 80 | 81 | public override void Draw() 82 | { 83 | base.Draw(); 84 | 85 | var uvs = new Vector2[mesh.vertices.Length]; 86 | 87 | float _wdiv = material.mainTexture.width / 128f; 88 | int times = Mathf.CeilToInt((boundaries[0] - boundaries[1]).magnitude / _wdiv); 89 | 90 | uvs[1] = new Vector2(0f, 0f); 91 | uvs[0] = new Vector2(times, 0f); 92 | uvs[5] = new Vector2(0f, 1f); 93 | uvs[4] = new Vector2(times, 1f); 94 | 95 | uvs[3] = new Vector2(0f, 0f); 96 | uvs[2] = new Vector2(times, 0f); 97 | uvs[7] = new Vector2(0f, 1f); 98 | uvs[6] = new Vector2(times, 1f); 99 | 100 | times = Mathf.CeilToInt((boundaries[2] - boundaries[1]).magnitude / _wdiv); 101 | 102 | uvs[10] = new Vector2(0f, 0f); 103 | uvs[9] = new Vector2(times, 0f); 104 | uvs[14] = new Vector2(0f, 1f); 105 | uvs[13] = new Vector2(times, 1f); 106 | 107 | uvs[8] = new Vector2(0f, 0f); 108 | uvs[11] = new Vector2(times, 0f); 109 | uvs[12] = new Vector2(0f, 1f); 110 | uvs[15] = new Vector2(times, 1f); 111 | 112 | mesh.uv = uvs; 113 | 114 | gameObject.transform.parent = parentRoof.parentMesh.parent.gameObject.transform; 115 | gameObject.transform.position = parentRoof.parentMesh.meshOrigin; 116 | } 117 | } 118 | 119 | } // namespace Thesis -------------------------------------------------------------------------------- /Assets/Standard Assets/Managers/ColorManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | namespace Thesis { 6 | 7 | public sealed class ColorManager 8 | { 9 | private static readonly ColorManager _instance = new ColorManager(); 10 | public static ColorManager Instance 11 | { 12 | get { return _instance; } 13 | } 14 | 15 | private static bool _isInitialized; 16 | 17 | private Dictionary _colors; 18 | 19 | private Dictionary> _collections; 20 | 21 | private ColorManager () 22 | { 23 | _colors = new Dictionary(); 24 | _collections = new Dictionary>(); 25 | _isInitialized = false; 26 | } 27 | 28 | public void Init () 29 | { 30 | if (!_isInitialized) 31 | { 32 | AddComponentColors(); 33 | AddWallColors(); 34 | 35 | _isInitialized = true; 36 | } 37 | } 38 | 39 | public void Unload () 40 | { 41 | _colors.Clear(); 42 | foreach (List l in _collections.Values) 43 | l.Clear(); 44 | _collections.Clear(); 45 | _isInitialized = false; 46 | } 47 | 48 | public void Add (string name, Color color) 49 | { 50 | if (!_colors.ContainsKey(name)) 51 | _colors.Add(name, color); 52 | } 53 | 54 | public void AddToCollection (string name, Color color) 55 | { 56 | if (_collections.ContainsKey(name)) 57 | { 58 | if (!_collections[name].Contains(color)) 59 | _collections[name].Add(color); 60 | } 61 | else 62 | { 63 | var list = new List(); 64 | list.Add(color); 65 | _collections.Add(name, list); 66 | } 67 | } 68 | 69 | public Color Get (string name) 70 | { 71 | return _colors.ContainsKey(name) ? _colors[name] : Color.clear; 72 | } 73 | 74 | public List GetCollection (string name) 75 | { 76 | return _collections.ContainsKey(name) ? _collections[name] : null; 77 | } 78 | 79 | private void AddComponentColors () 80 | { 81 | var name = "col_components"; 82 | AddToCollection(name, new Color32( 245, 245, 220, 255)); 83 | AddToCollection(name, new Color32( 210, 180, 140, 255)); 84 | AddToCollection(name, new Color32( 151, 105, 79, 255)); 85 | AddToCollection(name, new Color32( 139, 105, 105, 255)); 86 | AddToCollection(name, new Color32( 139, 90, 51, 255)); 87 | AddToCollection(name, new Color32( 139, 69, 19, 255)); 88 | AddToCollection(name, new Color32( 133, 99, 99, 255)); 89 | AddToCollection(name, new Color32( 107, 66, 38, 255)); 90 | AddToCollection(name, new Color32( 92, 64, 51, 255)); 91 | AddToCollection(name, new Color32( 92, 51, 23, 255)); 92 | } 93 | 94 | private void AddWallColors () 95 | { 96 | var name = "col_walls"; 97 | AddToCollection(name, new Color32( 166, 159, 141, 255)); 98 | AddToCollection(name, new Color32( 231, 206, 165, 255)); 99 | AddToCollection(name, new Color32( 173, 155, 155, 255)); 100 | AddToCollection(name, new Color32( 135, 125, 115, 255)); 101 | AddToCollection(name, new Color32( 155, 157, 143, 255)); 102 | AddToCollection(name, new Color32( 225, 168, 151, 255)); 103 | AddToCollection(name, new Color32( 224, 174, 125, 255)); 104 | AddToCollection(name, new Color32( 216, 191, 150, 255)); 105 | AddToCollection(name, new Color32( 205, 171, 110, 255)); 106 | AddToCollection(name, new Color32( 165, 133, 118, 255)); 107 | AddToCollection(name, new Color32( 190, 169, 164, 255)); 108 | AddToCollection(name, new Color32( 194, 183, 181, 255)); 109 | } 110 | } 111 | 112 | } // namespace Thesis -------------------------------------------------------------------------------- /Assets/Standard Assets/General/Util.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | using Random = System.Random; 4 | using Exception = System.Exception; 5 | using CombinablesCollection = System.Collections.Generic.IList; 6 | 7 | namespace Thesis { 8 | 9 | public class Util 10 | { 11 | public static Random random = new Random(); 12 | 13 | /// 14 | /// Rolls a weighted dice. 15 | /// 16 | /// 17 | /// The chances for each possible result. 18 | /// 19 | /// 20 | /// A set of the possible result values. 21 | /// 22 | /// 23 | /// The maximum of decimal digits that a number has. 24 | /// 25 | public static int RollDice (float[] chances, int[] numbers = null, int precision = 2) 26 | { 27 | if (numbers == null) 28 | { 29 | numbers = new int[chances.Length]; 30 | for (var i = 0; i < chances.Length; ++i) 31 | numbers[i] = i + 1; 32 | } 33 | 34 | precision = (int) Mathf.Pow(10, precision); 35 | 36 | int[] expanded = new int[precision]; 37 | int start = 0; 38 | int end = 0; 39 | for (var i = 0; i < chances.Length; ++i) 40 | { 41 | start = end; 42 | end += Mathf.FloorToInt(chances[i] * precision); 43 | for (var j = start; j < end; ++j) 44 | expanded[j] = numbers[i]; 45 | } 46 | 47 | return expanded[random.Next(precision)]; 48 | } 49 | 50 | public static GameObject CombineMeshes (string name, 51 | string materialName, 52 | CombinablesCollection objects, 53 | GameObject parent = null) 54 | { 55 | var gameObject = new GameObject(name); 56 | gameObject.SetActive(false); 57 | if (parent != null) 58 | gameObject.transform.parent = parent.transform; 59 | var meshFilter = gameObject.AddComponent(); 60 | var meshRenderer = gameObject.AddComponent(); 61 | meshRenderer.sharedMaterial = Resources.Load("Materials/" + materialName, 62 | typeof(Material)) as Material; 63 | 64 | MeshFilter[] meshFilters = new MeshFilter[objects.Count]; 65 | for (var i = 0; i < objects.Count; ++i) 66 | { 67 | meshFilters[i] = objects[i].meshFilter; 68 | GameObject.Destroy(objects[i].gameObject); 69 | } 70 | 71 | CombineInstance[] combine = new CombineInstance[meshFilters.Length]; 72 | for (var i = 0; i < meshFilters.Length; ++i) 73 | { 74 | combine[i].mesh = meshFilters[i].sharedMesh; 75 | combine[i].transform = meshFilters[i].transform.localToWorldMatrix; 76 | } 77 | 78 | meshFilter.mesh = new Mesh(); 79 | meshFilter.mesh.CombineMeshes(combine); 80 | 81 | return gameObject; 82 | } 83 | 84 | public static Vector3 IntersectionPoint (Vector3 p1, Vector3 dir1, 85 | Vector3 p2, Vector3 dir2) 86 | { 87 | var dir_cross = Vector3.Cross(dir1, dir2); 88 | var tmp_cross = Vector3.Cross(p2 - p1, dir2); 89 | 90 | float c1; 91 | if (dir_cross.x != 0f) 92 | c1 = tmp_cross.x / dir_cross.x; 93 | else if (dir_cross.y != 0f) 94 | c1 = tmp_cross.y / dir_cross.y; 95 | else if (dir_cross.z != 0f) 96 | c1 = tmp_cross.z / dir_cross.z; 97 | else 98 | throw new System.DivideByZeroException("Result of cross product is Vector3(0,0,0)!"); 99 | 100 | return p1 + c1 * dir1; 101 | } 102 | 103 | public static void PrintVector (string s, Vector3 v) 104 | { 105 | Debug.Log(s + " " + v.x + " " + v.y + " " + v.z); 106 | } 107 | } 108 | 109 | } // namespace Thesis -------------------------------------------------------------------------------- /Assets/Standard Assets/General/DrawableObject.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using Thesis.Interface; 3 | 4 | namespace Thesis { 5 | 6 | public class DrawableObject : ProceduralObject, 7 | IDrawable, 8 | ICombinable 9 | { 10 | /*************** FIELDS ***************/ 11 | 12 | public string name; 13 | 14 | public Material material; 15 | 16 | public MeshFilter meshFilter; 17 | 18 | public Mesh mesh; 19 | 20 | public Vector3 meshOrigin; 21 | 22 | public Vector3[] boundaries; 23 | 24 | public Vector3[] vertices; 25 | 26 | public int[] triangles; 27 | 28 | /*************** CONSTRUCTORS ***************/ 29 | 30 | public DrawableObject (string name = "drawableObject", string materialName = null) 31 | { 32 | this.name = name; 33 | if (materialName != null) 34 | this.material = MaterialManager.Instance.Get(materialName); 35 | } 36 | 37 | /*************** METHODS ***************/ 38 | 39 | /// 40 | /// Calculates the intersection point of the lines formed by each two points in 3D space. 41 | /// Points a1 and a2 form the first line and points b1 and b2 form the second. 42 | /// Maths found here: http://mathforum.org/library/drmath/view/62814.html 43 | /// 44 | public virtual void FindMeshOrigin (Vector3 a1, Vector3 a2, Vector3 b1, Vector3 b2) 45 | { 46 | var a_dir = a1 - a2; // the direction vector of the first line 47 | var b_dir = b1 - b2; // the direction vector of the second line 48 | var dir_cross = Vector3.Cross(a_dir, b_dir); 49 | var tmp_cross = Vector3.Cross(b1 - a1, b_dir); 50 | 51 | float c1; 52 | if (dir_cross.x != 0f) 53 | c1 = tmp_cross.x / dir_cross.x; 54 | else if (dir_cross.y != 0f) 55 | c1 = tmp_cross.y / dir_cross.y; 56 | else if (dir_cross.z != 0f) 57 | c1 = tmp_cross.z / dir_cross.z; 58 | else 59 | throw new System.DivideByZeroException("Result of cross product is Vector3(0,0,0)!"); 60 | 61 | meshOrigin = a1 + c1 * a_dir; 62 | } 63 | 64 | public virtual void FindVertices () 65 | { 66 | throw new System.NotImplementedException(); 67 | } 68 | 69 | public virtual void FindTriangles () 70 | { 71 | throw new System.NotImplementedException(); 72 | } 73 | 74 | public virtual void Draw () 75 | { 76 | gameObject = new GameObject(name); 77 | meshFilter = gameObject.AddComponent(); 78 | var renderer = gameObject.AddComponent(); 79 | 80 | gameObject.SetActive(false); 81 | gameObject.isStatic = true; 82 | if (material != null) 83 | renderer.sharedMaterial = material; 84 | 85 | mesh = new Mesh(); 86 | mesh.Clear(); 87 | mesh.vertices = vertices; 88 | mesh.triangles = triangles; 89 | mesh.uv = new Vector2[mesh.vertices.Length]; 90 | mesh.RecalculateNormals(); 91 | mesh.Optimize(); 92 | meshFilter.sharedMesh = mesh; 93 | } 94 | 95 | public virtual void Destroy () 96 | { 97 | GameObject.DestroyImmediate(mesh); 98 | GameObject.DestroyImmediate(gameObject); 99 | } 100 | 101 | /*************** INTERFACE EXPLICIT IMPLEMENTATION ***************/ 102 | 103 | Vector3[] IDrawable.vertices 104 | { 105 | get { return vertices; } 106 | } 107 | 108 | int[] IDrawable.triangles 109 | { 110 | get { return triangles; } 111 | } 112 | 113 | GameObject ICombinable.gameObject 114 | { 115 | get { return gameObject; } 116 | } 117 | 118 | MeshFilter ICombinable.meshFilter 119 | { 120 | get { return meshFilter; } 121 | } 122 | 123 | Material ICombinable.material 124 | { 125 | get { return material; } 126 | } 127 | 128 | Mesh ICombinable.mesh 129 | { 130 | get { return mesh; } 131 | } 132 | } 133 | 134 | } // namespace Thesis -------------------------------------------------------------------------------- /Assets/Standard Assets/Balcony/BalconyFloor.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace Thesis { 4 | 5 | public class BalconyFloor : DrawableObject 6 | { 7 | /*************** FIELDS ***************/ 8 | 9 | public readonly Balcony parentBalcony; 10 | 11 | public float height; 12 | 13 | public float width; 14 | 15 | public float depth; 16 | 17 | public BuildingMesh parentBuilding 18 | { 19 | get { return parentBalcony.parentBuilding; } 20 | } 21 | 22 | /*************** CONSTRUCTORS ***************/ 23 | 24 | public BalconyFloor (Balcony parent) 25 | { 26 | parentBalcony = parent; 27 | 28 | height = parentBuilding.balconyFloorHeight; 29 | width = parentBuilding.balconyFloorWidth; 30 | depth = parentBuilding.balconyFloorDepth; 31 | 32 | var tmp_right = parentBalcony.parentFace.right * width; 33 | var tmp_normal = parentBalcony.parentFace.normal * depth; 34 | var tmp_up = -(height - 0.01f) * Vector3.up; 35 | 36 | boundaries = new Vector3[8]; 37 | boundaries[0] = parentBalcony.boundaries[0] + tmp_right + tmp_normal + tmp_up; 38 | boundaries[1] = parentBalcony.boundaries[1] - tmp_right + tmp_normal + tmp_up; 39 | boundaries[2] = parentBalcony.boundaries[1] - tmp_right - tmp_normal + tmp_up; 40 | boundaries[3] = parentBalcony.boundaries[0] + tmp_right - tmp_normal + tmp_up; 41 | 42 | for (var i = 0; i < 4; ++i) 43 | boundaries[i + 4] = boundaries[i] + Vector3.up * height; 44 | 45 | FindMeshOrigin(boundaries[0], 46 | boundaries[6], 47 | boundaries[2], 48 | boundaries[4]); 49 | 50 | for (var i = 0; i < boundaries.Length; ++i) 51 | boundaries[i] -= meshOrigin; 52 | } 53 | 54 | public override void FindVertices () 55 | { 56 | vertices = new Vector3[boundaries.Length * 3]; 57 | for (int i = 0; i < 3; ++i) 58 | System.Array.Copy(boundaries, 0, vertices, i * boundaries.Length, boundaries.Length); 59 | } 60 | 61 | public override void FindTriangles () 62 | { 63 | triangles = new int[36]; 64 | 65 | // bottom 66 | triangles[0] = 0; 67 | triangles[1] = 2; 68 | triangles[2] = 1; 69 | 70 | triangles[3] = 0; 71 | triangles[4] = 3; 72 | triangles[5] = 2; 73 | 74 | // top 75 | triangles[6] = 4; 76 | triangles[7] = 5; 77 | triangles[8] = 6; 78 | 79 | triangles[9] = 4; 80 | triangles[10] = 6; 81 | triangles[11] = 7; 82 | 83 | // left 84 | triangles[12] = 9; // 1 + 8 85 | triangles[13] = 10; // 2 + 8 86 | triangles[14] = 13; // 5 + 8 87 | 88 | triangles[15] = 10; // 2 + 8 89 | triangles[16] = 14; // 6 + 8 90 | triangles[17] = 13; // 5 + 8 91 | 92 | // right 93 | triangles[18] = 8; // 0 + 8 94 | triangles[19] = 12; // 4 + 8 95 | triangles[20] = 11; // 3 + 8 96 | 97 | triangles[21] = 11; // 3 + 8 98 | triangles[22] = 12; // 4 + 8 99 | triangles[23] = 15; // 7 + 8 100 | 101 | // front 102 | triangles[24] = 16; // 0 + 16 103 | triangles[25] = 17; // 1 + 16 104 | triangles[26] = 20; // 4 + 16 105 | 106 | triangles[27] = 17; // 1 + 16 107 | triangles[28] = 21; // 5 + 16 108 | triangles[29] = 20; // 4 + 16 109 | 110 | // back 111 | triangles[30] = 18; // 2 + 16 112 | triangles[31] = 19; // 3 + 16 113 | triangles[32] = 23; // 7 + 16 114 | 115 | triangles[33] = 18; // 2 + 16 116 | triangles[34] = 23; // 7 + 16 117 | triangles[35] = 22; // 6 + 16 118 | } 119 | 120 | public override void Draw () 121 | { 122 | base.Draw(); 123 | 124 | gameObject.transform.position = meshOrigin + parentBuilding.meshOrigin; 125 | gameObject.transform.parent = parentBuilding.parent.gameObject.transform; 126 | } 127 | } 128 | 129 | } // namespace Thesis -------------------------------------------------------------------------------- /Assets/Standard Assets/Window/Window.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace Thesis { 4 | 5 | public class Window : FaceComponent 6 | { 7 | /*************** FIELDS ***************/ 8 | 9 | public Shutter rightShutter; 10 | 11 | public Shutter leftShutter; 12 | 13 | public ComponentDecor decor; 14 | 15 | public Building masterParent 16 | { 17 | get { return parentBuilding.parent; } 18 | } 19 | 20 | /*************** CONSTRUCTORS ***************/ 21 | 22 | public Window (Face parent, Vector3 dr, Vector3 dl, ComponentCoordinate position) 23 | : base(parent, position) 24 | { 25 | height = parentBuilding.windowHeight; 26 | depth = 0.4f; 27 | width = (dr - dl).magnitude; 28 | float height_modifier = parentBuilding.floorHeight / 2.25f - height / 2; 29 | 30 | if (masterParent.windowWidth > 0f) 31 | { 32 | var mod = (masterParent.windowWidth - width) / 2f; 33 | width = masterParent.windowWidth; 34 | dr += mod * parentFace.right; 35 | dl -= mod * parentFace.right; 36 | } 37 | 38 | boundaries = new Vector3[4]; 39 | boundaries[0] = new Vector3(dr.x, dr.y + height_modifier, dr.z); 40 | boundaries[1] = new Vector3(dl.x, dl.y + height_modifier, dl.z); 41 | boundaries[2] = new Vector3(dl.x, dl.y + height + height_modifier, dl.z); 42 | boundaries[3] = new Vector3(dr.x, dr.y + height + height_modifier, dr.z); 43 | 44 | frame = new ComponentFrame(this); 45 | frame.name = "neo_window_frame"; 46 | frame.material = MaterialManager.Instance.Get("ComponentFrame"); 47 | parentBuilding.parent.AddCombinable(frame.material.name, frame); 48 | 49 | body = new WindowBody(this); 50 | body.name = "neo_window_body"; 51 | body.material = parentBuilding.parent.windowMaterial; 52 | parentBuilding.parent.AddCombinable(body.material.name, body); 53 | 54 | rightShutter = new Shutter(this, ShutterSide.Right); 55 | rightShutter.name = "right_shutter"; 56 | rightShutter.material = parentBuilding.parent.shutterMaterial; 57 | parentBuilding.parent.AddCombinable(rightShutter.material.name, rightShutter); 58 | 59 | leftShutter = new Shutter(this, ShutterSide.Left); 60 | leftShutter.name = "left_shutter"; 61 | leftShutter.material = parentBuilding.parent.shutterMaterial; 62 | parentBuilding.parent.AddCombinable(leftShutter.material.name, leftShutter); 63 | 64 | if (position.floor >= 1) 65 | { 66 | decor = new ComponentDecor(this); 67 | decor.name = "window_decor"; 68 | decor.material = parentBuilding.parent.compDecorMaterial; 69 | parentBuilding.parent.AddCombinable(decor.material.name, decor); 70 | } 71 | else 72 | { 73 | decor = new ComponentDecor(this, true); 74 | decor.name = "window_decor"; 75 | decor.material = parentBuilding.parent.simpleCompDecorMaterial; 76 | parentBuilding.parent.AddCombinable(decor.material.name, decor); 77 | } 78 | } 79 | 80 | /*************** METHODS ***************/ 81 | 82 | public override void Draw () 83 | { 84 | //base.Draw(); 85 | 86 | frame.FindVertices(); 87 | frame.FindTriangles(); 88 | frame.Draw(); 89 | 90 | body.FindVertices(); 91 | body.FindTriangles(); 92 | body.Draw(); 93 | 94 | //Shutter.SetAngles(); 95 | 96 | rightShutter.FindVertices(); 97 | rightShutter.FindTriangles(); 98 | rightShutter.Draw(); 99 | 100 | leftShutter.FindVertices(); 101 | leftShutter.FindTriangles(); 102 | leftShutter.Draw(); 103 | 104 | if (decor != null) 105 | { 106 | decor.FindVertices(); 107 | decor.FindTriangles(); 108 | decor.Draw(); 109 | } 110 | } 111 | 112 | public override void Destroy() 113 | { 114 | base.Destroy(); 115 | 116 | rightShutter.Destroy(); 117 | leftShutter.Destroy(); 118 | 119 | if (decor != null) 120 | decor.Destroy(); 121 | } 122 | } 123 | 124 | } // namespace Thesis -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Unity3D 3 | ################# 4 | 5 | *.sln 6 | *.csproj 7 | *.unityproj 8 | *.suo 9 | Temp/* 10 | Library/* 11 | *.userprefs 12 | 13 | 14 | ################# 15 | ## Eclipse 16 | ################# 17 | 18 | *.pydevproject 19 | .project 20 | .metadata 21 | bin/ 22 | tmp/ 23 | *.tmp 24 | *.bak 25 | *.swp 26 | *~.nib 27 | local.properties 28 | .classpath 29 | .settings/ 30 | .loadpath 31 | 32 | # External tool builders 33 | .externalToolBuilders/ 34 | 35 | # Locally stored "Eclipse launch configurations" 36 | *.launch 37 | 38 | # CDT-specific 39 | .cproject 40 | 41 | # PDT-specific 42 | .buildpath 43 | 44 | 45 | ################# 46 | ## Visual Studio 47 | ################# 48 | 49 | ## Ignore Visual Studio temporary files, build results, and 50 | ## files generated by popular Visual Studio add-ons. 51 | 52 | # User-specific files 53 | *.suo 54 | *.user 55 | *.sln.docstates 56 | 57 | # Build results 58 | 59 | [Dd]ebug/ 60 | [Rr]elease/ 61 | x64/ 62 | build/ 63 | [Bb]in/ 64 | [Oo]bj/ 65 | 66 | # MSTest test Results 67 | [Tt]est[Rr]esult*/ 68 | [Bb]uild[Ll]og.* 69 | 70 | *_i.c 71 | *_p.c 72 | *.ilk 73 | *.meta 74 | *.obj 75 | *.pch 76 | *.pdb 77 | *.pgc 78 | *.pgd 79 | *.rsp 80 | *.sbr 81 | *.tlb 82 | *.tli 83 | *.tlh 84 | *.tmp 85 | *.tmp_proj 86 | *.log 87 | *.vspscc 88 | *.vssscc 89 | .builds 90 | *.pidb 91 | *.log 92 | *.scc 93 | 94 | # Visual C++ cache files 95 | ipch/ 96 | *.aps 97 | *.ncb 98 | *.opensdf 99 | *.sdf 100 | *.cachefile 101 | 102 | # Visual Studio profiler 103 | *.psess 104 | *.vsp 105 | *.vspx 106 | 107 | # Guidance Automation Toolkit 108 | *.gpState 109 | 110 | # ReSharper is a .NET coding add-in 111 | _ReSharper*/ 112 | *.[Rr]e[Ss]harper 113 | 114 | # TeamCity is a build add-in 115 | _TeamCity* 116 | 117 | # DotCover is a Code Coverage Tool 118 | *.dotCover 119 | 120 | # NCrunch 121 | *.ncrunch* 122 | .*crunch*.local.xml 123 | 124 | # Installshield output folder 125 | [Ee]xpress/ 126 | 127 | # DocProject is a documentation generator add-in 128 | DocProject/buildhelp/ 129 | DocProject/Help/*.HxT 130 | DocProject/Help/*.HxC 131 | DocProject/Help/*.hhc 132 | DocProject/Help/*.hhk 133 | DocProject/Help/*.hhp 134 | DocProject/Help/Html2 135 | DocProject/Help/html 136 | 137 | # Click-Once directory 138 | publish/ 139 | 140 | # Publish Web Output 141 | *.Publish.xml 142 | *.pubxml 143 | 144 | # NuGet Packages Directory 145 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 146 | #packages/ 147 | 148 | # Windows Azure Build Output 149 | csx 150 | *.build.csdef 151 | 152 | # Windows Store app package directory 153 | AppPackages/ 154 | 155 | # Others 156 | sql/ 157 | *.Cache 158 | ClientBin/ 159 | [Ss]tyle[Cc]op.* 160 | ~$* 161 | *~ 162 | *.dbmdl 163 | *.[Pp]ublish.xml 164 | *.pfx 165 | *.publishsettings 166 | 167 | # RIA/Silverlight projects 168 | Generated_Code/ 169 | 170 | # Backup & report files from converting an old project file to a newer 171 | # Visual Studio version. Backup files are not needed, because we have git ;-) 172 | _UpgradeReport_Files/ 173 | Backup*/ 174 | UpgradeLog*.XML 175 | UpgradeLog*.htm 176 | 177 | # SQL Server files 178 | App_Data/*.mdf 179 | App_Data/*.ldf 180 | 181 | ############# 182 | ## Windows detritus 183 | ############# 184 | 185 | # Windows image file caches 186 | Thumbs.db 187 | ehthumbs.db 188 | 189 | # Folder config file 190 | Desktop.ini 191 | 192 | # Recycle Bin used on file shares 193 | $RECYCLE.BIN/ 194 | 195 | # Mac crap 196 | .DS_Store 197 | 198 | 199 | ############# 200 | ## Python 201 | ############# 202 | 203 | *.py[co] 204 | 205 | # Packages 206 | *.egg 207 | *.egg-info 208 | dist/ 209 | build/ 210 | eggs/ 211 | parts/ 212 | var/ 213 | sdist/ 214 | develop-eggs/ 215 | .installed.cfg 216 | 217 | # Installer logs 218 | pip-log.txt 219 | 220 | # Unit test / coverage reports 221 | .coverage 222 | .tox 223 | 224 | #Translations 225 | *.mo 226 | 227 | #Mr Developer 228 | .mr.developer.cfg 229 | -------------------------------------------------------------------------------- /Assets/Scripts/CityMapController.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using Thesis; 3 | using System.Linq; 4 | 5 | public class CityMapController : MonoBehaviour { 6 | 7 | private Block block; 8 | 9 | private bool _drawGizmos = true; 10 | private bool _drawFirstBlock = true; 11 | private bool _drawBlocks = true; 12 | private bool _drawSideWalk = true; 13 | private bool _drawFirstLot = true; 14 | private bool _drawLots = true; 15 | 16 | void Start () 17 | { 18 | block = new Block(); 19 | block.Bisect(); 20 | } 21 | 22 | void Update () 23 | { 24 | if (Input.GetKeyUp(KeyCode.B)) 25 | { 26 | AddBuildings(); 27 | CityMapManager.Instance.DrawRoads(); 28 | CityMapManager.Instance.DrawSidewalks(); 29 | CityMapManager.Instance.DrawLots(); 30 | } 31 | 32 | if (Input.GetKeyUp(KeyCode.R)) 33 | { 34 | BuildingManager.Instance.DestroyBuildings(); 35 | block = new Block(); 36 | block.Bisect(); 37 | } 38 | 39 | if (Input.GetKeyUp(KeyCode.G)) 40 | _drawGizmos = !_drawGizmos; 41 | 42 | if (Input.GetKeyUp(KeyCode.Alpha1)) 43 | _drawFirstBlock = !_drawFirstBlock; 44 | 45 | if (Input.GetKeyUp(KeyCode.Alpha2)) 46 | _drawBlocks = !_drawBlocks; 47 | 48 | if (Input.GetKeyUp(KeyCode.Alpha3)) 49 | _drawSideWalk = !_drawSideWalk; 50 | 51 | if (Input.GetKeyUp(KeyCode.Alpha4)) 52 | _drawFirstLot = !_drawFirstLot; 53 | 54 | if (Input.GetKeyUp(KeyCode.Alpha5)) 55 | _drawLots = !_drawLots; 56 | 57 | if (Input.GetKeyUp(KeyCode.Alpha0)) 58 | { 59 | _drawFirstBlock = false; 60 | _drawBlocks = false; 61 | _drawSideWalk = false; 62 | _drawFirstLot = false; 63 | _drawLots = false; 64 | } 65 | } 66 | 67 | private void AddBuildings () 68 | { 69 | BuildingManager.Instance.DestroyBuildings(); 70 | foreach (Block b in CityMapManager.Instance.blocks) 71 | foreach (BuildingLot l in b.finalLots) 72 | BuildingManager.Instance.Build(l); 73 | } 74 | 75 | void OnPostRender () 76 | { 77 | if (_drawGizmos) 78 | { 79 | if (_drawFirstBlock) 80 | { 81 | MaterialManager.Instance.Get("line_block").SetPass(0); 82 | GL.Begin(GL.LINES); 83 | foreach (Edge e in block.edges) 84 | { 85 | GL.Vertex(e.start); 86 | GL.Vertex(e.end); 87 | } 88 | GL.End(); 89 | } 90 | 91 | if (_drawBlocks) 92 | { 93 | MaterialManager.Instance.Get("line_block").SetPass(0); 94 | GL.Begin(GL.LINES); 95 | foreach (Block b in CityMapManager.Instance.blocks) 96 | foreach (Edge e in b.edges) 97 | { 98 | GL.Vertex(e.start); 99 | GL.Vertex(e.end); 100 | } 101 | GL.End(); 102 | } 103 | 104 | if (_drawSideWalk) 105 | { 106 | MaterialManager.Instance.Get("line_sidewalk").SetPass(0); 107 | GL.Begin(GL.LINES); 108 | foreach (Sidewalk s in CityMapManager.Instance.sidewalks) 109 | foreach (Edge e in s.edges) 110 | { 111 | GL.Vertex(e.start); 112 | GL.Vertex(e.end); 113 | } 114 | GL.End(); 115 | } 116 | 117 | if (_drawFirstLot) 118 | { 119 | MaterialManager.Instance.Get("line_lot").SetPass(0); 120 | GL.Begin(GL.LINES); 121 | foreach (Block b in CityMapManager.Instance.blocks) 122 | foreach (Edge e in b.initialLot.edges) 123 | { 124 | GL.Vertex(e.start); 125 | GL.Vertex(e.end); 126 | } 127 | GL.End(); 128 | } 129 | 130 | if (_drawLots) 131 | { 132 | MaterialManager.Instance.Get("line_lot").SetPass(0); 133 | GL.Begin(GL.LINES); 134 | foreach (Block b in CityMapManager.Instance.blocks) 135 | foreach (BuildingLot l in b.finalLots) 136 | foreach (Edge e in l.edges) 137 | { 138 | GL.Vertex(e.start); 139 | GL.Vertex(e.end); 140 | } 141 | GL.End(); 142 | } 143 | } 144 | } 145 | } -------------------------------------------------------------------------------- /Assets/Standard Assets/Managers/CityMapManager.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using UnityEngine; 3 | 4 | namespace Thesis { 5 | 6 | public sealed class CityMapManager 7 | { 8 | private const float _tolerance = 5f; 9 | 10 | private static readonly CityMapManager _instance = new CityMapManager(); 11 | public static CityMapManager Instance 12 | { 13 | get { return _instance; } 14 | } 15 | 16 | private List _blocks; 17 | public IList blocks 18 | { 19 | get { return _blocks.AsReadOnly(); } 20 | } 21 | 22 | private List _lots; 23 | public IList lots 24 | { 25 | get { return _lots.AsReadOnly(); } 26 | } 27 | 28 | private List _nodes; 29 | public IList nodes 30 | { 31 | get { return _nodes.AsReadOnly(); } 32 | } 33 | 34 | private List _roads; 35 | public IList roads 36 | { 37 | get { return _roads; } 38 | } 39 | 40 | private List _sidewalks; 41 | public IList sidewalks 42 | { 43 | get { return _sidewalks; } 44 | } 45 | 46 | private List _drawableLots; 47 | public IList drawableLots 48 | { 49 | get { return _drawableLots; } 50 | } 51 | 52 | private CityMapManager () 53 | { 54 | _blocks = new List(); 55 | _nodes = new List(); 56 | _lots = new List(); 57 | _roads = new List(); 58 | _sidewalks = new List(); 59 | _drawableLots = new List(); 60 | } 61 | 62 | public void Add (Block block) 63 | { 64 | _blocks.Add(block); 65 | } 66 | 67 | public void Add (BuildingLot lot) 68 | { 69 | _lots.Add(lot); 70 | } 71 | 72 | public int Add (Vector3 node) 73 | { 74 | var n = _nodes.FindIndex(0, delegate (Vector3 v) { 75 | return (Mathf.Abs(v.x - node.x) <= _tolerance && 76 | Mathf.Abs(v.z - node.z) <= _tolerance); 77 | }); 78 | if (n == -1) 79 | _nodes.Add(node); 80 | return n; 81 | } 82 | 83 | public void AddRoad (Block block) 84 | { 85 | Road r = new Road(block); 86 | r.name = "road"; 87 | r.material = MaterialManager.Instance.Get("mat_road"); 88 | _roads.Add(r); 89 | } 90 | 91 | public void DrawRoads () 92 | { 93 | foreach (Road r in _roads) 94 | { 95 | r.FindVertices(); 96 | r.FindTriangles(); 97 | r.Draw(); 98 | r.gameObject.SetActive(true); 99 | } 100 | } 101 | 102 | public void DestroyRoads () 103 | { 104 | foreach (Road r in _roads) 105 | r.Destroy(); 106 | } 107 | 108 | public void AddSidewalk (Block block) 109 | { 110 | Sidewalk s = new Sidewalk(block); 111 | s.name = "sidewalk"; 112 | s.material = MaterialManager.Instance.Get("mat_sidewalk"); 113 | _sidewalks.Add(s); 114 | } 115 | 116 | public void DrawSidewalks () 117 | { 118 | foreach (Sidewalk s in _sidewalks) 119 | { 120 | s.FindVertices(); 121 | s.FindTriangles(); 122 | s.Draw(); 123 | s.gameObject.SetActive(true); 124 | } 125 | } 126 | 127 | public void DestroySidewalks () 128 | { 129 | foreach (Sidewalk s in _sidewalks) 130 | s.Destroy(); 131 | } 132 | 133 | public void AddDrawableLot (BuildingLot lot) 134 | { 135 | lot.name = "buildinglot"; 136 | lot.material = MaterialManager.Instance.Get("mat_lot"); 137 | _drawableLots.Add(lot); 138 | } 139 | 140 | public void DrawLots () 141 | { 142 | foreach (BuildingLot lot in _drawableLots) 143 | { 144 | lot.FindVertices(); 145 | lot.FindTriangles(); 146 | lot.Draw(); 147 | lot.gameObject.SetActive(true); 148 | } 149 | } 150 | 151 | public void DestroyLots () 152 | { 153 | foreach (BuildingLot lot in _drawableLots) 154 | lot.Destroy(); 155 | } 156 | 157 | public void Clear () 158 | { 159 | _blocks.Clear(); 160 | _lots.Clear(); 161 | _nodes.Clear(); 162 | DestroyRoads(); 163 | _roads.Clear(); 164 | DestroySidewalks(); 165 | _sidewalks.Clear(); 166 | DestroyLots(); 167 | _drawableLots.Clear(); 168 | } 169 | } 170 | 171 | } // namespace Thesis -------------------------------------------------------------------------------- /Assets/Standard Assets/Balcony/Balcony.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace Thesis { 4 | 5 | public class Balcony : FaceComponent 6 | { 7 | /*************** FIELDS ***************/ 8 | 9 | public BalconyFloor balconyFloor; 10 | 11 | public BalconyRail balconyRail; 12 | 13 | public Shutter rightShutter; 14 | 15 | public Shutter leftShutter; 16 | 17 | public ComponentDecor decor; 18 | 19 | public Building masterParent 20 | { 21 | get { return parentBuilding.parent; } 22 | } 23 | 24 | /*************** CONSTRUCTORS ***************/ 25 | 26 | public Balcony (Face parent, Vector3 dr, Vector3 dl, ComponentCoordinate position) 27 | : base(parent, position) 28 | { 29 | height = parentBuilding.balconyHeight; 30 | width = (dr - dl).magnitude; 31 | depth = 0.2f; 32 | 33 | if (masterParent.balconyWidth > 0f) 34 | { 35 | var mod = (masterParent.balconyWidth - width) / 2f; 36 | width = masterParent.balconyWidth; 37 | dr += mod * parentFace.right; 38 | dl -= mod * parentFace.right; 39 | } 40 | 41 | boundaries = new Vector3[4]; 42 | boundaries[0] = dr; 43 | boundaries[1] = dl; 44 | boundaries[2] = new Vector3(dl.x, dl.y + height, dl.z); 45 | boundaries[3] = new Vector3(dr.x, dr.y + height, dr.z); 46 | 47 | frame = new BalconyFrame(this); 48 | frame.name = "neo_balcony_frame"; 49 | frame.material = MaterialManager.Instance.Get("ComponentFrame"); 50 | parentBuilding.parent.AddCombinable(frame.material.name, frame); 51 | 52 | body = new BalconyBody(this); 53 | body.name = "neo_balcony_body"; 54 | body.material = parentBuilding.parent.balconyDoorMaterial; 55 | parentBuilding.parent.AddCombinable(body.material.name, body); 56 | 57 | balconyFloor = new BalconyFloor(this); 58 | balconyFloor.name = "neo_balcony_floor"; 59 | balconyFloor.material = parentBuilding.material; 60 | parentBuilding.parent.AddCombinable(balconyFloor.material.name, balconyFloor); 61 | 62 | balconyRail = new BalconyRail(balconyFloor); 63 | balconyRail.name = "neo_balcony_rail"; 64 | balconyRail.material = MaterialManager.Instance.Get("mat_balcony_rail"); 65 | parentBuilding.parent.AddCombinable(balconyRail.material.name, balconyRail); 66 | 67 | rightShutter = new Shutter(this, ShutterSide.Right); 68 | rightShutter.name = "bal_right_shutter"; 69 | rightShutter.material = parentBuilding.parent.shutterMaterial; 70 | parentBuilding.parent.AddCombinable(rightShutter.material.name, rightShutter); 71 | 72 | leftShutter = new Shutter(this, ShutterSide.Left); 73 | leftShutter.name = "bal_left_shutter"; 74 | leftShutter.material = parentBuilding.parent.shutterMaterial; 75 | parentBuilding.parent.AddCombinable(leftShutter.material.name, leftShutter); 76 | 77 | if (position.floor >= 1) 78 | { 79 | decor = new ComponentDecor(this); 80 | decor.name = "window_decor"; 81 | decor.material = parentBuilding.parent.compDecorMaterial; 82 | parentBuilding.parent.AddCombinable(decor.material.name, decor); 83 | } 84 | else 85 | { 86 | decor = new ComponentDecor(this, true); 87 | decor.name = "window_decor"; 88 | decor.material = parentBuilding.parent.simpleCompDecorMaterial; 89 | parentBuilding.parent.AddCombinable(decor.material.name, decor); 90 | } 91 | } 92 | 93 | /*************** METHODS ***************/ 94 | 95 | public override void Draw () 96 | { 97 | //base.Draw(); 98 | 99 | body.FindVertices(); 100 | body.FindTriangles(); 101 | body.Draw(); 102 | 103 | frame.FindVertices(); 104 | frame.FindTriangles(); 105 | frame.Draw(); 106 | 107 | balconyFloor.FindVertices(); 108 | balconyFloor.FindTriangles(); 109 | balconyFloor.Draw(); 110 | 111 | balconyRail.FindVertices(); 112 | balconyRail.FindTriangles(); 113 | balconyRail.Draw(); 114 | 115 | //Shutter.SetAngles(); 116 | 117 | rightShutter.FindVertices(); 118 | rightShutter.FindTriangles(); 119 | rightShutter.Draw(); 120 | 121 | leftShutter.FindVertices(); 122 | leftShutter.FindTriangles(); 123 | leftShutter.Draw(); 124 | 125 | if (decor != null) 126 | { 127 | decor.FindVertices(); 128 | decor.FindTriangles(); 129 | decor.Draw(); 130 | } 131 | } 132 | 133 | public override void Destroy() 134 | { 135 | base.Destroy(); 136 | 137 | balconyFloor.Destroy(); 138 | balconyRail.Destroy(); 139 | rightShutter.Destroy(); 140 | leftShutter.Destroy(); 141 | 142 | if (decor != null) 143 | decor.Destroy(); 144 | } 145 | } 146 | 147 | } // namespace Thesis -------------------------------------------------------------------------------- /Assets/Standard Assets/Managers/BuildingManager.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections.Generic; 3 | 4 | namespace Thesis { 5 | 6 | public sealed class BuildingManager 7 | { 8 | private static readonly BuildingManager _instance = new BuildingManager(); 9 | public static BuildingManager Instance 10 | { 11 | get { return _instance; } 12 | } 13 | 14 | private List _buildings; 15 | public IList buildings 16 | { 17 | get { return _buildings.AsReadOnly(); } 18 | } 19 | 20 | private BuildingManager () 21 | { 22 | _buildings = new List(); 23 | } 24 | 25 | public void Init () { } 26 | 27 | public void CreateNeoclassical (BuildMode mode) 28 | { 29 | switch (mode) 30 | { 31 | case BuildMode.Many: 32 | for (int i = 0; i < 25; ++i) 33 | { 34 | float x_mod = i * 30f; 35 | for (int j = 0; j < 25; ++j) 36 | { 37 | float z_mod = j * 15f; 38 | int dice = Util.RollDice(new float[] { 0.25f, 0.25f, 0.25f, 0.25f }); 39 | switch (dice) 40 | { 41 | case 1: 42 | Build(new Vector3(x_mod + 9f, 0f, z_mod + 3.5f), 43 | new Vector3(x_mod + 9f, 0f, z_mod), 44 | new Vector3(x_mod, 0f, z_mod), 45 | new Vector3(x_mod, 0f, z_mod + 3.5f)); 46 | break; 47 | 48 | case 2: 49 | Build(new Vector3(x_mod + 11f, 0f, z_mod + 4f), 50 | new Vector3(x_mod + 11f, 0f, z_mod), 51 | new Vector3(x_mod, 0f, z_mod), 52 | new Vector3(x_mod, 0f, z_mod + 4f)); 53 | break; 54 | 55 | case 3: 56 | Build(new Vector3(x_mod + 15f, 0f, z_mod + 6f), 57 | new Vector3(x_mod + 15f, 0f, z_mod), 58 | new Vector3(x_mod, 0f, z_mod), 59 | new Vector3(x_mod, 0f, z_mod + 6f)); 60 | break; 61 | 62 | case 4: 63 | Build(new Vector3(x_mod + 19f, 0f, z_mod + 8f), 64 | new Vector3(x_mod + 19f, 0f, z_mod), 65 | new Vector3(x_mod, 0f, z_mod), 66 | new Vector3(x_mod, 0f, z_mod + 8f)); 67 | break; 68 | } 69 | } 70 | } 71 | break; 72 | 73 | case BuildMode.Two: 74 | Build(new Vector3(8f, 0f, 4f), 75 | new Vector3(8f, 0f, 0f), 76 | new Vector3(0f, 0f, 0f), 77 | new Vector3(0f, 0f, 4f)); 78 | break; 79 | 80 | case BuildMode.Three: 81 | Build(new Vector3(11f, 0f, 4f), 82 | new Vector3(11f, 0f, 0f), 83 | new Vector3(0f, 0f, 0f), 84 | new Vector3(0f, 0f, 4f)); 85 | 86 | //Build(new Vector3(20f, 0f, 4f), 87 | // new Vector3(37f, 0f, 4f), 88 | // new Vector3(37f, 0f, 0f), 89 | // new Vector3(20f, 0f, 0f)); 90 | break; 91 | 92 | case BuildMode.Four: 93 | Build(new Vector3(15f, 0f, 6f), 94 | new Vector3(15f, 0f, 0f), 95 | new Vector3(0f, 0f, 0f), 96 | new Vector3(0f, 0f, 6f)); 97 | break; 98 | 99 | case BuildMode.Five: 100 | Build(new Vector3(19f, 0f, 8f), 101 | new Vector3(19f, 0f, 0f), 102 | new Vector3(0f, 0f, 0f), 103 | new Vector3(0f, 0f, 8f)); 104 | break; 105 | } 106 | } 107 | 108 | public void DestroyBuildings () 109 | { 110 | foreach (Building n in _buildings) 111 | n.Destroy(); 112 | _buildings.Clear(); 113 | } 114 | 115 | public void Build (Vector3 p1, Vector3 p2, Vector3 p3, Vector3 p4) 116 | { 117 | var n = new Building(p1, p2, p3, p4); 118 | n.buildingMesh.FindVertices(); 119 | n.buildingMesh.FindTriangles(); 120 | n.buildingMesh.Draw(); 121 | n.CombineSubmeshes(); 122 | n.gameObject.SetActive(true); 123 | foreach (Transform t in n.gameObject.transform) { 124 | t.gameObject.SetActive(true); 125 | } 126 | _buildings.Add(n); 127 | } 128 | 129 | public void Build (BuildingLot lot) 130 | { 131 | var n = new Building(lot); 132 | n.buildingMesh.FindVertices(); 133 | n.buildingMesh.FindTriangles(); 134 | n.buildingMesh.Draw(); 135 | n.CombineSubmeshes(); 136 | n.gameObject.SetActive(true); 137 | foreach (Transform t in n.gameObject.transform) { 138 | t.gameObject.SetActive(true); 139 | } 140 | _buildings.Add(n); 141 | } 142 | } 143 | 144 | } // namespace Thesis -------------------------------------------------------------------------------- /Assets/Standard Assets/Balcony/BalconyRail.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace Thesis { 4 | 5 | public class BalconyRail : DrawableObject 6 | { 7 | /*************** FIELDS ***************/ 8 | 9 | public readonly BalconyFloor parentFloor; 10 | 11 | public BuildingMesh parentBuilding 12 | { 13 | get { return parentFloor.parentBuilding; } 14 | } 15 | 16 | public Face parentFace 17 | { 18 | get { return parentFloor.parentBalcony.parentFace; } 19 | } 20 | 21 | public BalconyRail (BalconyFloor parent) 22 | : base("balcony_rail") 23 | { 24 | parentFloor = parent; 25 | 26 | var height = 1f; 27 | boundaries = new Vector3[8]; 28 | 29 | boundaries[0] = parentFloor.boundaries[4]; 30 | boundaries[1] = parentFloor.boundaries[5]; 31 | boundaries[2] = boundaries[1] - parentFloor.depth * parentFace.normal; 32 | boundaries[3] = boundaries[0] - parentFloor.depth * parentFace.normal; 33 | 34 | for (var i = 0; i < 4; ++i) 35 | boundaries[i + 4] = boundaries[i] + height * Vector3.up; 36 | 37 | FindMeshOrigin(boundaries[0], 38 | boundaries[6], 39 | boundaries[2], 40 | boundaries[4]); 41 | 42 | for (var i = 0; i < boundaries.Length; ++i) 43 | boundaries[i] -= meshOrigin; 44 | } 45 | 46 | public override void FindVertices () 47 | { 48 | // make length * 4 for inside sides of rails 49 | vertices = new Vector3[boundaries.Length * 2]; 50 | for (int i = 0; i < 2; ++i) 51 | System.Array.Copy(boundaries, 0, vertices, i * boundaries.Length, boundaries.Length); 52 | } 53 | 54 | public override void FindTriangles () 55 | { 56 | triangles = new int[18]; 57 | 58 | // from outside 59 | 60 | // front 61 | triangles[0] = 0; 62 | triangles[1] = 1; 63 | triangles[2] = 4; 64 | 65 | triangles[3] = 1; 66 | triangles[4] = 5; 67 | triangles[5] = 4; 68 | 69 | //// left 70 | //triangles[6] = 1; 71 | //triangles[7] = 2; 72 | //triangles[8] = 5; 73 | 74 | //triangles[9] = 2; 75 | //triangles[10] = 6; 76 | //triangles[11] = 5; 77 | 78 | //// right 79 | //triangles[12] = 0; 80 | //triangles[13] = 4; 81 | //triangles[14] = 3; 82 | 83 | //triangles[15] = 3; 84 | //triangles[16] = 4; 85 | //triangles[17] = 7; 86 | 87 | // left 88 | triangles[6] = 9; // 1 + 8 89 | triangles[7] = 10; // 2 + 8 90 | triangles[8] = 13; // 5 + 8 91 | 92 | triangles[9] = 10; // 2 + 8 93 | triangles[10] = 14; // 6 + 8 94 | triangles[11] = 13; // 5 + 8 95 | 96 | // right 97 | triangles[12] = 8; // 0 + 8 98 | triangles[13] = 12; // 4 + 8 99 | triangles[14] = 11; // 3 + 8 100 | 101 | triangles[15] = 11; // 3 + 8 102 | triangles[16] = 12; // 4 + 8 103 | triangles[17] = 15; // 7 + 8 104 | 105 | // from inside are the previous tris in reverse order 106 | 107 | //var index = 18; 108 | //for (var i = 17; i >= 0; --i) 109 | // triangles[index++] = triangles[i] + 16; 110 | } 111 | 112 | public override void Draw () 113 | { 114 | base.Draw(); 115 | 116 | var uvs = new Vector2[mesh.vertices.Length]; 117 | uvs[2 + 8] = new Vector2(.5f, 0f); 118 | uvs[6 + 8] = new Vector2(.5f, 1f); 119 | uvs[1 + 8] = new Vector2(1f, 0f); 120 | uvs[5 + 8] = new Vector2(1f, 1f); 121 | 122 | uvs[1] = new Vector2(0f, 0f); 123 | uvs[5] = new Vector2(0f, 1f); 124 | uvs[0] = new Vector2(1f, 0f); 125 | uvs[4] = new Vector2(1f, 1f); 126 | 127 | uvs[0 + 8] = new Vector2(1f, 0f); 128 | uvs[4 + 8] = new Vector2(1f, 1f); 129 | uvs[3 + 8] = new Vector2(.5f, 0f); 130 | uvs[7 + 8] = new Vector2(.5f, 1f); 131 | 132 | mesh.uv = uvs; 133 | 134 | gameObject.transform.position = meshOrigin + parentBuilding.meshOrigin + parentFloor.meshOrigin; 135 | gameObject.transform.parent = parentBuilding.parent.gameObject.transform; 136 | } 137 | 138 | private Texture2D CreateTexture () 139 | { 140 | var tex = new Texture2D(256, 128); 141 | int y = -1; 142 | int x = -1; 143 | 144 | var thickness = 5; 145 | 146 | do 147 | { 148 | x = 0; 149 | do 150 | { 151 | tex.SetPixel(x, y, Color.black); 152 | //Debug.Log(y); 153 | } while (x++ < tex.width); 154 | } while (y++ < thickness - 1); 155 | 156 | do 157 | { 158 | x = 0; 159 | do 160 | { 161 | if ((x & y) == 0) 162 | tex.SetPixel(x, y, Color.black); 163 | else 164 | tex.SetPixel(x, y, Color.clear); 165 | } while (x++ < tex.width); 166 | } while (y++ < tex.height - thickness); 167 | 168 | do 169 | { 170 | x = 0; 171 | do 172 | { 173 | tex.SetPixel(x, y, Color.black); 174 | Debug.Log(y); 175 | } while (x++ < tex.width); 176 | } while (y++ < tex.height); 177 | 178 | tex.Apply(); 179 | 180 | return tex; 181 | } 182 | } 183 | 184 | } // namespace Thesis -------------------------------------------------------------------------------- /Assets/Scripts/CameraController.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using Thesis; 3 | 4 | public class CameraController : MonoBehaviour { 5 | 6 | private enum CameraMode 7 | { 8 | Horizontal, 9 | Free 10 | } 11 | 12 | [SerializeField] 13 | private CameraMode _cameraMode = CameraMode.Horizontal; 14 | 15 | [SerializeField] 16 | private float _movementSpeed = 10f; 17 | 18 | [SerializeField] 19 | private float _rotationSpeed = 5f; 20 | 21 | private float _x_rotation; 22 | private float _y_rotation; 23 | 24 | private float _last_mouse_x; 25 | private float _last_mouse_y; 26 | private float _mouse_x; 27 | private float _mouse_y; 28 | private bool _follow_mouse = true; 29 | 30 | void Awake () 31 | { 32 | ColorManager.Instance.Init(); 33 | TextureManager.Instance.Init(); 34 | MaterialManager.Instance.Init(); 35 | BuildingManager.Instance.Init(); 36 | } 37 | 38 | void Start () 39 | { 40 | Screen.showCursor = false; 41 | 42 | _x_rotation = camera.transform.rotation.eulerAngles.x; 43 | _y_rotation = camera.transform.rotation.eulerAngles.y; 44 | 45 | _last_mouse_x = Input.GetAxis("Mouse X"); 46 | _last_mouse_y = -Input.GetAxis("Mouse Y"); 47 | _mouse_x = _last_mouse_x; 48 | _mouse_y = _last_mouse_y; 49 | } 50 | 51 | void Update () 52 | { 53 | if (_follow_mouse) 54 | { 55 | _mouse_x = Input.GetAxis("Mouse X"); 56 | _mouse_y = -Input.GetAxis("Mouse Y"); 57 | _y_rotation += Mathf.Lerp(_last_mouse_x * _rotationSpeed, _mouse_x * _rotationSpeed, Time.smoothDeltaTime); 58 | _x_rotation += Mathf.Lerp(_last_mouse_y * _rotationSpeed, _mouse_y * _rotationSpeed, Time.smoothDeltaTime); 59 | _last_mouse_x = _mouse_x; 60 | _last_mouse_y = _mouse_y; 61 | } 62 | 63 | ClampCamera(); 64 | camera.transform.eulerAngles = new Vector3(_x_rotation, _y_rotation, 0f); 65 | 66 | float moveSpeed = _movementSpeed; 67 | if (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift)) 68 | moveSpeed = 2 * _movementSpeed; 69 | 70 | if (Input.GetAxis("Vertical") != 0f) 71 | { 72 | if (_cameraMode == CameraMode.Horizontal) 73 | camera.transform.position += Vector3.Cross(camera.transform.right, Vector3.up) * 74 | Input.GetAxis("Vertical") * 75 | moveSpeed * Time.deltaTime; 76 | else 77 | camera.transform.position += camera.transform.forward * 78 | Input.GetAxis("Vertical") * 79 | moveSpeed * Time.deltaTime; 80 | } 81 | 82 | if (Input.GetAxis("Horizontal") != 0f) 83 | camera.transform.position += camera.transform.right * 84 | Input.GetAxis("Horizontal") * 85 | moveSpeed * Time.deltaTime; 86 | 87 | if (Input.GetKey(KeyCode.E)) 88 | camera.transform.position += Vector3.up * moveSpeed * Time.deltaTime; 89 | 90 | if (Input.GetKey(KeyCode.C)) 91 | camera.transform.position -= Vector3.up * moveSpeed * Time.deltaTime; 92 | 93 | if (Input.GetKeyUp(KeyCode.M)) 94 | if (_cameraMode == CameraMode.Free) 95 | _cameraMode = CameraMode.Horizontal; 96 | else 97 | _cameraMode = CameraMode.Free; 98 | 99 | if (Input.GetMouseButtonUp(1)) 100 | if (_follow_mouse) 101 | { 102 | _follow_mouse = false; 103 | Screen.showCursor = true; 104 | } 105 | else 106 | { 107 | _follow_mouse = true; 108 | Screen.showCursor = false; 109 | } 110 | 111 | if (Input.GetKey(KeyCode.Escape)) 112 | Application.Quit(); 113 | 114 | if (Input.GetKey(KeyCode.F1)) 115 | Application.LoadLevel("main_scene"); 116 | 117 | if (Input.GetKey(KeyCode.F2)) 118 | Application.LoadLevel("city_scene"); 119 | } 120 | 121 | public void OnGUI () 122 | { 123 | GUILayout.Label("Camera controls:"); 124 | GUILayout.Label("W - Forward"); 125 | GUILayout.Label("S - Backward"); 126 | GUILayout.Label("D - Right"); 127 | GUILayout.Label("A - Left"); 128 | GUILayout.Label("E - Up"); 129 | GUILayout.Label("C - Down"); 130 | GUILayout.Label("M - Change camera mode"); 131 | GUILayout.Label("Shift - Speed boost"); 132 | 133 | //#if UNITY_EDITOR 134 | // GUILayout.Label("All " + FindObjectsOfType(typeof(UnityEngine.Object)).Length); 135 | // GUILayout.Label("AudioClips " + FindObjectsOfType(typeof(AudioClip)).Length); 136 | // GUILayout.Label("Materials " + FindObjectsOfType(typeof(Material)).Length); 137 | // GUILayout.Label("Components " + FindObjectsOfType(typeof(Component)).Length); 138 | // GUILayout.Label("Textures " + FindObjectsOfType(typeof(Texture)).Length); 139 | // GUILayout.Label("Meshes " + FindObjectsOfType(typeof(Mesh)).Length); 140 | // GUILayout.Label("GameObjects " + FindObjectsOfType(typeof(GameObject)).Length); 141 | //#endif 142 | } 143 | 144 | private void ClampCamera (float horizontal = 360f, float vertical = 80f) 145 | { 146 | if (_y_rotation < -horizontal) _y_rotation += horizontal; 147 | if (_y_rotation > horizontal) _y_rotation -= horizontal; 148 | 149 | if (_x_rotation > vertical) _x_rotation = vertical; 150 | if (_x_rotation < -vertical) _x_rotation = -vertical; 151 | } 152 | 153 | void OnDestroy () 154 | { 155 | BuildingManager.Instance.DestroyBuildings(); 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /Assets/Standard Assets/Roof/DoublePeakRoof.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace Thesis { 4 | 5 | public class DoublePeakRoof : Roof 6 | { 7 | private enum _Type { four, five } 8 | private _Type _type; 9 | private float _widthBig; 10 | private float _widthSmall; 11 | private float _heightBig; 12 | private float _heightSmall; 13 | 14 | public DoublePeakRoof (BuildingMesh parent) 15 | : base(parent) 16 | { 17 | width = 0.2f; 18 | boundaries = new Vector3[6]; 19 | 20 | for (int i = 0; i < 4; ++i) 21 | boundaries[i] = parentMesh.roofBase.boundaries[i + 4]+ 22 | width * parentMesh.faces[i].normal + 23 | width * parentMesh.faces[(i + 3) % 4].normal; 24 | 25 | FindMeshOrigin(boundaries[0], boundaries[2], 26 | boundaries[1], boundaries[3]); 27 | 28 | int index = Mathf.Max(parentMesh.sortedFaces[2], parentMesh.sortedFaces[3]); 29 | Face face = parentMesh.faces[index]; 30 | height = 0.2f * face.width; 31 | var bi0 = (parentMesh.faces[(index + 3) % 4].right - face.right).normalized; 32 | var bi1 = (face.right - parentMesh.faces[(index + 1) % 4].right).normalized; 33 | var p = Util.IntersectionPoint(face.boundaries[0], bi0, face.boundaries[1], bi1); 34 | 35 | boundaries[4] = new Vector3(p.x, 36 | boundaries[0].y + height, 37 | p.z); 38 | 39 | index = Mathf.Min(parentMesh.sortedFaces[2], parentMesh.sortedFaces[3]); 40 | face = parentMesh.faces[index]; 41 | bi0 = (parentMesh.faces[(index + 3) % 4].right - face.right).normalized; 42 | bi1 = (face.right - parentMesh.faces[(index + 1) % 4].right).normalized; 43 | p = Util.IntersectionPoint(face.boundaries[0], bi0, face.boundaries[1], bi1); 44 | 45 | boundaries[5] = new Vector3(p.x, 46 | boundaries[0].y + height, 47 | p.z); 48 | 49 | if ((boundaries[0] - boundaries[4]).magnitude < 50 | (boundaries[0] - boundaries[5]).magnitude) 51 | { 52 | _type = _Type.four; 53 | _widthBig = (boundaries[0] - boundaries[1]).magnitude; 54 | _widthSmall = (boundaries[1] - boundaries[2]).magnitude; 55 | _heightSmall = ((boundaries[1] + boundaries[2]) / 2 - boundaries[5]).magnitude; 56 | } 57 | else 58 | { 59 | _type = _Type.five; 60 | _widthBig = (boundaries[1] - boundaries[2]).magnitude; 61 | _widthSmall = (boundaries[1] - boundaries[0]).magnitude; 62 | _heightSmall = ((boundaries[1] + boundaries[0]) / 2 - boundaries[5]).magnitude; 63 | } 64 | 65 | _heightBig = Mathf.Sqrt(Mathf.Pow(_widthSmall / 2, 2) + 66 | Mathf.Pow(height, 2)); 67 | } 68 | 69 | public override void FindVertices() 70 | { 71 | vertices = new Vector3[boundaries.Length * 4]; 72 | for (int i = 0; i < 4; ++i) 73 | System.Array.Copy(boundaries, 0, vertices, i * boundaries.Length, boundaries.Length); 74 | } 75 | 76 | public override void FindTriangles() 77 | { 78 | triangles = new int[24]; 79 | int i = 0; 80 | 81 | if (_type == _Type.five) 82 | { 83 | triangles[i++] = 0; 84 | triangles[i++] = 1; 85 | triangles[i++] = 5; 86 | 87 | triangles[i++] = 2; 88 | triangles[i++] = 3; 89 | triangles[i++] = 4; 90 | 91 | // +6 92 | triangles[i++] = 7; 93 | triangles[i++] = 8; 94 | triangles[i++] = 11; 95 | 96 | triangles[i++] = 8; 97 | triangles[i++] = 10; 98 | triangles[i++] = 11; 99 | 100 | // +12 101 | triangles[i++] = 12; 102 | triangles[i++] = 17; 103 | triangles[i++] = 16; 104 | 105 | triangles[i++] = 12; 106 | triangles[i++] = 16; 107 | triangles[i++] = 15; 108 | } 109 | else 110 | { 111 | triangles[i++] = 1; 112 | triangles[i++] = 2; 113 | triangles[i++] = 5; 114 | 115 | triangles[i++] = 0; 116 | triangles[i++] = 4; 117 | triangles[i++] = 3; 118 | 119 | // +6 120 | triangles[i++] = 6; 121 | triangles[i++] = 7; 122 | triangles[i++] = 11; 123 | 124 | triangles[i++] = 6; 125 | triangles[i++] = 11; 126 | triangles[i++] = 10; 127 | 128 | // +12 129 | triangles[i++] = 14; 130 | triangles[i++] = 15; 131 | triangles[i++] = 16; 132 | 133 | triangles[i++] = 14; 134 | triangles[i++] = 16; 135 | triangles[i++] = 17; 136 | } 137 | 138 | // +18 139 | triangles[i++] = 18; 140 | triangles[i++] = 21; 141 | triangles[i++] = 20; 142 | 143 | triangles[i++] = 18; 144 | triangles[i++] = 20; 145 | triangles[i++] = 19; 146 | } 147 | 148 | public override void Draw() 149 | { 150 | base.Draw(); 151 | 152 | var uvs = new Vector2[mesh.vertices.Length]; 153 | 154 | float _wdiv = material.mainTexture.width / 128f; 155 | float _hdiv = material.mainTexture.height / 128f; 156 | float htimes = _widthSmall / _wdiv; 157 | float vtimes = _heightSmall / _hdiv; 158 | 159 | uvs[1] = new Vector2(0f, 0f); 160 | uvs[0] = new Vector2(htimes, 0f); 161 | uvs[5] = new Vector2(htimes / 2, vtimes); 162 | 163 | uvs[3] = new Vector2(0f, 0f); 164 | uvs[2] = new Vector2(htimes, 0f); 165 | uvs[4] = new Vector2(htimes / 2, vtimes); 166 | 167 | htimes = _widthBig / _wdiv; 168 | vtimes = _heightBig / _hdiv; 169 | var _dist45 = (boundaries[4] - boundaries[5]).magnitude; 170 | var tmp = ((_widthBig - _dist45) / 2) / _wdiv; 171 | uvs[8] = new Vector2(0f, 0f); 172 | uvs[7] = new Vector2(htimes, 0f); 173 | uvs[10] = new Vector2(tmp, vtimes); 174 | uvs[11] = new Vector2(htimes - tmp, vtimes); 175 | 176 | uvs[12] = new Vector2(0f, 0f); 177 | uvs[15] = new Vector2(htimes, 0f); 178 | uvs[17] = new Vector2(tmp, vtimes); 179 | uvs[16] = new Vector2(htimes - tmp, vtimes); 180 | 181 | mesh.uv = uvs; 182 | } 183 | } 184 | 185 | } // namespace Thesis -------------------------------------------------------------------------------- /Assets/Standard Assets/Shutter/Shuter.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace Thesis { 4 | 5 | public class Shutter : DrawableObject 6 | { 7 | public readonly FaceComponent parent; 8 | 9 | public readonly ShutterSide side; 10 | 11 | static private int angles; 12 | 13 | public BuildingMesh parentBuilding 14 | { 15 | get { return parent.parentBuilding; } 16 | } 17 | 18 | /*************** CONSTRUCTORS ***************/ 19 | 20 | public Shutter (FaceComponent parent, ShutterSide side) 21 | { 22 | this.parent = parent; 23 | this.side = side; 24 | angles = 0; 25 | boundaries = new Vector3[8]; 26 | 27 | if (side == ShutterSide.Right) 28 | { 29 | boundaries[0] = Vector3.zero; 30 | boundaries[1] = - parent.parentFace.right * (parent.width / 2); 31 | boundaries[2] = boundaries[1] + Vector3.up * parent.height; 32 | boundaries[3] = Vector3.up * parent.height; 33 | 34 | meshOrigin = parent.boundaries[0]; 35 | } 36 | else 37 | { 38 | boundaries[0] = parent.parentFace.right * (parent.width / 2); 39 | boundaries[1] = Vector3.zero; 40 | boundaries[2] = Vector3.up * parent.height; 41 | boundaries[3] = boundaries[0] + boundaries[2]; 42 | 43 | meshOrigin = parent.boundaries[1]; 44 | } 45 | 46 | for (var i = 0; i < 4; ++i) 47 | boundaries[i + 4] = boundaries[i] - parent.normal * parent.depth / 2; 48 | } 49 | 50 | public override void FindVertices() 51 | { 52 | vertices = new Vector3[boundaries.Length * 3]; 53 | for (int i = 0; i < 3; ++i) 54 | System.Array.Copy(boundaries, 0, vertices, i * boundaries.Length, boundaries.Length); 55 | } 56 | 57 | public override void FindTriangles() 58 | { 59 | triangles = new int[36]; 60 | int i = 0; 61 | 62 | // front 63 | triangles[i++] = 0; 64 | triangles[i++] = 1; 65 | triangles[i++] = 3; 66 | 67 | triangles[i++] = 1; 68 | triangles[i++] = 2; 69 | triangles[i++] = 3; 70 | 71 | // back 72 | triangles[i++] = 4; 73 | triangles[i++] = 7; 74 | triangles[i++] = 5; 75 | 76 | triangles[i++] = 5; 77 | triangles[i++] = 7; 78 | triangles[i++] = 6; 79 | 80 | // right (+8) 81 | triangles[i++] = 8; 82 | triangles[i++] = 11; 83 | triangles[i++] = 15; 84 | 85 | triangles[i++] = 8; 86 | triangles[i++] = 15; 87 | triangles[i++] = 12; 88 | 89 | // left (+8) 90 | triangles[i++] = 9; 91 | triangles[i++] = 13; 92 | triangles[i++] = 10; 93 | 94 | triangles[i++] = 13; 95 | triangles[i++] = 14; 96 | triangles[i++] = 10; 97 | 98 | // bottom (+16) 99 | triangles[i++] = 16; 100 | triangles[i++] = 20; 101 | triangles[i++] = 17; 102 | 103 | triangles[i++] = 17; 104 | triangles[i++] = 20; 105 | triangles[i++] = 21; 106 | 107 | // top (+16) 108 | triangles[i++] = 18; 109 | triangles[i++] = 22; 110 | triangles[i++] = 23; 111 | 112 | triangles[i++] = 18; 113 | triangles[i++] = 23; 114 | triangles[i++] = 19; 115 | } 116 | 117 | public override void Draw() 118 | { 119 | base.Draw(); 120 | AssignUVs(); 121 | 122 | if (side == ShutterSide.Right) 123 | gameObject.transform.RotateAround(meshOrigin, Vector3.up, -angles); 124 | else 125 | gameObject.transform.RotateAround(meshOrigin, Vector3.up, angles); 126 | 127 | gameObject.transform.position = meshOrigin + parent.meshOrigin + 128 | parentBuilding.meshOrigin - parent.normal * 0.15f; 129 | gameObject.transform.parent = parentBuilding.parent.gameObject.transform; 130 | } 131 | 132 | private void AssignUVs () 133 | { 134 | var uvs = new Vector2[mesh.vertices.Length]; 135 | 136 | if (parent.GetType().IsSubclassOf(typeof(Window)) && 137 | side == ShutterSide.Left) 138 | { 139 | uvs[0] = new Vector2(.5f, .5f); 140 | uvs[1] = new Vector2( 0, .5f); 141 | uvs[2] = new Vector2( 0, 1); 142 | uvs[3] = new Vector2(.5f, 1); 143 | uvs[4] = new Vector2(.5f, .5f); 144 | uvs[5] = new Vector2( 0, .5f); 145 | uvs[6] = new Vector2( 0, 1); 146 | uvs[7] = new Vector2(.5f, 1); 147 | } 148 | else if (parent.GetType().IsSubclassOf(typeof(Window)) && 149 | side == ShutterSide.Right) 150 | { 151 | uvs[0] = new Vector2( 0, .5f); 152 | uvs[1] = new Vector2(.5f, .5f); 153 | uvs[2] = new Vector2(.5f, 1); 154 | uvs[3] = new Vector2( 0, 1); 155 | uvs[4] = new Vector2( 0, .5f); 156 | uvs[5] = new Vector2(.5f, .5f); 157 | uvs[6] = new Vector2(.5f, 1); 158 | uvs[7] = new Vector2( 0, 1); 159 | } 160 | else if (parent.GetType().IsSubclassOf(typeof(Balcony)) && 161 | side == ShutterSide.Left) 162 | { 163 | uvs[0] = new Vector2( 1, 0); 164 | uvs[1] = new Vector2(.5f, 0); 165 | uvs[2] = new Vector2(.5f, 1); 166 | uvs[3] = new Vector2( 1, 1); 167 | uvs[4] = new Vector2( 1, 0); 168 | uvs[5] = new Vector2(.5f, 0); 169 | uvs[6] = new Vector2(.5f, 1); 170 | uvs[7] = new Vector2( 1, 1); 171 | } 172 | else 173 | { 174 | uvs[0] = new Vector2(.5f, 0); 175 | uvs[1] = new Vector2( 1, 0); 176 | uvs[2] = new Vector2( 1, 1); 177 | uvs[3] = new Vector2(.5f, 1); 178 | uvs[4] = new Vector2(.5f, 0); 179 | uvs[5] = new Vector2( 1, 0); 180 | uvs[6] = new Vector2( 1, 1); 181 | uvs[7] = new Vector2(.5f, 1); 182 | } 183 | 184 | mesh.uv = uvs; 185 | } 186 | 187 | public static void SetAngles () 188 | { 189 | switch (Util.RollDice(new float[] {0.33f, 0.33f, 0.34f})) 190 | { 191 | case 1: 192 | angles = 150; 193 | break; 194 | 195 | case 2: 196 | angles = Random.Range(130, 150); 197 | break; 198 | 199 | case 3: 200 | angles = 0; 201 | break; 202 | } 203 | } 204 | } 205 | 206 | } // Thesis -------------------------------------------------------------------------------- /Assets/Standard Assets/Window/WindowDecor.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace Thesis { 4 | 5 | public class ComponentDecor : DrawableObject 6 | { 7 | public readonly FaceComponent parentComponent; 8 | 9 | public float width; 10 | 11 | public Building allParent 12 | { 13 | get { return parentComponent.parentBuilding.parent; } 14 | } 15 | 16 | private readonly bool _parentIsWindow; 17 | private readonly bool _isSimple; 18 | 19 | public ComponentDecor (FaceComponent parent, bool isSimple = false) 20 | { 21 | parentComponent = parent; 22 | _isSimple = isSimple; 23 | _parentIsWindow = parent.GetType().Equals(typeof(Window)) ? true : false; 24 | 25 | if (_isSimple) 26 | initSimpleDecor(); 27 | else 28 | initDecor(); 29 | } 30 | 31 | private void initDecor () 32 | { 33 | boundaries = new Vector3[16]; 34 | 35 | for (int i = 0; i < 4; ++i) 36 | boundaries[i] = parentComponent.boundaries[i] + 37 | 0.01f * parentComponent.parentFace.normal; 38 | 39 | width = 0.3f; 40 | var dist = width * parentComponent.parentFace.right; 41 | 42 | boundaries[4] = boundaries[0] + dist; 43 | boundaries[5] = boundaries[1] - dist; 44 | boundaries[6] = boundaries[2] - dist; 45 | boundaries[7] = boundaries[3] + dist; 46 | 47 | boundaries[8] = boundaries[2] - 2 * dist; 48 | boundaries[9] = boundaries[8] + 2 * width * Vector3.up; 49 | boundaries[11] = boundaries[3] + 2 * dist; 50 | boundaries[10] = boundaries[11] + 2 * width * Vector3.up; 51 | 52 | boundaries[12] = boundaries[5] - 4 * width * Vector3.up; 53 | boundaries[13] = boundaries[5]; 54 | boundaries[14] = boundaries[4]; 55 | boundaries[15] = boundaries[4] - 4 * width * Vector3.up; 56 | } 57 | 58 | private void initSimpleDecor () 59 | { 60 | boundaries = new Vector3[8]; 61 | width = 0.15f; 62 | 63 | for (int i = 0; i < 4; ++i) 64 | boundaries[i] = parentComponent.boundaries[i] + 65 | 0.01f * parentComponent.parentFace.normal; 66 | 67 | var right = parentComponent.parentFace.right; 68 | 69 | boundaries[4] = boundaries[0] + width * right - width * Vector3.up; 70 | boundaries[5] = boundaries[1] - width * right - width * Vector3.up; 71 | boundaries[6] = boundaries[2] - width * right + width * Vector3.up; 72 | boundaries[7] = boundaries[3] + width * right + width * Vector3.up; 73 | } 74 | 75 | public override void FindVertices() 76 | { 77 | vertices = boundaries; 78 | } 79 | 80 | public override void FindTriangles() 81 | { 82 | triangles = new int[_parentIsWindow ? 24 : 18]; 83 | if (_isSimple) 84 | findTrisSimple(); 85 | else 86 | findTris(); 87 | } 88 | 89 | private void findTris() 90 | { 91 | int i = 0; 92 | 93 | // left side 94 | triangles[i++] = 1; 95 | triangles[i++] = 5; 96 | triangles[i++] = 6; 97 | 98 | triangles[i++] = 1; 99 | triangles[i++] = 6; 100 | triangles[i++] = 2; 101 | 102 | // right side 103 | triangles[i++] = 0; 104 | triangles[i++] = 3; 105 | triangles[i++] = 7; 106 | 107 | triangles[i++] = 0; 108 | triangles[i++] = 7; 109 | triangles[i++] = 4; 110 | 111 | // top 112 | triangles[i++] = 8; 113 | triangles[i++] = 9; 114 | triangles[i++] = 10; 115 | 116 | triangles[i++] = 8; 117 | triangles[i++] = 10; 118 | triangles[i++] = 11; 119 | 120 | // bottom 121 | if (_parentIsWindow) 122 | { 123 | triangles[i++] = 12; 124 | triangles[i++] = 13; 125 | triangles[i++] = 14; 126 | 127 | triangles[i++] = 12; 128 | triangles[i++] = 14; 129 | triangles[i++] = 15; 130 | } 131 | } 132 | 133 | private void findTrisSimple() 134 | { 135 | int i = 0; 136 | 137 | // left 138 | triangles[i++] = 1; 139 | triangles[i++] = 5; 140 | triangles[i++] = 6; 141 | 142 | triangles[i++] = 1; 143 | triangles[i++] = 6; 144 | triangles[i++] = 2; 145 | 146 | // top 147 | triangles[i++] = 2; 148 | triangles[i++] = 6; 149 | triangles[i++] = 7; 150 | 151 | triangles[i++] = 2; 152 | triangles[i++] = 7; 153 | triangles[i++] = 3; 154 | 155 | // right 156 | triangles[i++] = 4; 157 | triangles[i++] = 0; 158 | triangles[i++] = 3; 159 | 160 | triangles[i++] = 4; 161 | triangles[i++] = 3; 162 | triangles[i++] = 7; 163 | 164 | if (_parentIsWindow) 165 | { 166 | // bottom 167 | triangles[i++] = 4; 168 | triangles[i++] = 5; 169 | triangles[i++] = 1; 170 | 171 | triangles[i++] = 4; 172 | triangles[i++] = 1; 173 | triangles[i++] = 0; 174 | } 175 | } 176 | 177 | public override void Draw() 178 | { 179 | base.Draw(); 180 | 181 | if (_isSimple) 182 | findUvsSimple(); 183 | else 184 | findUvs(); 185 | 186 | gameObject.transform.parent = allParent.gameObject.transform; 187 | gameObject.transform.position = allParent.buildingMesh.meshOrigin; 188 | } 189 | 190 | private void findUvs() 191 | { 192 | var uvs = new Vector2[mesh.vertices.Length]; 193 | 194 | // left 195 | uvs[5] = new Vector2(0f, 0f); 196 | uvs[1] = new Vector2(.125f, 0f); 197 | uvs[6] = new Vector2(0f, 1f); 198 | uvs[2] = new Vector2(.125f, 1f); 199 | 200 | // right 201 | uvs[0] = new Vector2(.125f, 0f); 202 | uvs[4] = new Vector2(.25f, 0f); 203 | uvs[3] = new Vector2(.125f, 1f); 204 | uvs[7] = new Vector2(.25f, 1f); 205 | 206 | // top 207 | uvs[8] = new Vector2(.25f, 1f); 208 | uvs[11] = new Vector2(.25f, 0f); 209 | uvs[9] = new Vector2(.5f, 1f); 210 | uvs[10] = new Vector2(.5f, 0f); 211 | 212 | // bottom 213 | if (_parentIsWindow) 214 | { 215 | uvs[15] = new Vector2(.5f, 0f); 216 | uvs[14] = new Vector2(1f, 0f); 217 | uvs[12] = new Vector2(.5f, 1f); 218 | uvs[13] = new Vector2(1f, 1f); 219 | } 220 | 221 | mesh.uv = uvs; 222 | } 223 | 224 | private void findUvsSimple() 225 | { 226 | var uvs = new Vector2[mesh.vertices.Length]; 227 | 228 | // bottom 229 | uvs[4] = new Vector2(0f, 0f); 230 | uvs[0] = new Vector2(1f, 0f); 231 | uvs[5] = new Vector2(0f, 1f); 232 | uvs[1] = new Vector2(1f, 1f); 233 | 234 | // left 235 | uvs[5] = new Vector2(0f, 0f); 236 | uvs[1] = new Vector2(1f, 0f); 237 | uvs[6] = new Vector2(0f, 1f); 238 | uvs[2] = new Vector2(1f, 1f); 239 | 240 | // top 241 | uvs[6] = new Vector2(0f, 0f); 242 | uvs[2] = new Vector2(1f, 0f); 243 | uvs[7] = new Vector2(0f, 1f); 244 | uvs[3] = new Vector2(1f, 1f); 245 | 246 | // right 247 | uvs[7] = new Vector2(0f, 0f); 248 | uvs[3] = new Vector2(1f, 0f); 249 | uvs[4] = new Vector2(0f, 1f); 250 | uvs[0] = new Vector2(1f, 1f); 251 | 252 | mesh.uv = uvs; 253 | } 254 | } 255 | 256 | } // namespace Thesis -------------------------------------------------------------------------------- /Assets/Standard Assets/Building/Building.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | using CombinablesCollection = System.Collections.Generic.IList; 6 | using Random = UnityEngine.Random; 7 | 8 | namespace Thesis { 9 | 10 | public class Building 11 | { 12 | // building dimensions 13 | // 0, 1 -> the indexes of faces 14 | public float width0 = 0f; 15 | public float width1 = 0f; 16 | public Vector3[] startingPoints; 17 | public float floorHeight = 0f; 18 | public int floorCount = 0; 19 | 20 | // component stuff 21 | public float componentDistance = 0f; 22 | public float windowHeight = 0f; 23 | public float windowWidth = 0f; 24 | public float doorWidth = 0f; 25 | public float doorHeight = 0f; 26 | public float balconyWidth = 0f; 27 | public float balconyHeight = 0f; 28 | 29 | // roof stuff 30 | public Type roofType; 31 | public Material roofDecorMaterial; 32 | public Material roofMaterial; 33 | public Material roofBaseMaterial; 34 | 35 | private Material _windowMaterial; 36 | public Material windowMaterial 37 | { 38 | get { return _windowMaterial; } 39 | } 40 | 41 | private Material _balconyDoorMaterial; 42 | public Material balconyDoorMaterial 43 | { 44 | get { return _balconyDoorMaterial; } 45 | } 46 | 47 | private Material _doorMaterial; 48 | public Material doorMaterial 49 | { 50 | get { return _doorMaterial; } 51 | } 52 | 53 | private Material _shutterMaterial; 54 | public Material shutterMaterial 55 | { 56 | get { return _shutterMaterial; } 57 | } 58 | 59 | private Material _compDecorMaterial; 60 | public Material compDecorMaterial 61 | { 62 | get { return _compDecorMaterial; } 63 | } 64 | 65 | private Material _simpleCompDecorMaterial; 66 | public Material simpleCompDecorMaterial 67 | { 68 | get { return _simpleCompDecorMaterial; } 69 | } 70 | 71 | public GameObject gameObject; 72 | 73 | public BuildingMesh buildingMesh; 74 | 75 | private Dictionary _combinables; 76 | 77 | private Dictionary _combiners; 78 | 79 | public Building () { Init(); } 80 | 81 | public Building (Vector3 p1, Vector3 p2, Vector3 p3, Vector3 p4) 82 | { 83 | Init(); 84 | 85 | // must be _after_ the initialization of this object 86 | buildingMesh = new BuildingMesh(this, p1, p2, p3, p4); 87 | gameObject = new GameObject("Neoclassical"); 88 | gameObject.transform.position = buildingMesh.meshOrigin; 89 | } 90 | 91 | public Building (BuildingLot lot) 92 | { 93 | Init(); 94 | 95 | // must be _after_ the initialization of this object 96 | buildingMesh = new BuildingMesh(this, lot); 97 | gameObject = new GameObject("Neoclassical"); 98 | gameObject.transform.position = buildingMesh.meshOrigin; 99 | } 100 | 101 | public void CreateBuilding () 102 | { 103 | if (startingPoints == null) 104 | { 105 | startingPoints = new Vector3[4]; 106 | if (width0 == 0f || width1 == 0f) 107 | { 108 | startingPoints[0] = new Vector3(); 109 | startingPoints[1] = new Vector3(0f, 0f, 11f); 110 | startingPoints[2] = new Vector3(8f, 0f, 11f); 111 | startingPoints[3] = new Vector3(8f, 0f, 0f); 112 | } 113 | else 114 | { 115 | startingPoints[0] = new Vector3(); 116 | startingPoints[1] = Vector3.forward * width0; 117 | startingPoints[3] = Vector3.right * width1; 118 | startingPoints[2] = startingPoints[1] + startingPoints[3]; 119 | } 120 | } 121 | 122 | buildingMesh = new BuildingMesh(this, startingPoints[0], 123 | startingPoints[1], 124 | startingPoints[2], 125 | startingPoints[3]); 126 | gameObject = new GameObject("Neoclassical"); 127 | gameObject.transform.position = buildingMesh.meshOrigin; 128 | } 129 | 130 | public void Init() 131 | { 132 | _combinables = new Dictionary(); 133 | _combiners = new Dictionary(); 134 | 135 | // find window material randomly 136 | var list = MaterialManager.Instance.GetCollection("mat_window"); 137 | var num = Random.Range(0, list.Count); 138 | _windowMaterial = list[num]; 139 | 140 | // balcony door material 141 | list = MaterialManager.Instance.GetCollection("mat_balcony_door"); 142 | _balconyDoorMaterial = list[num]; 143 | 144 | // door material 145 | list = MaterialManager.Instance.GetCollection("mat_door"); 146 | num = Random.Range(0, list.Count); 147 | _doorMaterial = list[num]; 148 | 149 | // shutter material 150 | // not randomly selected, depends on the door material 151 | // count and shutter material count, in order to match 152 | // colours 153 | list = MaterialManager.Instance.GetCollection("mat_shutter"); 154 | var doorCount = MaterialManager.Instance.GetCollection("mat_door").Count; 155 | var shutCount = MaterialManager.Instance.GetCollection("mat_shutter").Count; 156 | _shutterMaterial = list[num * shutCount / doorCount]; 157 | 158 | // component decor material 159 | list = MaterialManager.Instance.GetCollection("mat_comp_decor"); 160 | num = Random.Range(0, list.Count); 161 | _compDecorMaterial = list[num]; 162 | //compDecorMaterial = list[list.Count - 1]; 163 | 164 | list = MaterialManager.Instance.GetCollection("mat_comp_decor_simple"); 165 | num = Random.Range(0, list.Count); 166 | _simpleCompDecorMaterial = list[num]; 167 | } 168 | 169 | public void AddCombinable(string materialName, Interface.ICombinable combinable) 170 | { 171 | if (!_combinables.ContainsKey(materialName)) 172 | { 173 | CombinablesCollection temp = new List(); 174 | temp.Add(combinable); 175 | _combinables.Add(materialName, temp); 176 | } 177 | else 178 | _combinables[materialName].Add(combinable); 179 | } 180 | 181 | public void CombineSubmeshes () 182 | { 183 | foreach (string key in _combinables.Keys) 184 | { 185 | if (_combinables[key].Count < 2) continue; 186 | 187 | var gobject = new GameObject(key + "_combiner"); 188 | gobject.SetActive(false); 189 | gobject.transform.parent = gameObject.transform; 190 | var filter = gobject.AddComponent(); 191 | var renderer = gobject.AddComponent(); 192 | renderer.sharedMaterial = _combinables[key][0].material; 193 | 194 | var filters = new MeshFilter[_combinables[key].Count]; 195 | for (var i = 0; i < _combinables[key].Count; ++i) 196 | { 197 | filters[i] = _combinables[key][i].meshFilter; 198 | GameObject.Destroy(_combinables[key][i].mesh); 199 | GameObject.Destroy(_combinables[key][i].gameObject); 200 | } 201 | 202 | var combine = new CombineInstance[filters.Length]; 203 | for (var i = 0; i < filters.Length; ++i) 204 | { 205 | combine[i].mesh = filters[i].sharedMesh; 206 | combine[i].transform = filters[i].transform.localToWorldMatrix; 207 | } 208 | 209 | //filter.mesh = new Mesh(); 210 | filter.mesh.CombineMeshes(combine); 211 | 212 | if (_combiners.ContainsKey(key)) 213 | _combiners[key] = gobject; 214 | else 215 | _combiners.Add(key, gobject); 216 | } 217 | _combinables.Clear(); 218 | } 219 | 220 | public void Draw () 221 | { 222 | buildingMesh.FindVertices(); 223 | buildingMesh.FindTriangles(); 224 | buildingMesh.Draw(); 225 | gameObject.SetActive(true); 226 | } 227 | 228 | public void Destroy () 229 | { 230 | GameObject.DestroyImmediate(gameObject); 231 | 232 | foreach (string key in _combinables.Keys) 233 | for (var i = 0; i < _combinables[key].Count; ++i) 234 | { 235 | GameObject.DestroyImmediate(_combinables[key][i].mesh); 236 | GameObject.DestroyImmediate(_combinables[key][i].gameObject); 237 | } 238 | 239 | foreach (GameObject go in _combiners.Values) 240 | { 241 | if (go != null) 242 | { 243 | GameObject.DestroyImmediate(go.GetComponent().mesh); 244 | GameObject.DestroyImmediate(go); 245 | } 246 | } 247 | 248 | _combinables.Clear(); 249 | _combiners.Clear(); 250 | if (buildingMesh != null) 251 | buildingMesh.Destroy(); 252 | } 253 | } 254 | 255 | } // namespace Thesis -------------------------------------------------------------------------------- /Assets/Standard Assets/Managers/MaterialManager.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using UnityEngine; 3 | 4 | using Object = UnityEngine.Object; 5 | 6 | namespace Thesis { 7 | 8 | public sealed class MaterialManager 9 | { 10 | private static readonly MaterialManager _instance = new MaterialManager(); 11 | public static MaterialManager Instance 12 | { 13 | get { return _instance; } 14 | } 15 | 16 | private static bool _isInitialized; 17 | 18 | private Dictionary _materials; 19 | 20 | private Dictionary> _collections; 21 | 22 | private MaterialManager () 23 | { 24 | _materials = new Dictionary(); 25 | _collections = new Dictionary>(); 26 | _isInitialized = false; 27 | } 28 | 29 | public void Init () 30 | { 31 | if (!_isInitialized) 32 | { 33 | CreateDoorShutter(); 34 | CreateWindowBalcony(); 35 | CreateRoofRelated(); 36 | CreateWalls(); 37 | CreateCity(); 38 | 39 | Material mat; 40 | foreach (ProceduralTexture tex 41 | in TextureManager.Instance.GetCollection("tex_comp_decor")) 42 | { 43 | mat = new Material(Shader.Find("Transparent/Cutout/Diffuse")); 44 | mat.mainTexture = tex.content; 45 | MaterialManager.Instance.AddToCollection("mat_comp_decor", mat); 46 | } 47 | 48 | foreach (ProceduralTexture tex 49 | in TextureManager.Instance.GetCollection("tex_comp_decor_simple")) 50 | { 51 | mat = new Material(Shader.Find("Diffuse")); 52 | mat.mainTexture = tex.content; 53 | MaterialManager.Instance.AddToCollection("mat_comp_decor_simple", mat); 54 | } 55 | 56 | mat = new Material(Shader.Find("Diffuse")); 57 | mat.name = "ComponentFrame"; 58 | mat.color = new Color32(186, 189, 189, 255); 59 | Add(mat.name, mat); 60 | 61 | // lines 62 | mat = new Material(Shader.Find("VertexLit")); 63 | mat.name = "line_block"; 64 | mat.SetColor("_Color", Color.green); 65 | mat.SetColor("_SpecColor", Color.green); 66 | mat.SetColor("_Emission", Color.green); 67 | Add(mat.name, mat); 68 | 69 | mat = new Material(Shader.Find("VertexLit")); 70 | mat.name = "line_lot"; 71 | mat.SetColor("_Color", Color.cyan); 72 | mat.SetColor("_SpecColor", Color.cyan); 73 | mat.SetColor("_Emission", Color.cyan); 74 | Add(mat.name, mat); 75 | 76 | mat = new Material(Shader.Find("VertexLit")); 77 | mat.name = "line_sidewalk"; 78 | mat.SetColor("_Color", Color.red); 79 | mat.SetColor("_SpecColor", Color.red); 80 | mat.SetColor("_Emission", Color.red); 81 | Add(mat.name, mat); 82 | 83 | //Testing(); 84 | _isInitialized = true; 85 | } 86 | } 87 | 88 | public void Unload () 89 | { 90 | foreach (Material m in _materials.Values) 91 | Object.DestroyImmediate(m, true); 92 | _materials.Clear(); 93 | foreach (List l in _collections.Values) 94 | { 95 | foreach (Material m in l) 96 | Object.DestroyImmediate(m, true); 97 | l.Clear(); 98 | } 99 | _collections.Clear(); 100 | _isInitialized = false; 101 | } 102 | 103 | public void Add (string name, Material material) 104 | { 105 | if (!_materials.ContainsKey(name)) 106 | { 107 | material.name = name; 108 | _materials.Add(name, material); 109 | } 110 | } 111 | 112 | public void AddToCollection (string name, Material material) 113 | { 114 | if (_collections.ContainsKey(name)) 115 | { 116 | if (!_collections[name].Contains(material)) 117 | { 118 | material.name = name; 119 | _collections[name].Add(material); 120 | } 121 | } 122 | else 123 | { 124 | var list = new List(); 125 | material.name = name; 126 | list.Add(material); 127 | _collections.Add(name, list); 128 | } 129 | } 130 | 131 | public void Add (string name, string shaderName, ProceduralTexture texture) 132 | { 133 | if (!_materials.ContainsKey(name)) 134 | { 135 | var mat = new Material(Shader.Find(shaderName)); 136 | mat.name = name; 137 | mat.mainTexture = texture.content; 138 | _materials.Add(mat.name, mat); 139 | } 140 | } 141 | 142 | public void AddToCollection (string collectionName, string shaderName, 143 | ProceduralTexture texture) 144 | { 145 | var mat = new Material(Shader.Find(shaderName)); 146 | mat.mainTexture = texture.content; 147 | if (_collections.ContainsKey(collectionName)) 148 | { 149 | mat.name = collectionName + "_" + (_collections[collectionName].Count + 1).ToString(); 150 | _collections[collectionName].Add(mat); 151 | } 152 | else 153 | { 154 | mat.name = collectionName + "_1"; 155 | var list = new List(); 156 | list.Add(mat); 157 | _collections.Add(collectionName, list); 158 | } 159 | } 160 | 161 | public void Set (string name, Material material) 162 | { 163 | if (_materials.ContainsKey(name)) 164 | _materials[name] = material; 165 | } 166 | 167 | public Material FindByTextureName (string name) 168 | { 169 | foreach (Material m in _materials.Values) 170 | { 171 | if (m.mainTexture != null) 172 | if (m.mainTexture.name == name) 173 | return m; 174 | } 175 | 176 | foreach (List l in _collections.Values) 177 | foreach (Material m in l) 178 | { 179 | if (m.mainTexture != null) 180 | if (m.mainTexture.name == name) 181 | return m; 182 | } 183 | 184 | return null; 185 | } 186 | 187 | public Material Get (string name) 188 | { 189 | return _materials.ContainsKey(name) ? _materials[name] : null; 190 | } 191 | 192 | public List GetCollection (string name) 193 | { 194 | return _collections.ContainsKey(name) ? _collections[name] : null; 195 | } 196 | 197 | private void CreateDoorShutter () 198 | { 199 | foreach (Color color in ColorManager.Instance.GetCollection("col_components")) 200 | { 201 | foreach (ProceduralTexture tex 202 | in TextureManager.Instance.GetCollection("tex_door")) 203 | { 204 | Material mat = new Material(Shader.Find("Diffuse")); 205 | mat.color = color; 206 | mat.mainTexture = tex.content; 207 | MaterialManager.Instance.AddToCollection("mat_door", mat); 208 | } 209 | 210 | foreach (ProceduralTexture tex 211 | in TextureManager.Instance.GetCollection("tex_shutter")) 212 | { 213 | Material mat = new Material(Shader.Find("Diffuse")); 214 | mat.color = color; 215 | mat.mainTexture = tex.content; 216 | MaterialManager.Instance.AddToCollection("mat_shutter", mat); 217 | } 218 | } 219 | } 220 | 221 | private void CreateWindowBalcony () 222 | { 223 | foreach (ProceduralTexture tex in TextureManager.Instance.GetCollection("tex_window")) 224 | MaterialManager.Instance.AddToCollection("mat_window", "Diffuse", tex); 225 | 226 | foreach (ProceduralTexture tex in TextureManager.Instance.GetCollection("tex_balcony_door")) 227 | MaterialManager.Instance.AddToCollection("mat_balcony_door", 228 | "Diffuse", tex); 229 | 230 | MaterialManager.Instance.Add("mat_balcony_rail", 231 | "Transparent/Cutout/Diffuse", 232 | TextureManager.Instance.Get("tex_balcony")); 233 | } 234 | 235 | private void CreateRoofRelated() 236 | { 237 | if (TextureManager.Instance.GetCollection("tex_roof") != null) 238 | foreach (ProceduralTexture tex in TextureManager.Instance.GetCollection("tex_roof")) 239 | { 240 | Material mat = new Material(Shader.Find("Diffuse")); 241 | mat.mainTexture = tex.content; 242 | MaterialManager.Instance.AddToCollection("mat_roof", mat); 243 | } 244 | 245 | if (TextureManager.Instance.GetCollection("tex_roof_base") != null) 246 | foreach (ProceduralTexture tex in TextureManager.Instance.GetCollection("tex_roof_base")) 247 | { 248 | Material mat = new Material(Shader.Find("Diffuse")); 249 | mat.mainTexture = tex.content; 250 | MaterialManager.Instance.AddToCollection("mat_roof_base", mat); 251 | } 252 | 253 | if (TextureManager.Instance.GetCollection("tex_roof_decor") != null) 254 | foreach (ProceduralTexture tex in TextureManager.Instance.GetCollection("tex_roof_decor")) 255 | { 256 | Material mat = new Material(Shader.Find("Transparent/Cutout/Diffuse")); 257 | mat.mainTexture = tex.content; 258 | MaterialManager.Instance.AddToCollection("mat_roof_decor", mat); 259 | } 260 | } 261 | 262 | private void CreateWalls () 263 | { 264 | Material mat; 265 | foreach (Color color in ColorManager.Instance.GetCollection("col_walls")) 266 | { 267 | mat = new Material(Shader.Find("Diffuse")); 268 | mat.color = color; 269 | AddToCollection("mat_walls", mat); 270 | } 271 | } 272 | 273 | private void CreateCity () 274 | { 275 | Material mat = new Material(Shader.Find("Diffuse")); 276 | mat.color = new Color32(55, 55, 55, 255); 277 | _instance.Add("mat_road", mat); 278 | 279 | mat = new Material(Shader.Find("Diffuse")); 280 | mat.color = Color.gray; 281 | _instance.Add("mat_sidewalk", mat); 282 | 283 | mat = new Material(Shader.Find("Diffuse")); 284 | mat.color = new Color32(0, 55, 0, 255); 285 | _instance.Add("mat_lot", mat); 286 | } 287 | 288 | private void Testing () 289 | { 290 | Material m = new Material(Shader.Find("Diffuse")); 291 | m.mainTexture = TextureManager.Instance.Get("tile3").content; 292 | MaterialManager.Instance.Add("mat_roof", m); 293 | 294 | Material n = new Material(Shader.Find("Diffuse")); 295 | n.mainTexture = TextureManager.Instance.Get("tex_roof_base").content; 296 | MaterialManager.Instance.Add("mat_roof_base", n); 297 | 298 | m = new Material(Shader.Find("Transparent/Cutout/Diffuse")); 299 | m.mainTexture = TextureManager.Instance.Get("decor").content; 300 | MaterialManager.Instance.Add("mat_decor", m); 301 | } 302 | } 303 | 304 | } // namespace Thesis -------------------------------------------------------------------------------- /Assets/Standard Assets/Building/BuildingMesh.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections.Generic; 3 | using System.Reflection; 4 | 5 | namespace Thesis { 6 | 7 | public class BuildingMesh : DrawableObject 8 | { 9 | /*************** FIELDS ***************/ 10 | 11 | public readonly Building parent; 12 | 13 | public List faces = new List(); 14 | 15 | private int _floorCount = 0; 16 | public int floorCount 17 | { 18 | get { return _floorCount; } 19 | set 20 | { 21 | _floorCount = value; 22 | if (_floorHeight > 0f) 23 | height = _floorHeight * _floorCount; 24 | } 25 | } 26 | 27 | private float _floorHeight = 0f; 28 | public float floorHeight 29 | { 30 | get { return _floorHeight; } 31 | set 32 | { 33 | _floorHeight = value; 34 | if (_floorCount > 0) 35 | height = _floorHeight * _floorCount; 36 | } 37 | } 38 | 39 | public float height = 0f; 40 | 41 | /// 42 | /// Stores the indexes of faces in sorted order. 43 | /// 44 | public int[] sortedFaces; 45 | 46 | private const float _componentWidthMin = 1.1f; 47 | private const float _componentWidthMax = 1.25f; 48 | private const float _componentSpaceMin = 2f; 49 | private const float _componentSpaceMax = 2.25f; 50 | 51 | public float windowHeight; 52 | 53 | public float doorHeight; 54 | 55 | public float balconyHeight; 56 | 57 | public float balconyFloorHeight; 58 | 59 | public float balconyFloorWidth; 60 | 61 | public float balconyFloorDepth; 62 | 63 | public Roof roof; 64 | 65 | public RoofBase roofBase; 66 | 67 | /*************** CONSTRUCTORS ***************/ 68 | 69 | public BuildingMesh (Building parent, Vector3 p1, Vector3 p2, Vector3 p3, Vector3 p4) 70 | { 71 | this.parent = parent; 72 | name = "neo_building_mesh"; 73 | var list = MaterialManager.Instance.GetCollection("mat_walls"); 74 | material = list[Random.Range(0, list.Count)]; 75 | 76 | parent.AddCombinable(material.name, this); 77 | 78 | if (parent.floorHeight <= 0f) 79 | floorHeight = Random.Range(3.8f, 4f); 80 | else 81 | floorHeight = parent.floorHeight; 82 | 83 | if (parent.floorCount <= 0) 84 | floorCount = Util.RollDice(new float[] {0.15f, 0.7f, 0.15f}); 85 | else 86 | floorCount = parent.floorCount; 87 | 88 | FindMeshOrigin(p1, p3, p2, p4); 89 | 90 | boundaries = new Vector3[8]; 91 | boundaries[0] = p1 - meshOrigin; 92 | boundaries[1] = p2 - meshOrigin; 93 | boundaries[2] = p3 - meshOrigin; 94 | boundaries[3] = p4 - meshOrigin; 95 | 96 | for (int i = 0; i < 4; ++i) 97 | boundaries[i + 4] = boundaries[i] + height * Vector3.up; 98 | 99 | ConstructFaces(); 100 | ConstructFaceComponents(); 101 | ConstructRoof(); 102 | } 103 | 104 | public BuildingMesh (Building parent, BuildingLot lot) 105 | { 106 | this.parent = parent; 107 | name = "neo_building_mesh"; 108 | var list = MaterialManager.Instance.GetCollection("mat_walls"); 109 | material = list[Random.Range(0, list.Count)]; 110 | 111 | parent.AddCombinable(material.name, this); 112 | 113 | if (parent.floorHeight <= 0f) 114 | floorHeight = Random.Range(3.8f, 4f); 115 | else 116 | floorHeight = parent.floorHeight; 117 | 118 | if (parent.floorCount <= 0) 119 | floorCount = Util.RollDice(new float[] {0.15f, 0.7f, 0.15f}); 120 | else 121 | floorCount = parent.floorCount; 122 | 123 | FindMeshOrigin(lot.edges[0].start, lot.edges[2].start, 124 | lot.edges[1].start, lot.edges[3].start); 125 | 126 | boundaries = new Vector3[8]; 127 | boundaries[0] = lot.edges[0].start - meshOrigin; 128 | boundaries[1] = lot.edges[1].start - meshOrigin; 129 | boundaries[2] = lot.edges[2].start - meshOrigin; 130 | boundaries[3] = lot.edges[3].start - meshOrigin; 131 | 132 | for (int i = 0; i < 4; ++i) 133 | boundaries[i + 4] = boundaries[i] + height * Vector3.up; 134 | 135 | ConstructFaces(lot); 136 | ConstructFaceComponents(); 137 | ConstructRoof(); 138 | } 139 | 140 | /*************** METHODS ***************/ 141 | 142 | public void ConstructFaces () 143 | { 144 | faces.Add(new Face(this, boundaries[0], boundaries[1])); 145 | faces.Add(new Face(this, boundaries[1], boundaries[2])); 146 | faces.Add(new Face(this, boundaries[2], boundaries[3])); 147 | faces.Add(new Face(this, boundaries[3], boundaries[0])); 148 | 149 | SortFaces(); 150 | } 151 | 152 | public void ConstructFaces (BuildingLot lot) 153 | { 154 | faces.Add(new Face(this, boundaries[0], boundaries[1], 155 | lot.freeEdges.Contains(0))); 156 | faces.Add(new Face(this, boundaries[1], boundaries[2], 157 | lot.freeEdges.Contains(1))); 158 | faces.Add(new Face(this, boundaries[2], boundaries[3], 159 | lot.freeEdges.Contains(2))); 160 | faces.Add(new Face(this, boundaries[3], boundaries[0], 161 | lot.freeEdges.Contains(3))); 162 | 163 | SortFaces(); 164 | } 165 | 166 | public void ConstructFaceComponents () 167 | { 168 | if (parent.windowHeight <= 0f) 169 | windowHeight = Random.Range(1.5f, 1.7f); 170 | else 171 | windowHeight = parent.windowHeight; 172 | 173 | if (parent.doorHeight <= 0f) 174 | doorHeight = Random.Range(2.8f, 3f); 175 | else 176 | doorHeight = parent.doorHeight; 177 | 178 | if (parent.balconyHeight <= 0f) 179 | if (parent.windowHeight <= 0f) 180 | balconyHeight = windowHeight / 2 + floorHeight / 2.25f; 181 | else 182 | balconyHeight = 0.66f * floorHeight; 183 | else 184 | balconyHeight = parent.balconyHeight; 185 | 186 | balconyFloorHeight = 0.2f; 187 | balconyFloorDepth = 1f; 188 | balconyFloorWidth = 0.6f; 189 | 190 | float component_width = Random.Range(_componentWidthMin, _componentWidthMax); 191 | float inbetween_space = Random.Range(_componentSpaceMin, _componentSpaceMax); 192 | 193 | foreach (Face face in faces) 194 | face.ConstructFaceComponents(component_width, inbetween_space); 195 | } 196 | 197 | private void ConstructRoof() 198 | { 199 | roofBase = new RoofBase(this); 200 | 201 | if (parent.roofBaseMaterial == null) 202 | { 203 | var list = MaterialManager.Instance.GetCollection("mat_roof_base"); 204 | roofBase.material = list[Random.Range(0, list.Count - 1)]; 205 | } 206 | else 207 | roofBase.material = parent.roofBaseMaterial; 208 | parent.AddCombinable(roofBase.material.name, roofBase); 209 | 210 | int maxcpf = Mathf.Max(faces[0].componentsPerFloor, faces[1].componentsPerFloor); 211 | 212 | if (parent.roofType == null) 213 | { 214 | int n = Util.RollDice(new float[] { 0.33f, 0.33f, 0.34f }); 215 | if (n == 1) 216 | roof = new FlatRoof(this); 217 | else if (n == 2 && maxcpf <= 3) 218 | roof = new SinglePeakRoof(this); 219 | else 220 | roof = new DoublePeakRoof(this); 221 | } 222 | else 223 | { 224 | var ctors = parent.roofType.GetConstructors(BindingFlags.Instance | 225 | BindingFlags.Public); 226 | roof = (Roof) ctors[0].Invoke(new object[] { this }); 227 | } 228 | 229 | if (parent.roofMaterial == null) 230 | { 231 | var list = MaterialManager.Instance.GetCollection("mat_roof"); 232 | if (roof.GetType().Equals(typeof(FlatRoof))) 233 | roof.material = list[Random.Range(0, 2)]; 234 | else 235 | roof.material = list[Random.Range(0, list.Count - 1)]; 236 | } 237 | else 238 | roof.material = parent.roofMaterial; 239 | parent.AddCombinable(roof.material.name, roof); 240 | } 241 | 242 | public override void FindVertices () 243 | { 244 | int vert_count = 0; 245 | for (int i = 0; i < 4; ++i) 246 | { 247 | faces[i].FindVertices(); 248 | vert_count += faces[i].vertices.Length; 249 | } 250 | 251 | vertices = new Vector3[vert_count + 4]; 252 | 253 | // add roof vertices first 254 | for (int i = 0; i < 4; ++i) 255 | vertices[i] = boundaries[i + 4]; 256 | 257 | // copy the vertices of the faces to this.vertices 258 | // index starts from 4 because of roof vertices 259 | int index = 4; 260 | for (int i = 0; i < 4; ++i) 261 | { 262 | System.Array.Copy(faces[i].vertices, 0, vertices, index, faces[i].vertices.Length); 263 | index += faces[i].vertices.Length; 264 | } 265 | } 266 | 267 | public override void FindTriangles () 268 | { 269 | int tris_count = 0; 270 | for (int i = 0; i < 4; ++i) 271 | if (faces[i].componentsPerFloor == 0) 272 | tris_count += 2; 273 | else 274 | tris_count += floorCount * (6 * faces[i].componentsPerFloor + 2); 275 | 276 | triangles = new int[tris_count * 3]; 277 | 278 | // triangles index 279 | int trin = 0; 280 | int offset = 4; 281 | 282 | for (int face = 0; face < 4; ++face) 283 | { 284 | if (faces[face].componentsPerFloor == 0) 285 | { 286 | triangles[trin++] = offset; 287 | triangles[trin++] = offset + 1; 288 | triangles[trin++] = offset + 2; 289 | 290 | triangles[trin++] = offset; 291 | triangles[trin++] = offset + 2; 292 | triangles[trin++] = offset + 3; 293 | } 294 | else 295 | { 296 | for (int floor = 0; floor < floorCount; ++floor) 297 | { 298 | int fixedOffset = offset + faces[face].edgeVerticesCount + 299 | 8 * faces[face].componentsPerFloor * floor; 300 | int cpfX6 = 6 * faces[face].componentsPerFloor; 301 | int floorX2 = 2 * floor; 302 | 303 | triangles[trin++] = offset + floorX2; 304 | triangles[trin++] = fixedOffset; 305 | triangles[trin++] = offset + floorX2 + 2; 306 | 307 | triangles[trin++] = fixedOffset; 308 | triangles[trin++] = fixedOffset + cpfX6; 309 | triangles[trin++] = offset + floorX2 + 2; 310 | 311 | // wall between each component 312 | int index = fixedOffset + 1; 313 | for (int i = 1; i < faces[face].componentsPerFloor; ++i) 314 | { 315 | triangles[trin++] = index; 316 | triangles[trin++] = index + 1; 317 | triangles[trin++] = index + cpfX6; 318 | 319 | triangles[trin++] = index + 1; 320 | triangles[trin++] = index + cpfX6 + 1; 321 | triangles[trin++] = index + cpfX6; 322 | 323 | index += 2; 324 | } 325 | 326 | triangles[trin++] = index; 327 | triangles[trin++] = offset + floorX2 + 1; 328 | triangles[trin++] = index + cpfX6; 329 | 330 | triangles[trin++] = offset + floorX2 + 1; 331 | triangles[trin++] = offset + floorX2 + 3; 332 | triangles[trin++] = index + cpfX6; 333 | 334 | // wall over and under each component 335 | for (int i = 0; i < faces[face].componentsPerFloor; ++i) 336 | { 337 | int extOffset = fixedOffset + (i << 1); 338 | 339 | // under 340 | triangles[trin++] = extOffset; 341 | triangles[trin++] = extOffset + 1; 342 | triangles[trin++] = extOffset + 2 * faces[face].componentsPerFloor; 343 | 344 | triangles[trin++] = extOffset + 1; 345 | triangles[trin++] = extOffset + 2 * faces[face].componentsPerFloor + 1; 346 | triangles[trin++] = extOffset + 2 * faces[face].componentsPerFloor; 347 | 348 | // over 349 | triangles[trin++] = extOffset + 4 * faces[face].componentsPerFloor; 350 | triangles[trin++] = extOffset + 4 * faces[face].componentsPerFloor + 1; 351 | triangles[trin++] = extOffset + cpfX6; 352 | 353 | triangles[trin++] = extOffset + 4 * faces[face].componentsPerFloor + 1; 354 | triangles[trin++] = extOffset + cpfX6 + 1; 355 | triangles[trin++] = extOffset + cpfX6; 356 | } 357 | } 358 | } 359 | 360 | offset += faces[face].vertices.Length; 361 | } 362 | } 363 | 364 | public override void Draw () 365 | { 366 | base.Draw(); 367 | 368 | foreach (Face face in faces) 369 | foreach (FaceComponent component in face.faceComponents) 370 | component.Draw(); 371 | 372 | gameObject.transform.position = meshOrigin; 373 | gameObject.transform.parent = parent.gameObject.transform; 374 | 375 | roof.FindVertices(); 376 | roof.FindTriangles(); 377 | roof.Draw(); 378 | 379 | roofBase.FindVertices(); 380 | roofBase.FindTriangles(); 381 | roofBase.Draw(); 382 | } 383 | 384 | /// 385 | /// Sorts the faces of the building by width. 386 | /// 387 | public void SortFaces (bool descending = true) 388 | { 389 | List> lkv = new List>(); 390 | for (int i = 0; i < faces.Count; ++i) 391 | lkv.Add(new KeyValuePair(i, faces[i].width)); 392 | 393 | if (descending) 394 | lkv.Sort(delegate (KeyValuePair x, KeyValuePair y) 395 | { 396 | return y.Value.CompareTo(x.Value); 397 | }); 398 | else 399 | lkv.Sort(delegate (KeyValuePair x, KeyValuePair y) 400 | { 401 | return x.Value.CompareTo(y.Value); 402 | }); 403 | 404 | sortedFaces = new int[lkv.Count]; 405 | for (int i = 0; i < lkv.Count; ++i) 406 | sortedFaces[i] = lkv[i].Key; 407 | } 408 | 409 | public override void Destroy() 410 | { 411 | base.Destroy(); 412 | 413 | foreach (Face face in faces) 414 | face.Destroy(); 415 | 416 | roof.Destroy(); 417 | roofBase.Destroy(); 418 | } 419 | } 420 | 421 | } // namespace Thesis -------------------------------------------------------------------------------- /Assets/Standard Assets/City/Block.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace Thesis { 6 | 7 | public class Block 8 | { 9 | /*************** FIELDS ***************/ 10 | 11 | public readonly List edges; 12 | 13 | private bool _isFinal; 14 | 15 | private const float _divergence = 0.05f; 16 | 17 | public BuildingLot initialLot; 18 | 19 | public List finalLots = new List(); 20 | 21 | public readonly float sidewalkWidth = 1.75f; 22 | 23 | public readonly float roadWidth = 2.25f; 24 | 25 | public Vector3[] sidewalkVerts; 26 | 27 | public Vector3[] lotVerts; 28 | 29 | public Road road; 30 | 31 | public Sidewalk sidewalk; 32 | 33 | /*************** CONSTRUCTORS ***************/ 34 | 35 | // the point Vector3.zero must _not_ be used 36 | // as starting point and all 4 points must be 37 | // in the first quadrant 38 | public Block () 39 | : this(new Vector3(1f, 0f, 0f), 40 | new Vector3(0f, 0f, 300f), 41 | new Vector3(500f, 0f, 300f), 42 | new Vector3(500f, 0f, 0f)) 43 | { 44 | CityMapManager.Instance.Clear(); 45 | } 46 | 47 | public Block (Vector3 p1, Vector3 p2, Vector3 p3, Vector3 p4) 48 | { 49 | int i = CityMapManager.Instance.Add(p1); 50 | if (i != -1) 51 | p1 = CityMapManager.Instance.nodes[i]; 52 | 53 | i = CityMapManager.Instance.Add(p2); 54 | if (i != -1) 55 | p2 = CityMapManager.Instance.nodes[i]; 56 | 57 | i = CityMapManager.Instance.Add(p3); 58 | if (i != -1) 59 | p3 = CityMapManager.Instance.nodes[i]; 60 | 61 | i = CityMapManager.Instance.Add(p4); 62 | if (i != -1) 63 | p4 = CityMapManager.Instance.nodes[i]; 64 | 65 | var edgeList = new List(); 66 | edgeList.Add(new Edge(p1, p2)); 67 | edgeList.Add(new Edge(p2, p3)); 68 | edgeList.Add(new Edge(p3, p4)); 69 | edgeList.Add(new Edge(p4, p1)); 70 | 71 | // find index of longest edge 72 | i = edgeList.FindIndex(delegate (Edge edge) { 73 | return edge.length == edgeList.Max(e => e.length); 74 | }); 75 | 76 | // put the edges in clockwise order starting from the biggest 77 | edges = new List(); 78 | for (int j = 0; j < 4; ++j) 79 | edges.Add(edgeList[(i + j) % 4]); 80 | 81 | FindIfIsFinal(); 82 | } 83 | 84 | public void Bisect () 85 | { 86 | if (_isFinal) 87 | { 88 | FindSidewalkNLotVerts(); 89 | CityMapManager.Instance.AddRoad(this); 90 | CityMapManager.Instance.AddSidewalk(this); 91 | initialLot = new BuildingLot(this); 92 | if (initialLot.isFinal()) 93 | { 94 | initialLot.freeEdges.AddRange(new int[] { 0, 1, 2, 3 }); 95 | finalLots.Add(initialLot); 96 | } 97 | else 98 | CreateBuildingLots(); 99 | 100 | CityMapManager.Instance.Add(this); 101 | return; 102 | } 103 | 104 | var big_offset = Random.Range(0f, _divergence * edges[0].length) * edges[0].direction; 105 | if (Util.RollDice(new float[] { 0.5f, 0.5f }) == 1) 106 | big_offset *= -1; 107 | var opp_offset = Random.Range(0f, _divergence * edges[2].length) * edges[2].direction; 108 | if (Util.RollDice(new float[] { 0.5f, 0.5f }) == 1) 109 | opp_offset *= -1; 110 | 111 | Block b1 = new Block(edges[3].start, edges[3].end, 112 | edges[0].middle + big_offset, edges[2].middle + opp_offset); 113 | b1.Bisect(); 114 | Block b2 = new Block(edges[1].start, edges[1].end, 115 | edges[2].middle + opp_offset, edges[0].middle + big_offset); 116 | b2.Bisect(); 117 | } 118 | 119 | private void FindIfIsFinal () 120 | { 121 | float min = edges.Min(e => e.length); 122 | if (min < 25f) 123 | { 124 | _isFinal = true; 125 | return; 126 | } 127 | 128 | if (edges[0].length > 63f) 129 | { 130 | _isFinal = false; 131 | return; 132 | } 133 | 134 | if (min < 35f && Util.RollDice(new float[] { 0.7f, 0.3f }) == 1) 135 | { 136 | _isFinal = true; 137 | return; 138 | } 139 | 140 | if (min < 45f && Util.RollDice(new float[] { 0.3f, 0.7f }) == 1) 141 | { 142 | _isFinal = true; 143 | return; 144 | } 145 | 146 | _isFinal = false; 147 | } 148 | 149 | private void CreateBuildingLots() 150 | { 151 | var es = initialLot.edges; 152 | var minLength = initialLot.edges.Min(e => e.length); 153 | BuildingLot lot; 154 | 155 | if (minLength <= 16f) 156 | { 157 | lot = new BuildingLot(es[0].start, es[0].middle, es[2].middle, es[2].end); 158 | lot.freeEdges.AddRange(new int[] { 0, 2, 3 }); 159 | finalLots.Add(lot); 160 | 161 | lot = new BuildingLot(es[0].middle, es[0].end, es[2].start, es[2].middle); 162 | lot.freeEdges.AddRange(new int[] { 0, 1, 2 }); 163 | finalLots.Add(lot); 164 | return; 165 | } 166 | 167 | if (minLength <= 27f && initialLot.edges[0].length <= 30f) 168 | { 169 | var r = Util.RollDice(new float[] { 0.5f, 0.5f }); 170 | var pointBig = es[0].start + r / 3f * es[0].length * es[0].direction; 171 | var pointOpp = es[2].start + (3 - r) / 3f * es[2].length * es[2].direction; 172 | var pointMid = (pointBig + pointOpp) / 2; 173 | 174 | lot = new BuildingLot(es[1].start, es[1].middle, pointMid, pointBig); 175 | lot.freeEdges.AddRange(new int[] { 0, 3 }); 176 | finalLots.Add(lot); 177 | 178 | lot = new BuildingLot(es[1].middle, es[1].end, pointOpp, pointMid); 179 | lot.freeEdges.AddRange(new int[] { 0, 1 }); 180 | finalLots.Add(lot); 181 | 182 | lot = new BuildingLot(es[0].start, pointBig, pointMid, es[3].middle); 183 | lot.freeEdges.AddRange(new int[] { 0, 3 }); 184 | finalLots.Add(lot); 185 | 186 | lot = new BuildingLot(pointOpp, es[2].end, es[3].middle, pointMid); 187 | lot.freeEdges.AddRange(new int[] { 0, 1 }); 188 | finalLots.Add(lot); 189 | return; 190 | } 191 | 192 | if (minLength <= 27f && es[0].length <= 40f) 193 | { 194 | var bisector = new Edge(es[3].middle, es[1].middle); 195 | var r = Random.Range(11, 16); 196 | 197 | var p1big = es[0].start + r * es[0].direction; 198 | var p2big = p1big + Vector3.Distance(p1big, es[0].end) / 2 * es[0].direction; 199 | var p1mid = es[3].middle + r / es[0].length * bisector.length * bisector.direction; 200 | var p2mid = p1mid + Vector3.Distance(p1mid, bisector.end) / 2 * bisector.direction; 201 | 202 | lot = new BuildingLot(es[0].start, p1big, p1mid, bisector.start); 203 | lot.freeEdges.AddRange(new int[] { 0, 3 }); 204 | finalLots.Add(lot); 205 | 206 | lot = new BuildingLot(p1big, p2big, p2mid, p1mid); 207 | lot.freeEdges.Add(0); 208 | finalLots.Add(lot); 209 | 210 | lot = new BuildingLot(p2big, es[0].end, bisector.end, p2mid); 211 | lot.freeEdges.AddRange(new int[] { 0, 1 }); 212 | finalLots.Add(lot); 213 | 214 | var p1opp = es[2].start + r * es[2].direction; 215 | var p2opp = p1opp + Vector3.Distance(p1opp, es[2].end) / 2 * es[2].direction; 216 | var p3mid = es[1].middle - r / es[2].length * bisector.length * bisector.direction; 217 | var p4mid = p3mid - Vector3.Distance(p3mid, bisector.start) / 2 * bisector.direction; 218 | 219 | lot = new BuildingLot(es[2].start, p1opp, p3mid, es[1].middle); 220 | lot.freeEdges.AddRange(new int[] { 0, 3 }); 221 | finalLots.Add(lot); 222 | 223 | lot = new BuildingLot(p1opp, p2opp, p4mid, p3mid); 224 | lot.freeEdges.Add(0); 225 | finalLots.Add(lot); 226 | 227 | lot = new BuildingLot(p2opp, es[2].end, es[3].middle, p4mid); 228 | lot.freeEdges.AddRange(new int[] { 0, 1 }); 229 | finalLots.Add(lot); 230 | 231 | return; 232 | } 233 | 234 | // for initialLots larger than 40x27 235 | 236 | CityMapManager.Instance.AddDrawableLot(initialLot); 237 | 238 | // big face range -> 11 - 20 239 | // small face range -> 6 - 9 240 | // therefore small = (3big + 21) / 9 241 | float r1, r2; 242 | Vector3 p1, p2, p3, p4; 243 | 244 | for (int i = 0; i < 3; i+=2) 245 | while (es[i].length - initialLot.occupied[i] > 7f) 246 | { 247 | if (initialLot.pointsInEdge[i].Count == 0) 248 | { 249 | r1 = Random.Range(11, 20); 250 | r2 = (3 * r1 + 21) / 9f; 251 | p1 = es[i].start; 252 | p2 = p1 + r1 * es[i].direction; 253 | p4 = es[i].start - r2 * es[(i + 3) % 4].direction; 254 | p3 = Util.IntersectionPoint(p2, es[i].right, p4, es[i].direction); 255 | 256 | initialLot.pointsInEdge[i].Add(p2); 257 | initialLot.occupied[i] += r1; 258 | initialLot.pointsInEdge[(i + 3) % 4].Add(p4); 259 | initialLot.occupied[(i + 3) % 4] += r2; 260 | 261 | lot = new BuildingLot(p1, p2, p3, p4); 262 | lot.freeEdges.AddRange(new int[] { 0, 3 }); 263 | finalLots.Add(lot); 264 | } 265 | else 266 | { 267 | r1 = es[i].length - initialLot.occupied[i]; 268 | if (r1 > 31f) 269 | { 270 | r1 = Random.Range(11, 20); 271 | r2 = (3 * r1 + 21) / 9f; 272 | 273 | p1 = initialLot.pointsInEdge[i].Last(); 274 | p2 = p1 + r1 * es[i].direction; 275 | p3 = p2 + r2 * es[i].right; 276 | p4 = p1 + r2 * es[i].right; 277 | 278 | initialLot.pointsInEdge[i].Add(p2); 279 | initialLot.occupied[i] += r1; 280 | 281 | lot = new BuildingLot(p1, p2, p3, p4); 282 | lot.freeEdges.Add(0); 283 | finalLots.Add(lot); 284 | } 285 | else if (25f <= r1 && r1 <= 31f) 286 | { 287 | r1 = r1 / 2; 288 | r2 = (3 * r1 + 21) / 9f; 289 | 290 | p1 = initialLot.pointsInEdge[i].Last(); 291 | p2 = p1 + r1 * es[i].direction; 292 | p3 = p2 + r2 * es[i].right; 293 | p4 = p1 + r2 * es[i].right; 294 | 295 | initialLot.pointsInEdge[i].Add(p2); 296 | initialLot.occupied[i] += r1; 297 | 298 | lot = new BuildingLot(p1, p2, p3, p4); 299 | lot.freeEdges.Add(0); 300 | finalLots.Add(lot); 301 | } 302 | else if (19f <= r1 && r1 <= 25f) 303 | { 304 | r1 -= 7f; 305 | r2 = (3 * r1 + 21) / 9f; 306 | 307 | p1 = initialLot.pointsInEdge[i].Last(); 308 | p2 = p1 + r1 * es[i].direction; 309 | p3 = p2 + r2 * es[(i + 1) % 4].direction; 310 | p4 = p1 + r2 * es[i].right; 311 | 312 | initialLot.pointsInEdge[i].Add(p2); 313 | initialLot.occupied[i] += r1; 314 | 315 | lot = new BuildingLot(p1, p2, p3, p4); 316 | lot.freeEdges.Add(0); 317 | finalLots.Add(lot); 318 | } 319 | else if (11f <= r1 && r1 <= 19f) 320 | { 321 | r2 = (3 * r1 + 21) / 9f; 322 | 323 | p1 = initialLot.pointsInEdge[i].Last(); 324 | p2 = es[i].end; 325 | p3 = es[i].end + r2 * es[(i + 1) % 4].direction; 326 | p4 = Util.IntersectionPoint(p1, es[i].right, p3, es[i].direction); 327 | 328 | initialLot.pointsInEdge[(i + 1) % 4].Add(p3); 329 | initialLot.occupied[(i + 1) % 4] += r2; 330 | initialLot.occupied[i] += r1; 331 | 332 | lot = new BuildingLot(p1, p2, p3, p4); 333 | lot.freeEdges.AddRange(new int[] { 0, 1 }); 334 | finalLots.Add(lot); 335 | } 336 | else 337 | break; 338 | } 339 | } 340 | 341 | for (int i = 1; i < 4; i+=2) 342 | { 343 | if (initialLot.pointsInEdge[i].Count == 2) 344 | { 345 | if (Vector3.Distance(es[i].start, initialLot.pointsInEdge[i][0]) > 346 | Vector3.Distance(es[i].start, initialLot.pointsInEdge[i][1])) 347 | initialLot.pointsInEdge[i].Reverse(); 348 | 349 | r1 = Vector3.Distance(initialLot.pointsInEdge[i][0], initialLot.pointsInEdge[i][1]); 350 | if (r1 <= 12f) 351 | r2 = r1; 352 | else 353 | r2 = (3 * r1 + 21) / 9f; 354 | 355 | p1 = initialLot.pointsInEdge[i][0]; 356 | p2 = initialLot.pointsInEdge[i][1]; 357 | p3 = p2 + r2 * es[(i + 1) % 4].direction; 358 | p4 = p1 - r2 * es[(i + 3) % 4].direction; 359 | 360 | lot = new BuildingLot(p1, p2, p3, p4); 361 | lot.freeEdges.Add(0); 362 | finalLots.Add(lot); 363 | continue; 364 | } 365 | 366 | if (initialLot.pointsInEdge[i].Count == 1) 367 | { 368 | var dist = Vector3.Distance(es[i].start, initialLot.pointsInEdge[i][0]); 369 | 370 | if (dist < 22f) 371 | { 372 | p1 = es[i].start; 373 | p2 = initialLot.pointsInEdge[i][0]; 374 | p4 = initialLot.pointsInEdge[(i + 3) % 4].Last(); 375 | p3 = Util.IntersectionPoint(p4, es[i].direction, 376 | p2, es[(i + 1) % 4].direction); 377 | 378 | lot = new BuildingLot(p1, p2, p3, p4); 379 | lot.freeEdges.AddRange(new int[] { 0, 3 }); 380 | finalLots.Add(lot); 381 | } 382 | else 383 | { 384 | r1 = dist / 2; 385 | 386 | p1 = es[i].start; 387 | p2 = p1 + r1 * es[i].direction; 388 | p4 = initialLot.pointsInEdge[(i + 3) % 4].Last(); 389 | p3 = Util.IntersectionPoint(p4, es[(i + 0) % 4].direction, 390 | p2, es[i].right); 391 | 392 | lot = new BuildingLot(p1, p2, p3, p4); 393 | lot.freeEdges.AddRange(new int[] { 0, 3 }); 394 | finalLots.Add(lot); 395 | 396 | r2 = (3 * r1 + 21) / 9f; 397 | p1 = p2; 398 | p2 = initialLot.pointsInEdge[i][0]; 399 | p3 = p2 + r2 * es[(i + 1) % 4].direction; 400 | p4 = p1 + r2 * es[i].right; 401 | 402 | lot = new BuildingLot(p1, p2, p3, p4); 403 | lot.freeEdges.Add(0); 404 | finalLots.Add(lot); 405 | } 406 | } 407 | } 408 | } 409 | 410 | private void FindSidewalkNLotVerts () 411 | { 412 | sidewalkVerts = new Vector3[4]; 413 | lotVerts = new Vector3[4]; 414 | float angle, dist, sin; 415 | Vector3 dir; 416 | 417 | for (int i = 0; i < 4; ++i) 418 | { 419 | angle = Vector3.Angle(edges[i].direction, -edges[(i + 3) % 4].direction); 420 | sin = Mathf.Sin(angle / 2 * Mathf.Deg2Rad); 421 | dir = (edges[i].direction - edges[(i + 3) % 4].direction).normalized; 422 | 423 | dist = roadWidth / sin; 424 | sidewalkVerts[i] = edges[i].start + dist * dir; 425 | 426 | dist = (roadWidth + sidewalkWidth) / sin; 427 | lotVerts[i] = edges[i].start + dist * dir; 428 | } 429 | } 430 | } 431 | 432 | } // namespace Thesis -------------------------------------------------------------------------------- /Assets/Standard Assets/Editor/Builder.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEditor; 3 | using Thesis; 4 | using System.Collections.Generic; 5 | using System; 6 | 7 | using Object = UnityEngine.Object; 8 | 9 | public class Builder : EditorWindow 10 | { 11 | // dimensions stuff 12 | private Vector2 _p1 = Vector2.zero; 13 | private Vector2 _p2 = Vector2.zero; 14 | private Vector2 _p3 = Vector2.zero; 15 | private Vector2 _p4 = Vector2.zero; 16 | private float _width = 0f, _depth = 0f, _height = 0f; 17 | private int _floors = 0; 18 | 19 | private enum Area { noChoice, dimensions, points } 20 | private Area choice1 = Area.noChoice; 21 | 22 | private enum Heights 23 | { 24 | noChoice, 25 | floorCount, 26 | floorHeight, 27 | floorCountAndHeight 28 | } 29 | private Heights choice2 = Heights.noChoice; 30 | 31 | // component stuff 32 | private bool inputCompCount = false; 33 | private float compDist = 0f; 34 | private bool windowFoldout = false; 35 | private float windowHeight = 0f; 36 | private float windowWidth = 0f; 37 | private bool setWindowWidth = false; 38 | private bool setWindowHeight = false; 39 | private bool doorFoldout = false; 40 | private float doorHeight = 0f; 41 | private float doorWidth = 0f; 42 | private bool setDoorWidth = false; 43 | private bool setDoorHeight = false; 44 | private bool balconyFoldout = false; 45 | private bool setBalconyWidth = false; 46 | private float balconyWidth = 0f; 47 | private bool setBalconyHeight = false; 48 | private float balconyHeight = 0f; 49 | 50 | // roof stuff 51 | private enum myRType 52 | { 53 | noChoice, 54 | Flat, 55 | SinglePeak, 56 | DoublePeak 57 | } 58 | private myRType rtype = myRType.noChoice; 59 | private bool inputRoofDecor = false; 60 | private Object roofDecorTexture; 61 | private bool inputRoof = false; 62 | private Object roofTexture; 63 | private bool inputRoofBase = false; 64 | private Object roofBaseTexture; 65 | 66 | private static Building _building; 67 | 68 | [MenuItem ("Window/Builder")] 69 | static void Init () 70 | { 71 | ColorManager.Instance.Init(); 72 | TextureManager.Instance.Init(); 73 | MaterialManager.Instance.Init(); 74 | 75 | _building = new Building(); 76 | 77 | EditorWindow.GetWindow(typeof(Builder), false, "Builder"); 78 | } 79 | 80 | void OnGUI () 81 | { 82 | GUILayout.Space(20); 83 | EditorGUILayout.BeginHorizontal(); 84 | if (GUILayout.Button("Destroy")) 85 | _building.Destroy(); 86 | 87 | if (GUILayout.Button("Create")) 88 | { 89 | _building.Destroy(); 90 | _building.Init(); 91 | _building.CreateBuilding(); 92 | _building.Draw(); 93 | } 94 | EditorGUILayout.EndHorizontal(); 95 | 96 | GUILayout.Space(20); 97 | BuildingDimensions(); 98 | GUILayout.Space(10); 99 | ComponentParams(); 100 | GUILayout.Space(10); 101 | RoofParams(); 102 | } 103 | 104 | void OnDestroy () 105 | { 106 | _building.Destroy(); 107 | ColorManager.Instance.Unload(); 108 | TextureManager.Instance.Unload(); 109 | MaterialManager.Instance.Unload(); 110 | } 111 | 112 | private void BuildingDimensions () 113 | { 114 | EditorGUILayout.LabelField("Dimensions", EditorStyles.boldLabel); 115 | 116 | choice1 = (Area) EditorGUILayout.EnumPopup("Area", choice1); 117 | switch (choice1) 118 | { 119 | case Area.dimensions: 120 | _building.startingPoints = null; 121 | 122 | _width = EditorGUILayout.FloatField("Width", _width); 123 | _depth = EditorGUILayout.FloatField("Depth", _depth); 124 | _building.width0 = _width; 125 | _building.width1 = _depth; 126 | break; 127 | 128 | case Area.points: 129 | _building.width0 = 0f; 130 | _building.width1 = 0f; 131 | 132 | _p1 = EditorGUILayout.Vector2Field("point 1", _p1); 133 | _p2 = EditorGUILayout.Vector2Field("point 2", _p2); 134 | _p3 = EditorGUILayout.Vector2Field("point 3", _p3); 135 | _p4 = EditorGUILayout.Vector2Field("point 4", _p4); 136 | 137 | if (_p1 != _p2 && _p1 != _p3 && _p1 != _p4 && _p2 != _p3 && 138 | _p2 != _p4 && _p3 != _p4) 139 | { 140 | _building.startingPoints = new Vector3[4]; 141 | _building.startingPoints[0] = new Vector3(_p1.x, 0f, _p1.y); 142 | _building.startingPoints[1] = new Vector3(_p2.x, 0f, _p2.y); 143 | _building.startingPoints[2] = new Vector3(_p3.x, 0f, _p3.y); 144 | _building.startingPoints[3] = new Vector3(_p4.x, 0f, _p4.y); 145 | } 146 | break; 147 | 148 | default: 149 | _building.width0 = 0f; 150 | _building.width1 = 0f; 151 | _building.startingPoints = null; 152 | break; 153 | } 154 | 155 | choice2 = (Heights) EditorGUILayout.EnumPopup("Height", choice2); 156 | switch (choice2) 157 | { 158 | case Heights.floorCount: 159 | _floors = EditorGUILayout.IntField("Floor Count", _floors); 160 | _building.floorCount = _floors; 161 | _building.floorHeight = 0f; 162 | break; 163 | 164 | case Heights.floorHeight: 165 | _height = EditorGUILayout.FloatField("Floor Height", _height); 166 | _building.floorHeight = _height; 167 | _building.floorCount = 0; 168 | break; 169 | 170 | case Heights.floorCountAndHeight: 171 | _floors = EditorGUILayout.IntField("Floor Count", _floors); 172 | _height = EditorGUILayout.FloatField("Floor Height", _height); 173 | _building.floorHeight = _height; 174 | _building.floorCount = _floors; 175 | break; 176 | 177 | default: 178 | _building.floorHeight = 0f; 179 | _building.floorCount = 0; 180 | break; 181 | } 182 | } 183 | 184 | private void ComponentParams () 185 | { 186 | EditorGUILayout.LabelField("Components", EditorStyles.boldLabel); 187 | 188 | EditorGUILayout.BeginHorizontal(); 189 | EditorGUILayout.LabelField("Component distance"); 190 | inputCompCount = EditorGUILayout.Toggle(inputCompCount); 191 | if (inputCompCount) 192 | { 193 | compDist = EditorGUILayout.FloatField(compDist, GUILayout.Width(30)); 194 | _building.componentDistance = compDist; 195 | } 196 | else 197 | { 198 | compDist = 0; 199 | _building.componentDistance = 0; 200 | } 201 | EditorGUILayout.EndHorizontal(); 202 | 203 | //EditorGUILayout.BeginHorizontal(); 204 | //EditorGUILayout.LabelField("Component distance"); 205 | //inputCompDistance = EditorGUILayout.Toggle(inputCompDistance); 206 | //if (inputCompDistance) 207 | //{ 208 | // distance = EditorGUILayout.FloatField(distance, GUILayout.Width(25)); 209 | // _building.distance = distance; 210 | //} 211 | //else 212 | //{ 213 | // distance = 0f; 214 | // _building.distance = 0f; 215 | //} 216 | //EditorGUILayout.EndHorizontal(); 217 | 218 | // Window 219 | windowFoldout = EditorGUILayout.Foldout(windowFoldout, "Window"); 220 | if (windowFoldout) 221 | { 222 | // width 223 | EditorGUILayout.BeginHorizontal(); 224 | EditorGUILayout.LabelField("Width"); 225 | setWindowWidth = EditorGUILayout.Toggle(setWindowWidth); 226 | if (setWindowWidth) 227 | windowWidth = EditorGUILayout.FloatField(windowWidth, GUILayout.Width(30)); 228 | else 229 | windowWidth = 0f; 230 | EditorGUILayout.EndHorizontal(); 231 | _building.windowWidth = windowWidth; 232 | 233 | // height 234 | EditorGUILayout.BeginHorizontal(); 235 | EditorGUILayout.LabelField("Height"); 236 | setWindowHeight = EditorGUILayout.Toggle(setWindowHeight); 237 | if (setWindowHeight) 238 | windowHeight = EditorGUILayout.FloatField(windowHeight, GUILayout.Width(30)); 239 | else 240 | windowHeight = 0f; 241 | EditorGUILayout.EndHorizontal(); 242 | _building.windowHeight = windowHeight; 243 | 244 | // material 245 | //EditorGUILayout.BeginHorizontal(); 246 | //EditorGUILayout.LabelField("Texture"); 247 | //setWindowTexture = EditorGUILayout.Toggle(setWindowTexture); 248 | //if (setWindowTexture) 249 | // windowTexture = EditorGUILayout.ObjectField(windowTexture, 250 | // typeof(Texture), 251 | // false, 252 | // GUILayout.Height(55)); 253 | //else 254 | // windowTexture = null; 255 | //EditorGUILayout.EndHorizontal(); 256 | // find material by windowtexture name 257 | } 258 | 259 | // Door 260 | doorFoldout = EditorGUILayout.Foldout(doorFoldout, "Door"); 261 | if (doorFoldout) 262 | { 263 | // width 264 | EditorGUILayout.BeginHorizontal(); 265 | EditorGUILayout.LabelField("Width"); 266 | setDoorWidth = EditorGUILayout.Toggle(setDoorWidth); 267 | if (setDoorWidth) 268 | doorWidth = EditorGUILayout.FloatField(doorWidth, GUILayout.Width(30)); 269 | else 270 | doorWidth = 0f; 271 | EditorGUILayout.EndHorizontal(); 272 | _building.doorWidth = doorWidth; 273 | 274 | // height 275 | EditorGUILayout.BeginHorizontal(); 276 | EditorGUILayout.LabelField("Height"); 277 | setDoorHeight = EditorGUILayout.Toggle(setDoorHeight); 278 | if (setDoorHeight) 279 | doorHeight = EditorGUILayout.FloatField(doorHeight, GUILayout.Width(30)); 280 | else 281 | doorHeight = 0f; 282 | EditorGUILayout.EndHorizontal(); 283 | _building.doorHeight = doorHeight; 284 | 285 | // material 286 | //EditorGUILayout.BeginHorizontal(); 287 | //EditorGUILayout.LabelField("Texture"); 288 | //setDoorTexture = EditorGUILayout.Toggle(setDoorTexture); 289 | //if (setDoorTexture) 290 | // doorTexture = EditorGUILayout.ObjectField(doorTexture, 291 | // typeof(Texture), 292 | // false, 293 | // GUILayout.Height(55)); 294 | //else 295 | // doorTexture = null; 296 | //EditorGUILayout.EndHorizontal(); 297 | // find material by windowtexture name 298 | } 299 | 300 | // balcony 301 | balconyFoldout = EditorGUILayout.Foldout(balconyFoldout, "Balcony"); 302 | if (balconyFoldout) 303 | { 304 | // width 305 | EditorGUILayout.BeginHorizontal(); 306 | EditorGUILayout.LabelField("Width"); 307 | setBalconyWidth = EditorGUILayout.Toggle(setBalconyWidth); 308 | if (setBalconyWidth) 309 | balconyWidth = EditorGUILayout.FloatField(balconyWidth, GUILayout.Width(30)); 310 | else 311 | balconyWidth = 0f; 312 | EditorGUILayout.EndHorizontal(); 313 | _building.balconyWidth = balconyWidth; 314 | 315 | // height 316 | EditorGUILayout.BeginHorizontal(); 317 | EditorGUILayout.LabelField("Height"); 318 | setBalconyHeight = EditorGUILayout.Toggle(setBalconyHeight); 319 | if (setBalconyHeight) 320 | balconyHeight = EditorGUILayout.FloatField(balconyHeight, GUILayout.Width(30)); 321 | else 322 | balconyHeight = 0f; 323 | EditorGUILayout.EndHorizontal(); 324 | _building.balconyHeight = balconyHeight; 325 | } 326 | } 327 | 328 | private void RoofParams () 329 | { 330 | EditorGUILayout.LabelField("Roof", EditorStyles.boldLabel); 331 | 332 | rtype = (myRType) EditorGUILayout.EnumPopup("Roof type", rtype); 333 | switch (rtype) 334 | { 335 | case myRType.Flat: 336 | _building.roofType = Type.GetType(GetFullType(myRType.Flat)); 337 | EditorGUILayout.BeginHorizontal(); 338 | EditorGUILayout.LabelField("Roof decor texture"); 339 | inputRoofDecor = EditorGUILayout.Toggle(inputRoofDecor); 340 | if (inputRoofDecor) 341 | { 342 | roofDecorTexture = EditorGUILayout.ObjectField(roofDecorTexture, 343 | typeof(Texture), 344 | false, 345 | GUILayout.Height(55)); 346 | if (roofDecorTexture != null) 347 | _building.roofDecorMaterial = MaterialManager.Instance. 348 | FindByTextureName(roofDecorTexture.name); 349 | } 350 | else 351 | { 352 | _building.roofDecorMaterial = null; 353 | roofDecorTexture = null; 354 | } 355 | EditorGUILayout.EndHorizontal(); 356 | break; 357 | 358 | case myRType.SinglePeak: 359 | _building.roofType = Type.GetType(GetFullType(myRType.SinglePeak)); 360 | inputRoofDecor = false; 361 | _building.roofDecorMaterial = null; 362 | break; 363 | 364 | case myRType.DoublePeak: 365 | _building.roofType = Type.GetType(GetFullType(myRType.DoublePeak)); 366 | inputRoofDecor = false; 367 | _building.roofDecorMaterial = null; 368 | break; 369 | 370 | default: 371 | _building.roofType = null; 372 | inputRoofDecor = false; 373 | _building.roofDecorMaterial = null; 374 | break; 375 | } 376 | 377 | // roof texture 378 | EditorGUILayout.BeginHorizontal(); 379 | EditorGUILayout.LabelField("Roof texture"); 380 | inputRoof = EditorGUILayout.Toggle(inputRoof); 381 | if (inputRoof) 382 | { 383 | roofTexture = EditorGUILayout.ObjectField(roofTexture, 384 | typeof(Texture), 385 | false, 386 | GUILayout.Height(55)); 387 | if (roofTexture != null) 388 | _building.roofMaterial = MaterialManager.Instance. 389 | FindByTextureName(roofTexture.name); 390 | } 391 | else 392 | { 393 | _building.roofMaterial = null; 394 | roofTexture = null; 395 | } 396 | EditorGUILayout.EndHorizontal(); 397 | 398 | // roof base texture 399 | EditorGUILayout.BeginHorizontal(); 400 | EditorGUILayout.LabelField("Roof base texture"); 401 | inputRoofBase = EditorGUILayout.Toggle(inputRoofBase); 402 | if (inputRoofBase) 403 | { 404 | roofBaseTexture = EditorGUILayout.ObjectField(roofBaseTexture, 405 | typeof(Texture), 406 | false, 407 | GUILayout.Height(55)); 408 | if (roofBaseTexture != null) 409 | _building.roofBaseMaterial = MaterialManager.Instance. 410 | FindByTextureName(roofBaseTexture.name); 411 | } 412 | else 413 | { 414 | _building.roofBaseMaterial = null; 415 | roofBaseTexture = null; 416 | } 417 | EditorGUILayout.EndHorizontal(); 418 | } 419 | 420 | private string GetFullType (myRType t) 421 | { 422 | return "Thesis." + t.ToString() + "Roof,Assembly-CSharp-firstpass"; 423 | } 424 | } -------------------------------------------------------------------------------- /Assets/Standard Assets/Building/Face.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | using System.Reflection; 4 | using System.Collections.Generic; 5 | 6 | namespace Thesis { 7 | 8 | public class Face : DrawableObject 9 | { 10 | /*************** FIELDS ***************/ 11 | 12 | public readonly BuildingMesh parentBuilding; 13 | 14 | public Vector3 normal; 15 | 16 | public Vector3 right; 17 | 18 | public float width; 19 | 20 | /// 21 | /// A list containing all of the components attached to this face. 22 | /// 23 | public List faceComponents = new List(); 24 | 25 | /// 26 | /// The number of the components on each floor. 27 | /// 28 | public int componentsPerFloor = 0; 29 | 30 | /// 31 | /// The sum of the components on each floor times two. 32 | /// Helps with the calculation of the vertices' indexes and triangles. 33 | /// 34 | public int verticesPerRow = 0; 35 | 36 | /// 37 | /// The number of vertices on the face's vertical edges, including 38 | /// the boundaries. 39 | /// 40 | public int edgeVerticesCount = 0; 41 | 42 | /// 43 | /// Maps the position (index) of one component to its type. 44 | /// The indexing starts from the bottom right corner and goes 45 | /// to the left and then up. 46 | /// 47 | public Dictionary pattern = new Dictionary(); 48 | 49 | public List doorIndexes = new List(); 50 | 51 | public List balconyIndexes = new List(); 52 | 53 | private bool _isFree; 54 | 55 | public Building masterParent 56 | { 57 | get { return parentBuilding.parent; } 58 | } 59 | 60 | /*************** CONSTRUCTORS ***************/ 61 | 62 | /// 63 | /// Initializes a new instance of the class from the given points, 64 | /// in clockwise order. The clockwise order is required so that the normal of this face 65 | /// is properly calculated. 66 | /// 67 | public Face (BuildingMesh parent, Vector3 dr, Vector3 dl, bool isFree = true) 68 | { 69 | parentBuilding = parent; 70 | _isFree = isFree; 71 | 72 | boundaries = new Vector3[4]; 73 | boundaries[0] = dr; 74 | boundaries[1] = dl; 75 | boundaries[2] = new Vector3(dl.x, dl.y + parentBuilding.height, dl.z); 76 | boundaries[3] = new Vector3(dr.x, dr.y + parentBuilding.height, dr.z); 77 | 78 | right = new Vector3(boundaries[0].x - boundaries[1].x, 79 | 0f, 80 | boundaries[0].z - boundaries[1].z); 81 | width = right.magnitude; 82 | normal = Vector3.Cross(Vector3.up, right); 83 | 84 | right.Normalize(); 85 | normal.Normalize(); 86 | } 87 | 88 | /*************** METHODS ***************/ 89 | 90 | public void ConstructFaceComponents (float component_width, float inbetween_space) 91 | { 92 | if (!_isFree) 93 | { 94 | componentsPerFloor = 0; 95 | return; 96 | } 97 | 98 | float lim = 1.75f; 99 | if (masterParent.componentDistance <= 0f) 100 | componentsPerFloor = Mathf.CeilToInt(width / (component_width + inbetween_space)); 101 | else 102 | { 103 | componentsPerFloor = Mathf.CeilToInt(width / (component_width + masterParent.componentDistance)); 104 | lim = masterParent.componentDistance; 105 | } 106 | float fixed_space = (width - componentsPerFloor * component_width) / (componentsPerFloor + 1); 107 | while (fixed_space < lim) 108 | { 109 | componentsPerFloor -= 1; 110 | fixed_space = (width - componentsPerFloor * component_width) / (componentsPerFloor + 1); 111 | } 112 | 113 | if (componentsPerFloor == 0) 114 | return; 115 | 116 | if (parentBuilding.faces[0] == this) 117 | FindDoorIndexes(); 118 | FindBalconyIndexes(); 119 | 120 | float offset; 121 | int index; 122 | Vector3 dr, dl; 123 | ConstructorInfo[] ctors; 124 | for (int floor = 0; floor < parentBuilding.floorCount; ++floor) 125 | { 126 | offset = fixed_space; 127 | for (int component = 0; component < componentsPerFloor; ++component) 128 | { 129 | index = floor * componentsPerFloor + component; 130 | dr = boundaries[0] - right * offset + floor * parentBuilding.floorHeight * Vector3.up; 131 | dl = dr - right * component_width; 132 | offset += component_width; 133 | if (!pattern.ContainsKey(index)) 134 | pattern[index] = typeof(Window); 135 | 136 | ctors = pattern[index].GetConstructors(BindingFlags.Instance | BindingFlags.Public); 137 | faceComponents.Add((FaceComponent) ctors[0].Invoke(new object[] { this, dr, dl, IndexToCoordinate(index) })); 138 | 139 | offset += fixed_space; 140 | } 141 | } 142 | } 143 | 144 | public override void FindVertices () 145 | { 146 | if (componentsPerFloor == 0) 147 | { 148 | edgeVerticesCount = boundaries.Length; 149 | vertices = boundaries; 150 | return; 151 | } 152 | 153 | edgeVerticesCount = 2 * (parentBuilding.floorCount + 1); 154 | vertices = new Vector3[8 * componentsPerFloor * parentBuilding.floorCount + edgeVerticesCount]; 155 | 156 | for (int i = 0; i < edgeVerticesCount; i += 2) 157 | { 158 | vertices[i] = boundaries[0] + (i / 2) * parentBuilding.floorHeight * Vector3.up; 159 | vertices[i + 1] = boundaries[1] + (i / 2) * parentBuilding.floorHeight * Vector3.up; 160 | } 161 | 162 | int double_cpf = 2 * componentsPerFloor; 163 | for (var floor = 1; floor <= parentBuilding.floorCount; ++floor) 164 | for (var cp = 0; cp < componentsPerFloor; ++cp) 165 | { 166 | int cpn = cp + componentsPerFloor * (floor - 1); 167 | int indexModifier = 8 * componentsPerFloor * (floor - 1) + 2 * cp + edgeVerticesCount; 168 | 169 | vertices[indexModifier] = new Vector3( 170 | faceComponents[cpn].boundaries[0].x, 171 | parentBuilding.boundaries[0].y + (floor - 1) * parentBuilding.floorHeight, 172 | faceComponents[cpn].boundaries[0].z); 173 | 174 | vertices[indexModifier + 1] = new Vector3( 175 | faceComponents[cpn].boundaries[1].x, 176 | parentBuilding.boundaries[0].y + (floor - 1) * parentBuilding.floorHeight, 177 | faceComponents[cpn].boundaries[1].z); 178 | 179 | vertices[indexModifier + double_cpf] = faceComponents[cpn].boundaries[0]; 180 | 181 | vertices[indexModifier + double_cpf + 1] = faceComponents[cpn].boundaries[1]; 182 | 183 | vertices[indexModifier + 2 * double_cpf] = faceComponents[cpn].boundaries[3]; 184 | 185 | vertices[indexModifier + 2 * double_cpf + 1] = faceComponents[cpn].boundaries[2]; 186 | 187 | vertices[indexModifier + 3 * double_cpf] = new Vector3( 188 | faceComponents[cpn].boundaries[3].x, 189 | floor * parentBuilding.floorHeight - parentBuilding.meshOrigin.y, 190 | faceComponents[cpn].boundaries[3].z); 191 | 192 | vertices[indexModifier + 3 * double_cpf + 1] = new Vector3( 193 | faceComponents[cpn].boundaries[2].x, 194 | floor * parentBuilding.floorHeight - parentBuilding.meshOrigin.y, 195 | faceComponents[cpn].boundaries[2].z); 196 | } 197 | } 198 | 199 | private void FindDoorIndexes () 200 | { 201 | switch (componentsPerFloor) 202 | { 203 | case 1: 204 | doorIndexes.Add(0); 205 | break; 206 | 207 | case 2: 208 | doorIndexes.Add(Util.RollDice(new float[] { 0.5f, 0.5f }, new int[] { 0, 1 })); 209 | break; 210 | 211 | case 3: 212 | doorIndexes.Add(1); 213 | break; 214 | 215 | case 4: 216 | doorIndexes.Add(Util.RollDice(new float[] { 0.5f, 0.5f }, new int[] { 0, 3 })); 217 | break; 218 | 219 | case 5: 220 | if (Util.RollDice(new float[] { 0.2f, 0.8f }, new int[] { 1, 2 }) == 1) 221 | doorIndexes.Add(2); 222 | else 223 | doorIndexes.AddRange(new int[] { 0, 4 }); 224 | break; 225 | 226 | default: 227 | if (Util.RollDice(new float[] { 0.2f, 0.8f }, new int[] { 1, 2 }) == 1) 228 | { 229 | if (componentsPerFloor % 2 == 0) 230 | doorIndexes.Add(Util.RollDice(new float[] { 0.5f, 0.5f }, new int[] { 0, componentsPerFloor - 1 })); 231 | else 232 | doorIndexes.Add((componentsPerFloor - 1) / 2); 233 | } 234 | else 235 | doorIndexes.AddRange(new int[] { 0, componentsPerFloor - 1 }); 236 | break; 237 | } 238 | 239 | foreach (int index in doorIndexes) 240 | pattern[index] = typeof(Door); 241 | } 242 | 243 | private void FindBalconyIndexes () 244 | { 245 | int dice; 246 | 247 | switch (parentBuilding.floorCount) 248 | { 249 | // two floors 250 | case 2: 251 | switch (componentsPerFloor) 252 | { 253 | case 1: 254 | break; 255 | 256 | case 2: 257 | break; 258 | 259 | case 3: 260 | if (doorIndexes.Count > 0) 261 | balconyIndexes.Add(doorIndexes[0] + componentsPerFloor); 262 | else if (Util.RollDice(new float[] { 0.3f, 0.7f }) == 1) 263 | balconyIndexes.Add(4); 264 | break; 265 | 266 | case 4: 267 | dice = Util.RollDice(new float[] { 0.3f, 0.4f, 0.3f }); 268 | if (dice == 1) 269 | balconyIndexes.AddRange(new int[] { 5, 6 }); 270 | else if (dice == 2) 271 | balconyIndexes.AddRange(new int[] { 4, 7 }); 272 | break; 273 | 274 | case 5: 275 | dice = Util.RollDice(new float[] { 0.25f, 0.25f, 0.25f, 0.25f }); 276 | switch (dice) 277 | { 278 | case 1: 279 | balconyIndexes.AddRange(new int[] { 5, 7, 9 }); 280 | break; 281 | 282 | case 2: 283 | balconyIndexes.AddRange(new int[] { 5, 9 }); 284 | break; 285 | 286 | case 3: 287 | balconyIndexes.AddRange(new int[] { 6, 7, 8 }); 288 | break; 289 | 290 | default: 291 | break; 292 | } 293 | break; 294 | 295 | case 6: 296 | balconyIndexes.AddRange(new int[] { 8, 9 }); 297 | if (Util.RollDice(new float[] { 0.3f, 0.7f }) == 1) 298 | balconyIndexes.AddRange(new int[] { 6, 11 }); 299 | break; 300 | 301 | case 7: 302 | balconyIndexes.AddRange(new int[] { 9, 10, 11 }); 303 | if (Util.RollDice(new float[] { 0.3f, 0.7f }) == 1) 304 | balconyIndexes.AddRange(new int[] { 7, 13 }); 305 | break; 306 | 307 | default: 308 | if (componentsPerFloor % 2 == 0) 309 | { 310 | var mid = componentsPerFloor + componentsPerFloor / 2 - 1; 311 | balconyIndexes.AddRange(new int[] { mid - 1, mid, mid + 1, mid + 2 }); 312 | if (Util.RollDice(new float[] { 0.3f, 0.7f }) == 1) 313 | balconyIndexes.AddRange(new int[] { componentsPerFloor, 2 * componentsPerFloor - 1 }); 314 | } 315 | else 316 | { 317 | var mid = componentsPerFloor + (componentsPerFloor - 1) / 2; 318 | balconyIndexes.AddRange(new int[] { mid - 1, mid, mid + 1 }); 319 | if (Util.RollDice(new float[] { 0.5f, 0.5f }) == 1) 320 | balconyIndexes.AddRange(new int[] { mid - 2, mid + 2 }); 321 | if (Util.RollDice(new float[] { 0.3f, 0.7f }) == 1) 322 | balconyIndexes.AddRange(new int[] { componentsPerFloor, 2 * componentsPerFloor - 1 }); 323 | } 324 | break; 325 | } 326 | break; 327 | 328 | // three floors 329 | case 3: 330 | switch (componentsPerFloor) 331 | { 332 | case 1: 333 | break; 334 | 335 | case 2: 336 | break; 337 | 338 | case 3: 339 | dice = Util.RollDice(new float[] { 0.5f, 0.25f, 0.25f }); 340 | if (doorIndexes.Count > 0) 341 | balconyIndexes.Add(4); 342 | switch (dice) 343 | { 344 | case 1: 345 | balconyIndexes.Add(7); 346 | break; 347 | 348 | case 2: 349 | balconyIndexes.AddRange(new int[] { 6, 8 }); 350 | break; 351 | 352 | default: 353 | break; 354 | } 355 | break; 356 | 357 | case 4: 358 | dice = Util.RollDice(new float[] { 0.33f, 0.34f, 0.33f }); 359 | switch (dice) 360 | { 361 | case 1: 362 | balconyIndexes.AddRange(new int[] { 5, 6 }); 363 | break; 364 | 365 | case 2: 366 | balconyIndexes.AddRange(new int[] { 9, 10 }); 367 | break; 368 | 369 | case 3: 370 | balconyIndexes.AddRange(new int[] { 5, 6, 9, 10 }); 371 | break; 372 | } 373 | break; 374 | 375 | case 5: 376 | dice = Util.RollDice(new float[] { 0.2f, 0.2f, 0.2f, 0.2f, 0.2f }); 377 | switch (dice) 378 | { 379 | case 1: 380 | balconyIndexes.AddRange(new int[] { 6, 7, 8 }); 381 | break; 382 | 383 | case 2: 384 | balconyIndexes.AddRange(new int[] { 11, 12, 13 }); 385 | break; 386 | 387 | case 3: 388 | balconyIndexes.AddRange(new int[] { 6, 7, 8, 11, 12, 13 }); 389 | break; 390 | 391 | case 4: 392 | balconyIndexes.AddRange(new int[] { 6, 8, 11, 12, 13 }); 393 | break; 394 | 395 | case 5: 396 | balconyIndexes.AddRange(new int[] { 5, 9, 11, 12, 13 }); 397 | break; 398 | } 399 | break; 400 | 401 | case 6: 402 | balconyIndexes.AddRange(new int[] { 8, 9, 14, 15 }); 403 | dice = Util.RollDice(new float[] { 0.3f, 0.3f, 0.4f }); 404 | if (dice == 1) 405 | balconyIndexes.AddRange(new int[] { 6, 11 }); 406 | if (dice == 2) 407 | balconyIndexes.AddRange(new int[] { 12, 13 }); 408 | if (dice == 3) 409 | balconyIndexes.AddRange(new int[] { 6, 11, 12, 13 }); 410 | break; 411 | 412 | case 7: 413 | balconyIndexes.AddRange(new int[] { 9, 10, 11, 16, 17, 18 }); 414 | dice = Util.RollDice(new float[] { 0.3f, 0.7f }); 415 | if (dice == 1) 416 | balconyIndexes.AddRange(new int[] { 7, 13 }); 417 | if (dice == 2) 418 | balconyIndexes.AddRange(new int[] { 14, 20 }); 419 | if (dice == 3) 420 | balconyIndexes.AddRange(new int[] { 7, 13, 14, 20 }); 421 | break; 422 | 423 | default: 424 | break; 425 | } 426 | break; 427 | 428 | default: 429 | break; 430 | } 431 | 432 | foreach (int index in balconyIndexes) 433 | pattern[index] = typeof(Balcony); 434 | } 435 | 436 | public ComponentCoordinate IndexToCoordinate (int index) 437 | { 438 | return new ComponentCoordinate(index / componentsPerFloor, 439 | index % componentsPerFloor); 440 | } 441 | 442 | public override void Destroy() 443 | { 444 | base.Destroy(); 445 | 446 | foreach (FaceComponent fc in faceComponents) 447 | fc.Destroy(); 448 | } 449 | } 450 | 451 | } // namespace Thesis -------------------------------------------------------------------------------- /Assets/Standard Assets/Managers/TextureManager.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using UnityEngine; 3 | 4 | using Object = UnityEngine.Object; 5 | 6 | namespace Thesis { 7 | 8 | public sealed class TextureManager 9 | { 10 | private static readonly TextureManager _instance = new TextureManager(); 11 | public static TextureManager Instance 12 | { 13 | get { return _instance; } 14 | } 15 | 16 | private static bool _isInitialized; 17 | 18 | private Dictionary _textures; 19 | 20 | private Dictionary> _collections; 21 | 22 | private TextureManager () 23 | { 24 | _textures = new Dictionary(); 25 | _collections = new Dictionary>(); 26 | _isInitialized = false; 27 | } 28 | 29 | public void Init () 30 | { 31 | if (!_isInitialized) 32 | { 33 | Object[] texs = Resources.LoadAll("Textures/Door", 34 | typeof(Texture2D)); 35 | for (var i = 0; i < texs.Length; ++i) 36 | AddToCollection("tex_door", 37 | new ProceduralTexture((Texture2D) texs[i])); 38 | 39 | texs = Resources.LoadAll("Textures/Shutter", 40 | typeof(Texture2D)); 41 | for (var i = 0; i < texs.Length; ++i) 42 | AddToCollection("tex_shutter", 43 | new ProceduralTexture((Texture2D) texs[i])); 44 | 45 | texs = Resources.LoadAll("Textures/Roof", 46 | typeof(Texture2D)); 47 | for (var i = 0; i < texs.Length; ++i) 48 | AddToCollection("tex_roof", 49 | new ProceduralTexture((Texture2D) texs[i])); 50 | 51 | texs = Resources.LoadAll("Textures/RoofBase", 52 | typeof(Texture2D)); 53 | for (var i = 0; i < texs.Length; ++i) 54 | AddToCollection("tex_roof_base", 55 | new ProceduralTexture((Texture2D) texs[i])); 56 | 57 | texs = Resources.LoadAll("Textures/RoofDecor", 58 | typeof(Texture2D)); 59 | for (var i = 0; i < texs.Length; ++i) 60 | AddToCollection("tex_roof_decor", 61 | new ProceduralTexture((Texture2D) texs[i])); 62 | 63 | texs = Resources.LoadAll("Textures/CompDecor", 64 | typeof(Texture2D)); 65 | for (var i = 0; i < texs.Length; ++i) 66 | AddToCollection("tex_comp_decor", 67 | new ProceduralTexture((Texture2D) texs[i])); 68 | 69 | texs = Resources.LoadAll("Textures/CompDecorSimple", 70 | typeof(Texture2D)); 71 | for (var i = 0; i < texs.Length; ++i) 72 | AddToCollection("tex_comp_decor_simple", 73 | new ProceduralTexture((Texture2D) texs[i])); 74 | 75 | CreateBalconyRailTexture(); 76 | CreateWindowTextures(); 77 | CreateBalconyBodyTextures(); 78 | 79 | _isInitialized = true; 80 | } 81 | } 82 | 83 | public void Unload () 84 | { 85 | _textures.Clear(); 86 | foreach (List l in _collections.Values) 87 | l.Clear(); 88 | _collections.Clear(); 89 | _isInitialized = false; 90 | } 91 | 92 | public void Add (string name, ProceduralTexture texture) 93 | { 94 | if (!_textures.ContainsKey(name)) 95 | { 96 | texture.content.name = name; 97 | _textures.Add(name, texture); 98 | } 99 | } 100 | 101 | public void AddToCollection (string name, ProceduralTexture texture) 102 | { 103 | if (_collections.ContainsKey(name)) 104 | { 105 | texture.content.name = name + "_" + (_collections[name].Count + 1).ToString(); 106 | _collections[name].Add(texture); 107 | } 108 | else 109 | { 110 | var list = new List(); 111 | texture.content.name = name + "_1"; 112 | list.Add(texture); 113 | _collections.Add(name, list); 114 | } 115 | } 116 | 117 | public void Set (string name, ProceduralTexture texture) 118 | { 119 | if (_textures.ContainsKey(name)) 120 | _textures[name] = texture; 121 | } 122 | 123 | public ProceduralTexture Get (string name) 124 | { 125 | return _textures.ContainsKey(name) ? _textures[name] : null; 126 | } 127 | 128 | public List GetCollection (string name) 129 | { 130 | return _collections.ContainsKey(name) ? _collections[name] : null; 131 | } 132 | 133 | private void CreateBalconyRailTexture () 134 | { 135 | var tex = new ProceduralTexture(); 136 | tex.content = new Texture2D(1024, 512); 137 | tex.Clear(); 138 | 139 | var ratio = 2f; 140 | var outBorderSize = 0.02f; 141 | var inBorderSize = 0.018f; 142 | var spaceBetweenBorders = 0.06f; 143 | 144 | int vOutBorderWidth = Mathf.FloorToInt(tex.content.width * outBorderSize); 145 | int topOutBorderWidth = Mathf.FloorToInt(tex.content.height * outBorderSize * 2 * ratio); 146 | int vInBorderWidth = Mathf.FloorToInt(tex.content.width * inBorderSize); 147 | int hInBorderWidth = Mathf.FloorToInt(tex.content.height * inBorderSize * ratio); 148 | int vInBorderOffset = Mathf.FloorToInt(tex.content.width * spaceBetweenBorders) + 149 | vOutBorderWidth; 150 | int botInBorderOffset = Mathf.FloorToInt(tex.content.height * spaceBetweenBorders * ratio); 151 | 152 | var halfWidth = tex.content.width >> 1; 153 | 154 | int topOutBorderY = tex.content.height - (topOutBorderWidth >> 1); 155 | int botInBorderY = botInBorderOffset + (hInBorderWidth >> 1); 156 | int topInBorderY = tex.content.height - botInBorderY - topOutBorderWidth; 157 | int leftOutBorderX = (vOutBorderWidth >> 1) - 1; 158 | int rightOutBorderX = tex.content.width - leftOutBorderX; 159 | int leftInBorderX = vInBorderOffset + (vInBorderWidth >> 1); 160 | int rightInBorderX = tex.content.width - leftInBorderX; 161 | 162 | // top out border 163 | tex.lines.Add(new TextureLine(0, topOutBorderY, 164 | tex.content.width, topOutBorderY, 165 | Color.black, topOutBorderWidth)); 166 | // bot in border 167 | tex.lines.Add(new TextureLine(0, botInBorderY, 168 | tex.content.width, botInBorderY, 169 | Color.black, hInBorderWidth)); 170 | // top in border 171 | tex.lines.Add(new TextureLine(0, topInBorderY, 172 | tex.content.width, topInBorderY, 173 | Color.black, hInBorderWidth)); 174 | // left out border 175 | tex.lines.Add(new TextureLine(leftOutBorderX, 0, 176 | leftOutBorderX, tex.content.height, 177 | Color.black, vOutBorderWidth)); 178 | // right out border 179 | tex.lines.Add(new TextureLine(rightOutBorderX, 0, 180 | rightOutBorderX, tex.content.height, 181 | Color.black, vOutBorderWidth)); 182 | // left in border 183 | tex.lines.Add(new TextureLine(leftInBorderX, 0, 184 | leftInBorderX, tex.content.width, 185 | Color.black, vInBorderWidth)); 186 | // right in border 187 | tex.lines.Add(new TextureLine(rightInBorderX, 0, 188 | rightInBorderX, tex.content.width, 189 | Color.black, vInBorderWidth)); 190 | // middle border 191 | tex.lines.Add(new TextureLine(halfWidth, 0, 192 | halfWidth, tex.content.height, 193 | Color.black, vInBorderWidth)); 194 | // left inner box 195 | tex.lines.Add(new TextureLine(leftInBorderX, botInBorderY + 2, 196 | halfWidth + 1, topInBorderY, 197 | Color.black, vInBorderWidth)); 198 | 199 | tex.lines.Add(new TextureLine(leftInBorderX, topInBorderY - 1, 200 | halfWidth + 1, botInBorderY, 201 | Color.black, vInBorderWidth)); 202 | // right inner box 203 | tex.lines.Add(new TextureLine(halfWidth + 1, botInBorderY, 204 | rightInBorderX, topInBorderY, 205 | Color.black, vInBorderWidth)); 206 | 207 | tex.lines.Add(new TextureLine(halfWidth + 1, topInBorderY, 208 | rightInBorderX, botInBorderY, 209 | Color.black, vInBorderWidth)); 210 | 211 | tex.Draw(); 212 | 213 | TextureManager.Instance.Add("tex_balcony", tex); 214 | } 215 | 216 | private void CreateWindowTextures () 217 | { 218 | var color = Color.white; 219 | var th = 22; 220 | ProceduralTexture tex; 221 | int h; 222 | 223 | // 1st texture 224 | tex = new ProceduralTexture(512, 1024); 225 | tex.SetBackgroundColor(new Color32(25, 0, 143, 255)); 226 | AddBorders(ref tex, color, th); 227 | h = (tex.content.height * 3) >> 2; 228 | tex.lines.Add(new TextureLine(0, h, tex.content.width, h, 229 | color, th)); 230 | tex.lines.Add(new TextureLine(tex.content.width >> 1, 0, 231 | tex.content.width >> 1, h, 232 | color, th << 1)); 233 | tex.Draw(); 234 | TextureManager.Instance.AddToCollection("tex_window", tex); 235 | // 1st texture 236 | 237 | // 2nd texture 238 | tex = new ProceduralTexture(512, 1024); 239 | tex.SetBackgroundColor(new Color32(25, 0, 143, 255)); 240 | AddBorders(ref tex, color, th); 241 | h = (tex.content.height * 3) >> 2; 242 | tex.lines.Add(new TextureLine(0, h, tex.content.width, h, 243 | color, th)); 244 | tex.lines.Add(new TextureLine(tex.content.width >> 1, 0, 245 | tex.content.width >> 1, h, 246 | color, th << 1)); 247 | tex.lines.Add(new TextureLine(0, h >> 1, tex.content.width, h >> 1, 248 | color, th)); 249 | tex.Draw(); 250 | TextureManager.Instance.AddToCollection("tex_window", tex); 251 | // 2nd texture 252 | 253 | // 3rd texture 254 | tex = new ProceduralTexture(512, 1024); 255 | tex.SetBackgroundColor(new Color32(25, 0, 143, 255)); 256 | AddBorders(ref tex, color, th); 257 | AddBalancedLines(ref tex, 2, color, th); 258 | tex.lines.Add(new TextureLine(tex.content.width >> 1, 0, 259 | tex.content.width >> 1, tex.content.height, 260 | color, th << 1)); 261 | tex.Draw(); 262 | TextureManager.Instance.AddToCollection("tex_window", tex); 263 | // 3rd texture 264 | 265 | // 4th texture 266 | tex = new ProceduralTexture(512, 1024); 267 | tex.SetBackgroundColor(new Color32(25, 0, 143, 255)); 268 | AddBorders(ref tex, color, th); 269 | AddBalancedLines(ref tex, 3, color, th); 270 | tex.lines.Add(new TextureLine(tex.content.width >> 1, 0, 271 | tex.content.width >> 1, (tex.content.height * 3) >> 2, 272 | color, th << 1)); 273 | tex.Draw(); 274 | TextureManager.Instance.AddToCollection("tex_window", tex); 275 | // 4th texture 276 | 277 | // 5th texture 278 | tex = new ProceduralTexture(512, 1024); 279 | tex.SetBackgroundColor(new Color32(25, 0, 143, 255)); 280 | AddBorders(ref tex, color, th); 281 | AddBalancedLines(ref tex, 3, color, th); 282 | tex.lines.Add(new TextureLine(tex.content.width >> 1, 0, 283 | tex.content.width >> 1, tex.content.height, 284 | color, th << 1)); 285 | tex.Draw(); 286 | TextureManager.Instance.AddToCollection("tex_window", tex); 287 | // 5th texture 288 | } 289 | 290 | private void CreateBalconyBodyTextures () 291 | { 292 | var color = Color.white; 293 | var th = 22; 294 | ProceduralTexture tex; 295 | int h; 296 | 297 | // 1st texture 298 | tex = new ProceduralTexture(512, 1024); 299 | tex.SetBackgroundColor(new Color32(25, 0, 143, 255)); 300 | AddBorders(ref tex, color, th); 301 | h = (tex.content.height * 3) >> 2; 302 | tex.lines.Add(new TextureLine(0, h, tex.content.width, h, 303 | color, th)); 304 | tex.lines.Add(new TextureLine(tex.content.width >> 1, 0, 305 | tex.content.width >> 1, h, 306 | color, th << 1)); 307 | tex.Draw(); 308 | TextureManager.Instance.AddToCollection("tex_balcony_door", tex); 309 | // 1st texture 310 | 311 | // 2nd texture 312 | tex = new ProceduralTexture(512, 1024); 313 | tex.SetBackgroundColor(new Color32(25, 0, 143, 255)); 314 | AddBorders(ref tex, color, th); 315 | h = (tex.content.height * 3) >> 2; 316 | tex.lines.Add(new TextureLine(0, h, tex.content.width, h, 317 | color, th)); 318 | tex.lines.Add(new TextureLine(tex.content.width >> 1, 0, 319 | tex.content.width >> 1, h, 320 | color, th << 1)); 321 | tex.lines.Add(new TextureLine(0, h >> 1, tex.content.width, h >> 1, 322 | color, th)); 323 | tex.Draw(); 324 | TextureManager.Instance.AddToCollection("tex_balcony_door", tex); 325 | // 2nd texture 326 | 327 | // 3rd texture 328 | tex = new ProceduralTexture(512, 1024); 329 | tex.SetBackgroundColor(new Color32(25, 0, 143, 255)); 330 | AddBorders(ref tex, color, th); 331 | AddBalancedLines(ref tex, 3, color, th); 332 | tex.lines.Add(new TextureLine(tex.content.width >> 1, 0, 333 | tex.content.width >> 1, tex.content.height, 334 | color, th << 1)); 335 | tex.Draw(); 336 | TextureManager.Instance.AddToCollection("tex_balcony_door", tex); 337 | // 3rd texture 338 | 339 | // 4th texture 340 | tex = new ProceduralTexture(512, 1024); 341 | tex.SetBackgroundColor(new Color32(25, 0, 143, 255)); 342 | AddBorders(ref tex, color, th); 343 | AddBalancedLines(ref tex, 4, color, th); 344 | tex.lines.Add(new TextureLine(tex.content.width >> 1, 0, 345 | tex.content.width >> 1, (tex.content.height << 2) / 5, 346 | color, th << 1)); 347 | tex.Draw(); 348 | TextureManager.Instance.AddToCollection("tex_balcony_door", tex); 349 | // 4th texture 350 | 351 | // 5th texture 352 | tex = new ProceduralTexture(512, 1024); 353 | tex.SetBackgroundColor(new Color32(25, 0, 143, 255)); 354 | AddBorders(ref tex, color, th); 355 | AddBalancedLines(ref tex, 4, color, th); 356 | tex.lines.Add(new TextureLine(tex.content.width >> 1, 0, 357 | tex.content.width >> 1, tex.content.height, 358 | color, th << 1)); 359 | tex.Draw(); 360 | TextureManager.Instance.AddToCollection("tex_balcony_door", tex); 361 | // 5th texture 362 | } 363 | 364 | private void AddBorders (ref ProceduralTexture tex, Color color, int thickness) 365 | { 366 | tex.lines.Add(new TextureLine(thickness >> 1, 0, 367 | thickness >> 1, tex.content.height, 368 | color, thickness)); 369 | tex.lines.Add(new TextureLine(0, thickness >> 1, 370 | tex.content.width, thickness >> 1, 371 | color, thickness)); 372 | tex.lines.Add(new TextureLine(tex.content.width - (thickness >> 1), 0, 373 | tex.content.width - (thickness >> 1), tex.content.height, 374 | color, thickness)); 375 | tex.lines.Add(new TextureLine(0, tex.content.height - (thickness >> 1), 376 | tex.content.width, tex.content.height - (thickness >> 1), 377 | color, thickness)); 378 | } 379 | 380 | private void AddBalancedLines (ref ProceduralTexture tex, int count, 381 | Color color, int thickness) 382 | { 383 | int interval = tex.content.height / (count + 1); 384 | int h = 0; 385 | for (int i = 0; i < count; ++i) 386 | { 387 | h+= interval; 388 | tex.lines.Add(new TextureLine(0, h, 389 | tex.content.width, h, 390 | color, thickness)); 391 | } 392 | } 393 | } 394 | 395 | } // namespace Thesis --------------------------------------------------------------------------------