private void OnDisable() { if (bMesh != null) { bMesh.Clear(); } bMesh = null; if (mesh != null) { mesh.Clear(); } mesh = null; }
public static void Generate(IBuilding building) { int numberOfVolumes = building.numberOfVolumes; // Debug.Log("n vol "+numberOfVolumes); for (int v = 0; v < numberOfVolumes; v++) { IVolume volume = building[v]; volume.CheckVolume(); if (!volume.isLegal) { GenerateMesh.ClearVisuals(volume); continue; } int numberOfPoints = volume.numberOfPoints; float totalPlanHeight = volume.planHeight; Vector3 planUp = totalPlanHeight * Vector3.up; VerticalOpening[] volumeOpenings = BuildrUtils.GetOpeningsQuick(building, volume); float foundation = building.IsBaseVolume(volume) ? building.foundationDepth : 0;//set suspended volumes foundation to 0 IVisualPart visual = volume.visualPart; BuildRMesh dMesh = visual.dynamicMesh; BuildRCollider cMesh = visual.colliderMesh; BuildingMeshTypes meshType = building.meshType; BuildingColliderTypes colliderType = building.colliderType; dMesh.Clear(); cMesh.Clear(); cMesh.TogglePrimitives(colliderType == BuildingColliderTypes.Primitive); cMesh.thickness = volume.wallThickness; if (colliderType == BuildingColliderTypes.None) { cMesh = null; } Transform[] prefabs = volume.prefabs.GetComponentsInChildren <Transform>(); int prefabCount = prefabs.Length; for (int p = 0; p < prefabCount; p++) { if (prefabs[p] == volume.prefabs) { continue; } if (prefabs[p] == null) { continue; //gone already man } #if UNITY_EDITOR Object.DestroyImmediate(prefabs[p].gameObject); #else Object.Destroy(prefabs[p].gameObject); #endif } Dictionary <int, List <Vector2Int> > anchorPoints = volume.facadeWallAnchors; Texture2D facadeTexture = null; #region Exteriors // Debug.Log("ext"); if (building.generateExteriors) { for (int p = 0; p < numberOfPoints; p++) { if (!volume[p].render) { continue; } Vector3 p0 = volume.BuildingPoint(p); Vector3 p1 = volume.BuildingPoint((p + 1) % numberOfPoints); Vector3 p0u = p0 + planUp; Vector3 p1u = p1 + planUp; Vector3 cw0 = volume.BuildingControlPointA(p); Vector3 cw1 = volume.BuildingControlPointB(p); Facade facade = volume.GetFacade(p); bool isStraight = volume.IsWallStraight(p); Vector3 facadeVector = p1 - p0; Vector3 facadeDirection = facadeVector.normalized; float facadeLength = facadeVector.magnitude; if (facadeLength < Mathf.Epsilon) { continue; } // Debug.Log("flength "+facadeLength); if (facade == null || colliderType == BuildingColliderTypes.Simple) { // Debug.Log("simple"); if (isStraight) { Vector3 normal = Vector3.Cross(Vector3.up, facadeDirection); Vector4 tangent = BuildRMesh.CalculateTangent(facadeDirection); if (facade == null) { dMesh.AddPlane(p0, p1, p0u, p1u, normal, tangent, 0); } if (colliderType != BuildingColliderTypes.None) { cMesh.AddPlane(p0, p1, p0u, p1u); } if (foundation > Mathf.Epsilon) { Vector3 fp2 = p0; Vector3 fp3 = p1; Vector3 fp0 = fp2 + Vector3.down * foundation; Vector3 fp1 = fp3 + Vector3.down * foundation; if (facade == null) { Surface foundationSurface = building.foundationSurface != null ? building.foundationSurface : null; int foundationSubmesh = dMesh.submeshLibrary.SubmeshAdd(foundationSurface); Vector2 uxmax = new Vector2(Vector3.Distance(p0, p1), foundation); dMesh.AddPlane(fp0, fp1, fp2, fp3, Vector2.zero, uxmax, normal, tangent, foundationSubmesh, foundationSurface); } if (colliderType != BuildingColliderTypes.None) { cMesh.mesh.AddPlane(fp0, fp1, fp2, fp3, 0); } } } else { List <Vector2Int> facadeAnchorPoints = anchorPoints[p]; int anchorCount = facadeAnchorPoints.Count; for (int i = 0; i < anchorCount - 1; i++) { Vector3 c0 = facadeAnchorPoints[i].vector3XZ; c0.y = p0.y; Vector3 c1 = facadeAnchorPoints[i + 1].vector3XZ; c1.y = p0.y; Vector3 c2 = c0 + planUp; Vector3 c3 = c1 + planUp; Vector3 sectionDirection = (c1 - c0).normalized; Vector3 normal = Vector3.Cross(Vector3.up, sectionDirection); Vector4 tangent = BuildRMesh.CalculateTangent(sectionDirection); if (facade == null) { dMesh.AddPlane(c0, c1, c2, c3, normal, tangent, 0); } if (colliderType != BuildingColliderTypes.None) { cMesh.AddPlane(c0, c1, c2, c3); } if (foundation > Mathf.Epsilon) { Vector3 fp2 = c0; Vector3 fp3 = c1; Vector3 fp0 = fp2 + Vector3.down * foundation; Vector3 fp1 = fp3 + Vector3.down * foundation; if (facade == null) { Surface foundationSurface = building.foundationSurface != null ? building.foundationSurface : null; int foundationSubmesh = dMesh.submeshLibrary.SubmeshAdd(foundationSurface); Vector2 uxmax = new Vector2(Vector3.Distance(c0, c1), foundation); dMesh.AddPlane(fp0, fp1, fp2, fp3, Vector2.zero, uxmax, normal, tangent, foundationSubmesh, foundationSurface); } if (colliderType != BuildingColliderTypes.None) { cMesh.AddPlane(fp0, fp1, fp2, fp3); } } } } // Debug.Log("Generate facade " + p + " " + dMesh.vertexCount ); } // Debug.Log("fac "+p); if (facade != null && (meshType == BuildingMeshTypes.Full || colliderType == BuildingColliderTypes.Primitive || colliderType == BuildingColliderTypes.Complex)) { //generate the facade // Debug.Log("full"); FacadeGenerator.FacadeData fData = new FacadeGenerator.FacadeData(); // fData.building = building; // fData.volume = volume; fData.baseA = p0; fData.baseB = p1; fData.controlA = cw0; fData.controlB = cw1; fData.anchors = anchorPoints[p]; fData.isStraight = isStraight; fData.curveStyle = volume[p].curveStyle; fData.floorCount = volume.floors; fData.facadeDesign = facade; // fData.submeshList = usedFloorplanSurfaces; fData.startFloor = BuildRFacadeUtil.MinimumFloor(building, volume, p); fData.actualStartFloor = building.VolumeBaseFloor(volume); fData.foundationDepth = foundation; fData.foundationSurface = building.foundationSurface; fData.wallThickness = volume.wallThickness; fData.minimumWallUnitLength = volume.minimumWallUnitLength; fData.floorHeight = volume.floorHeight; fData.floors = volume.floors; fData.meshType = building.meshType; fData.colliderType = building.colliderType; fData.cullDoors = building.cullDoors; fData.prefabs = volume.prefabs; // Debug.Log("mesh"); FacadeGenerator.GenerateFacade(fData, dMesh, cMesh); // Debug.Log("pref"); FacadeGenerator.GeneratePrefabs(fData); // Debug.Log("Generate facade "+p+" "+dMesh.vertexCount); } } } #endregion #region Interiors // Debug.Log("int"); bool generateInteriors = building.generateInteriors && meshType == BuildingMeshTypes.Full; if (generateInteriors) { int floors = volume.floors; IFloorplan[] floorplans = volume.InteriorFloorplans(); for (int fl = 0; fl < floors; fl++) { IFloorplan floorplan = floorplans[fl]; IVisualPart floorVisual = floorplan.visualPart; BuildRMesh flMesh = floorVisual.dynamicMesh; BuildRCollider flCollider = floorVisual.colliderMesh; flMesh.Clear(); flCollider.Clear(); flCollider.TogglePrimitives(colliderType == BuildingColliderTypes.Primitive); FloorplanGenerator.Generate(building, volume, floorplans[fl], fl, volumeOpenings, flMesh, flCollider); floorVisual.GenerateFromDynamicMesh(); floorplan.transform.localPosition = Vector3.up * (fl * volume.floorHeight); floorVisual.transform.localPosition = Vector3.zero;// floorVisual.transform.localRotation = Quaternion.identity; } } else { IFloorplan[] floorplans = volume.InteriorFloorplans(); int floors = floorplans.Length; for (int fl = 0; fl < floors; fl++) { floorplans[fl].visualPart.Clear(); } } #endregion #region Volume Underside Generation // Debug.Log("und"); BuildRVolumeUtil.VolumeShape[] underShapes = BuildRVolumeUtil.GetBottomShape(building, volume); int underShapeCount = underShapes.Length; float volumeBaseHeight = volume.baseHeight - building.foundationDepth; for (int u = 0; u < underShapeCount; u++) { if (underShapes[u].outer == null) { continue; //no underside shape } int undersideSubmesh = dMesh.submeshLibrary.SubmeshAdd(volume.undersideSurafce); Poly2TriWrapper.BMesh(dMesh, volumeBaseHeight, null, undersideSubmesh, underShapes[u].outer, new Rect(0, 0, 0, 0), false, underShapes[u].holes); } #endregion // Debug.Log("roof"); if (building.generateExteriors) { RoofGenerator.Generate(building, volume, dMesh, cMesh); visual.GenerateFromDynamicMesh(); } else { visual.Clear(); } // Debug.Log("mat"); switch (meshType) { case BuildingMeshTypes.None: visual.materials = null; break; case BuildingMeshTypes.Box: visual.materials = new[] { new Material(Shader.Find("Standard")) }; break; case BuildingMeshTypes.Simple: facadeTexture.filterMode = FilterMode.Bilinear; facadeTexture.Apply(true, false); Material simpleMaterial = new Material(Shader.Find("Standard")); simpleMaterial.mainTexture = facadeTexture; visual.materials = new[] { simpleMaterial }; break; case BuildingMeshTypes.Full: visual.materials = dMesh.materials.ToArray(); break; } } }
public void Clear() { _mesh.Clear(); _boxList.Clear(); }
public static void Generate(Chimney chimney, GenerationOutput output, SubmeshLibrary submeshLibrary = null) { RGEN.seed = chimney.seed; DYNAMIC_MESH.Clear(); if (submeshLibrary != null) { DYNAMIC_MESH.submeshLibrary.AddRange(submeshLibrary.SURFACES.ToArray()); //DYNAMIC_MESH.submeshLibrary.Inject(ref submeshLibrary); } else { DYNAMIC_MESH.submeshLibrary.Add(chimney); } submeshLibrary = DYNAMIC_MESH.submeshLibrary; //CASE Vector3 caseNoiseVector = new Vector3(chimney.noise.x * RGEN.OneRange(), chimney.noise.y * RGEN.OneRange(), chimney.noise.z * RGEN.OneRange()); Vector3 cs0 = new Vector3(-chimney.caseSize.x * 0.5f, 0, -chimney.caseSize.z * 0.5f); Vector3 cs1 = new Vector3(chimney.caseSize.x * 0.5f, 0, -chimney.caseSize.z * 0.5f); Vector3 cs2 = new Vector3(-chimney.caseSize.x * 0.5f, 0, chimney.caseSize.z * 0.5f); Vector3 cs3 = new Vector3(chimney.caseSize.x * 0.5f, 0, chimney.caseSize.z * 0.5f); Vector3 cs4 = new Vector3(-chimney.caseSize.x * 0.5f, chimney.caseSize.y, -chimney.caseSize.z * 0.5f) + caseNoiseVector; Vector3 cs5 = new Vector3(chimney.caseSize.x * 0.5f, chimney.caseSize.y, -chimney.caseSize.z * 0.5f) + caseNoiseVector; Vector3 cs6 = new Vector3(-chimney.caseSize.x * 0.5f, chimney.caseSize.y, chimney.caseSize.z * 0.5f) + caseNoiseVector; Vector3 cs7 = new Vector3(chimney.caseSize.x * 0.5f, chimney.caseSize.y, chimney.caseSize.z * 0.5f) + caseNoiseVector; Vector2 csuv0 = new Vector2(0, 0); Vector2 csuv1 = new Vector2(chimney.caseSize.x, chimney.caseSize.y); Vector2 csuv2 = new Vector2(csuv1.x, 0); Vector2 csuv3 = new Vector2(csuv1.x + chimney.caseSize.z, chimney.caseSize.y); Vector2 csuv4 = new Vector2(csuv3.x, 0); Vector2 csuv5 = new Vector2(csuv3.x + chimney.caseSize.x, chimney.caseSize.y); Vector2 csuv6 = new Vector2(csuv5.x, 0); Vector2 csuv7 = new Vector2(csuv5.x + chimney.caseSize.z, chimney.caseSize.y); Vector2 csuv8 = new Vector2(0, 0); Vector2 csuv9 = new Vector2(chimney.caseSize.x, chimney.caseSize.z); Vector4 cst0 = new Vector4(0, 0, 1, 0); Vector4 cst1 = new Vector4(1, 0, 1, 0); Vector4 cst2 = new Vector4(0, 0, -1, 0); Vector4 cst3 = new Vector4(-1, 0, 0, 0); Vector4 cst4 = new Vector4(0, 0, 1, 0); int caseSubmesh = submeshLibrary.SubmeshAdd(chimney.caseSurface); //sides DYNAMIC_MESH.AddPlane(cs0, cs1, cs4, cs5, csuv0, csuv1, Vector3.back, cst0, caseSubmesh, chimney.caseSurface); DYNAMIC_MESH.AddPlane(cs1, cs3, cs5, cs7, csuv2, csuv3, Vector3.right, cst1, caseSubmesh, chimney.caseSurface); DYNAMIC_MESH.AddPlane(cs3, cs2, cs7, cs6, csuv4, csuv5, Vector3.forward, cst2, caseSubmesh, chimney.caseSurface); DYNAMIC_MESH.AddPlane(cs2, cs0, cs6, cs4, csuv6, csuv7, Vector3.left, cst3, caseSubmesh, chimney.caseSurface); //top DYNAMIC_MESH.AddPlane(cs4, cs5, cs6, cs7, csuv8, csuv9, Vector3.up, cst4, caseSubmesh, chimney.caseSurface);//todo calculate the values for this - don't be lazy //CROWN Vector3 crownBase = caseNoiseVector + Vector3.up * chimney.caseSize.y; Vector3 crownNoiseVector = new Vector3(chimney.noise.x * RGEN.OneRange(), chimney.noise.y * RGEN.OneRange(), chimney.noise.z * RGEN.OneRange()); Vector3 cr0 = crownBase + new Vector3(-chimney.crownSize.x * 0.5f, 0, -chimney.crownSize.z * 0.5f); Vector3 cr1 = crownBase + new Vector3(chimney.crownSize.x * 0.5f, 0, -chimney.crownSize.z * 0.5f); Vector3 cr2 = crownBase + new Vector3(-chimney.crownSize.x * 0.5f, 0, chimney.crownSize.z * 0.5f); Vector3 cr3 = crownBase + new Vector3(chimney.crownSize.x * 0.5f, 0, chimney.crownSize.z * 0.5f); Vector3 cr4 = crownBase + new Vector3(-chimney.crownSize.x * 0.5f, chimney.crownSize.y, -chimney.crownSize.z * 0.5f) + crownNoiseVector; Vector3 cr5 = crownBase + new Vector3(chimney.crownSize.x * 0.5f, chimney.crownSize.y, -chimney.crownSize.z * 0.5f) + crownNoiseVector; Vector3 cr6 = crownBase + new Vector3(-chimney.crownSize.x * 0.5f, chimney.crownSize.y, chimney.crownSize.z * 0.5f) + crownNoiseVector; Vector3 cr7 = crownBase + new Vector3(chimney.crownSize.x * 0.5f, chimney.crownSize.y, chimney.crownSize.z * 0.5f) + crownNoiseVector; Vector2 cruv0 = new Vector2(0, 0); Vector2 cruv1 = new Vector2(chimney.crownSize.x, chimney.crownSize.y); Vector2 cruv2 = new Vector2(csuv1.x, 0); Vector2 cruv3 = new Vector2(csuv1.x + chimney.caseSize.z, chimney.crownSize.y); Vector2 cruv4 = new Vector2(csuv3.x, 0); Vector2 cruv5 = new Vector2(csuv3.x + chimney.crownSize.x, chimney.crownSize.y); Vector2 cruv6 = new Vector2(csuv5.x, chimney.crownSize.y); Vector2 cruv7 = new Vector2(csuv5.x + chimney.crownSize.z, chimney.crownSize.y); Vector2 cruv8 = new Vector2(0, 0); Vector2 cruv9 = new Vector2(chimney.crownSize.x, chimney.crownSize.z); Vector4 crt0 = new Vector4(0, 0, 1, 0); Vector4 crt1 = new Vector4(1, 0, 1, 0); Vector4 crt2 = new Vector4(0, 0, -1, 0); Vector4 crt3 = new Vector4(-1, 0, 0, 0); Vector4 crt4 = new Vector4(0, 0, 1, 0); int crownSubmesh = submeshLibrary.SubmeshAdd(chimney.crownSurface); DYNAMIC_MESH.AddPlane(cr0, cr1, cr4, cr5, cruv0, cruv1, Vector3.back, crt0, crownSubmesh, chimney.crownSurface); //todo calculate the values for this - don't be lazy DYNAMIC_MESH.AddPlane(cr1, cr3, cr5, cr7, cruv2, cruv3, Vector3.right, crt1, crownSubmesh, chimney.crownSurface); //todo calculate the values for this - don't be lazy DYNAMIC_MESH.AddPlane(cr3, cr2, cr7, cr6, cruv4, cruv5, Vector3.forward, crt2, crownSubmesh, chimney.crownSurface); //todo calculate the values for this - don't be lazy DYNAMIC_MESH.AddPlane(cr2, cr0, cr6, cr4, cruv6, cruv7, Vector3.left, crt3, crownSubmesh, chimney.crownSurface); //todo calculate the values for this - don't be lazy DYNAMIC_MESH.AddPlane(cr1, cr0, cr3, cr2, cruv8, cruv9, Vector3.down, crt4, crownSubmesh, chimney.crownSurface); //todo calculate the values for this - don't be lazy DYNAMIC_MESH.AddPlane(cr4, cr5, cr6, cr7, cruv8, cruv9, Vector3.up, crt4, crownSubmesh, chimney.crownSurface); //todo calculate the values for this - don't be lazy int xCount = 1; int zCount = 1; if (chimney.allowMultiple) { xCount = Mathf.FloorToInt((chimney.crownSize.x - chimney.flueSpacing) / (chimney.flueSize.x + chimney.flueSpacing)); if (xCount < 1) { xCount = 1; } if (chimney.allowMultipleRows) { zCount = Mathf.FloorToInt((chimney.crownSize.z - chimney.flueSpacing) / (chimney.flueSize.z + chimney.flueSpacing)); if (zCount < 1) { zCount = 1; } } } float xSpacing = (chimney.crownSize.x - chimney.flueSize.x * xCount) / (xCount + 1); float zSpacing = (chimney.crownSize.z - chimney.flueSize.z * zCount) / (zCount + 1); //FLUES for (int x = 0; x < xCount; x++) { for (int z = 0; z < zCount; z++) { Vector3 flueBase = cr4 + new Vector3(xSpacing + x * (chimney.flueSize.x + xSpacing) + chimney.flueSize.x * 0.5f, 0, zSpacing + z * (chimney.flueSize.z + zSpacing) + chimney.flueSize.z * 0.5f); float thickness = (chimney.flueSize.x + chimney.flueSize.z) * 0.05f;//10% float drop = chimney.flueSize.y * 0.9f; Vector4 topTangent = new Vector4(1, 0, 0, 0); Surface useFlueSurface = GenerationUtil.GetSurface(chimney.flueSurfaces, RGEN); int flueSubmesh = submeshLibrary.SubmeshAdd(useFlueSurface); int innerSubmesh = submeshLibrary.SubmeshAdd(chimney.innerSurface); Vector3 flueNoiseVector = new Vector3(chimney.noise.x * RGEN.OneRange(), chimney.noise.y * RGEN.OneRange(), chimney.noise.z * RGEN.OneRange()); if (chimney.square) { Vector3 f0 = flueBase + new Vector3(-chimney.flueSize.x * 0.5f, 0, -chimney.flueSize.z * 0.5f); Vector3 f1 = flueBase + new Vector3(chimney.flueSize.x * 0.5f, 0, -chimney.flueSize.z * 0.5f); Vector3 f2 = flueBase + new Vector3(-chimney.flueSize.x * 0.5f, 0, chimney.flueSize.z * 0.5f); Vector3 f3 = flueBase + new Vector3(chimney.flueSize.x * 0.5f, 0, chimney.flueSize.z * 0.5f); Vector3 f4 = flueBase + new Vector3(-chimney.flueSize.x * 0.5f, chimney.flueSize.y, -chimney.flueSize.z * 0.5f) + flueNoiseVector; Vector3 f5 = flueBase + new Vector3(chimney.flueSize.x * 0.5f, chimney.flueSize.y, -chimney.flueSize.z * 0.5f) + flueNoiseVector; Vector3 f6 = flueBase + new Vector3(-chimney.flueSize.x * 0.5f, chimney.flueSize.y, chimney.flueSize.z * 0.5f) + flueNoiseVector; Vector3 f7 = flueBase + new Vector3(chimney.flueSize.x * 0.5f, chimney.flueSize.y, chimney.flueSize.z * 0.5f) + flueNoiseVector; Vector3 f4i = f4 + new Vector3(thickness, 0, thickness) + flueNoiseVector; Vector3 f5i = f5 + new Vector3(-thickness, 0, thickness) + flueNoiseVector; Vector3 f6i = f6 + new Vector3(thickness, 0, -thickness) + flueNoiseVector; Vector3 f7i = f7 + new Vector3(-thickness, 0, -thickness) + flueNoiseVector; Vector3 f4id = f4i + new Vector3(0, -drop, 0); Vector3 f5id = f5i + new Vector3(0, -drop, 0); Vector3 f6id = f6i + new Vector3(0, -drop, 0); Vector3 f7id = f7i + new Vector3(0, -drop, 0); // Vector2 fuv0 = new Vector2(0, 0); // Vector2 fuv1 = new Vector2(chimney.flueSize.x, 0); // Vector2 fuv2 = new Vector2(fuv1.x + chimney.flueSize.z, 0); // Vector2 fuv3 = new Vector2(fuv2.x + chimney.flueSize.x, 0); // // Vector2 fuv4 = new Vector2(0, chimney.flueSize.y); // Vector2 fuv5 = new Vector2(chimney.flueSize.x, chimney.flueSize.y); // Vector2 fuv6 = new Vector2(fuv1.x + chimney.flueSize.z, chimney.flueSize.y); // Vector2 fuv7 = new Vector2(fuv2.x + chimney.flueSize.x, chimney.flueSize.y); //Flue Sides DYNAMIC_MESH.AddPlane(f0, f1, f4, f5, flueSubmesh); //todo calculate the values for this - don't be lazy DYNAMIC_MESH.AddPlane(f1, f3, f5, f7, flueSubmesh); //todo calculate the values for this - don't be lazy DYNAMIC_MESH.AddPlane(f3, f2, f7, f6, flueSubmesh); //todo calculate the values for this - don't be lazy DYNAMIC_MESH.AddPlane(f2, f0, f6, f4, flueSubmesh); //todo calculate the values for this - don't be lazy //Flue Top DYNAMIC_MESH.AddPlaneComplex(f4, f5, f4i, f5i, Vector3.up, topTangent, flueSubmesh, useFlueSurface); //todo calculate the values for this - don't be lazy DYNAMIC_MESH.AddPlaneComplex(f5, f7, f5i, f7i, Vector3.up, topTangent, flueSubmesh, useFlueSurface); //todo calculate the values for this - don't be lazy DYNAMIC_MESH.AddPlaneComplex(f7, f6, f7i, f6i, Vector3.up, topTangent, flueSubmesh, useFlueSurface); //todo calculate the values for this - don't be lazy DYNAMIC_MESH.AddPlaneComplex(f6, f4, f6i, f4i, Vector3.up, topTangent, flueSubmesh, useFlueSurface); //todo calculate the values for this - don't be lazy //Flue Drop DYNAMIC_MESH.AddPlane(f5id, f4id, f5i, f4i, innerSubmesh); //todo calculate the values for this - don't be lazy DYNAMIC_MESH.AddPlane(f7id, f5id, f7i, f5i, innerSubmesh); //todo calculate the values for this - don't be lazy DYNAMIC_MESH.AddPlane(f6id, f7id, f6i, f7i, innerSubmesh); //todo calculate the values for this - don't be lazy DYNAMIC_MESH.AddPlane(f4id, f6id, f4i, f6i, innerSubmesh); //todo calculate the values for this - don't be lazy DYNAMIC_MESH.AddPlane(f4id, f5id, f6id, f7id, innerSubmesh); //todo calculate the values for this - don't be lazy } else { int vertCount = (chimney.segments + 1) * 2;//add an additonal so we can wrap the UVs well RawMeshData flueOuter = new RawMeshData(vertCount, chimney.segments * 6); RawMeshData flueTop = new RawMeshData(vertCount, chimney.segments * 6); //add additional point for the middle, bottom of the inside of the flue RawMeshData flueInner = new RawMeshData(vertCount + 1, chimney.segments * 9); //the additonal point at the bottom of the flue - added to the end of the mesh data flueInner.vertices[vertCount] = flueBase; flueInner.normals[vertCount] = Vector3.up; flueInner.tangents[vertCount] = new Vector4(1, 0, 0, 0); int indexIm = flueInner.vertCount - 1; float circumference = Mathf.PI * (chimney.flueSize.x + chimney.flueSize.z); for (int s = 0; s < chimney.segments + 1; s++) { float percent = s / (float)(chimney.segments); percent = (percent + (chimney.angleOffset / 360)) % 1f; int indexV0 = s * 2; int indexV1 = s * 2 + 1; int indexV2 = s * 2 + 2; int indexV3 = s * 2 + 3; if (s == chimney.segments - 1) { indexV2 = 0; indexV3 = 1; } float xa = Mathf.Sin(percent * Mathf.PI * 2) * chimney.flueSize.x * 0.5f; float za = Mathf.Cos(percent * Mathf.PI * 2) * chimney.flueSize.z * 0.5f; // float innerHalf = thickness / (chimney.flueSize.x + chimney.flueSize.z) / 2; float xai = Mathf.Sin(percent * Mathf.PI * 2) * chimney.flueSize.x * 0.4f; float zai = Mathf.Cos(percent * Mathf.PI * 2) * chimney.flueSize.z * 0.4f; Vector3 v0 = flueBase + new Vector3(xa, 0, za); Vector3 v1 = flueBase + new Vector3(xa, chimney.flueSize.y, za) + flueNoiseVector; Vector3 v2 = flueBase + new Vector3(xai, chimney.flueSize.y, zai) + flueNoiseVector; Vector3 v3 = flueBase + new Vector3(xai, chimney.flueSize.y * 0.1f, zai); Vector2 uv0 = new Vector2(-circumference * percent, 0); Vector2 uv1 = new Vector2(-circumference * percent, chimney.flueSize.y); Vector2 uv2 = new Vector2(-circumference * percent, chimney.flueSize.y + 0.1f); Vector2 uv3 = new Vector2(-circumference * percent, 0); int rdnFlueSurfaceIndex = RGEN.Index(chimney.flueSurfaces.Count); Surface flueSurface = rdnFlueSurfaceIndex != -1 ? chimney.flueSurfaces[rdnFlueSurfaceIndex] : null; if (flueSurface != null) { uv0 = flueSurface.CalculateUV(uv0); uv1 = flueSurface.CalculateUV(uv1); uv2 = flueSurface.CalculateUV(uv2); uv3 = flueSurface.CalculateUV(uv3); } flueOuter.vertices[indexV0] = v0; flueOuter.vertices[indexV1] = v1; flueOuter.uvs[indexV0] = uv0; flueOuter.uvs[indexV1] = uv1; flueTop.vertices[indexV0] = v1; flueTop.vertices[indexV1] = v2; flueTop.uvs[indexV0] = uv1; flueTop.uvs[indexV1] = uv2; flueInner.vertices[indexV0] = v2; flueInner.vertices[indexV1] = v3; flueInner.uvs[indexV0] = uv2; flueInner.uvs[indexV1] = uv3; Vector3 outerNormal = new Vector3(Mathf.Sin(percent * Mathf.PI * 2), 0, Mathf.Cos(percent * Mathf.PI * 2)); flueOuter.normals[indexV0] = outerNormal; flueOuter.normals[indexV1] = outerNormal; flueTop.normals[indexV0] = Vector3.up; flueTop.normals[indexV1] = Vector3.up; flueInner.normals[indexV0] = -outerNormal; flueInner.normals[indexV1] = -outerNormal; if (s < chimney.segments) { int tidx0 = s * 6; flueOuter.triangles[tidx0 + 0] = indexV0; flueOuter.triangles[tidx0 + 2] = indexV1; flueOuter.triangles[tidx0 + 1] = indexV2; flueOuter.triangles[tidx0 + 3] = indexV1; flueOuter.triangles[tidx0 + 4] = indexV2; flueOuter.triangles[tidx0 + 5] = indexV3; flueTop.triangles[tidx0 + 0] = indexV0; flueTop.triangles[tidx0 + 2] = indexV1; flueTop.triangles[tidx0 + 1] = indexV2; flueTop.triangles[tidx0 + 3] = indexV1; flueTop.triangles[tidx0 + 4] = indexV2; flueTop.triangles[tidx0 + 5] = indexV3; int tidx0i = s * 9; flueInner.triangles[tidx0i + 0] = indexV0; flueInner.triangles[tidx0i + 2] = indexV1; flueInner.triangles[tidx0i + 1] = indexV2; flueInner.triangles[tidx0i + 3] = indexV1; flueInner.triangles[tidx0i + 4] = indexV2; flueInner.triangles[tidx0i + 5] = indexV3; flueInner.triangles[tidx0i + 6] = indexV1; flueInner.triangles[tidx0i + 7] = indexV3; flueInner.triangles[tidx0i + 8] = indexIm; } } DYNAMIC_MESH.AddData(flueOuter, flueSubmesh); DYNAMIC_MESH.AddData(flueTop, flueSubmesh); DYNAMIC_MESH.AddData(flueInner, innerSubmesh); } } } if (output.raw != null) { output.raw.Copy(DYNAMIC_MESH); } if (output.mesh != null) { output.mesh.Clear(false); DYNAMIC_MESH.Build(output.mesh); } }
//TODO support custom models coming in from roof design public static void Generate(ref BuildRMesh mesh, IVolume volume, List <Vector3[]> roofFaces) { Roof design = volume.roof; float roofDepth = design.depth; float roofHeight = design.height; float dormerWidth = design.dormerWidth; float dormerHeight = design.dormerHeight; int dormerRows = design.dormerRows; if (dormerHeight * dormerRows > roofHeight) { dormerHeight = roofHeight / dormerRows; } float dormerRoofHeight = design.dormerRoofHeight; float roofPitchRad = Mathf.Atan2(roofHeight, roofDepth); float roofHyp = Mathf.Sqrt(roofDepth * roofDepth + roofHeight * roofHeight);//todo make a proper calculation - this is incorrect float dormerDepth = Mathf.Cos(roofPitchRad) * dormerHeight; float dormerHyp = Mathf.Sqrt(dormerHeight * dormerHeight + dormerDepth * dormerDepth); float dormerRowSpace = roofHyp / dormerRows; dormerHyp = Mathf.Min(dormerHyp, dormerRowSpace); float dormerSpace = dormerRowSpace - dormerHyp; float dormerSpaceLerp = dormerSpace / roofHyp; if (INTERNAL_B_MESH == null) { INTERNAL_B_MESH = new BuildRMesh("internal dormer"); } INTERNAL_B_MESH.Clear(); INTERNAL_B_MESH.submeshLibrary.AddRange(mesh.submeshLibrary.MATERIALS.ToArray()); Vector3 bpl = Vector3.left * dormerWidth * 0.5f; Vector3 bpr = Vector3.right * dormerWidth * 0.5f; Vector3 tpc = Vector3.up * dormerHeight; float dormerFaceHeight = dormerHeight - dormerHeight * dormerRoofHeight; Vector3 tpl = bpl + Vector3.up * dormerFaceHeight; Vector3 tpr = bpr + Vector3.up * dormerFaceHeight; Vector3 rpc = tpc + Vector3.back * dormerDepth; Vector3 rpl = tpl + Vector3.back * dormerDepth; Vector3 rpr = tpr + Vector3.back * dormerDepth; Surface mainSurface = design.mainSurface; Surface wallSurface = design.wallSurface; int mainSubmesh = mesh.submeshLibrary.SubmeshAdd(mainSurface); int wallSubmesh = mesh.submeshLibrary.SubmeshAdd(wallSurface); Vector2 sectionSize = new Vector2(dormerWidth, dormerFaceHeight); if (design.wallSection && design.wallSection.CanRender(sectionSize)) { // mesh.submeshLibrary.Add(design.wallSection); mesh.submeshLibrary.Add(design.wallSection); GenerationOutput output = GenerationOutput.CreateRawOutput(); WallSectionGenerator.Generate(design.wallSection, output, sectionSize, false, 0.02f, false, null, mesh.submeshLibrary); Vector3 sectionPos = new Vector3(0, dormerFaceHeight * 0.5f, 0); int[] mapping = new int[output.raw.materials.Count]; for (int s = 0; s < output.raw.materials.Count; s++) { mapping[s] = 0; } INTERNAL_B_MESH.AddDataKeepSubmeshStructure(output.raw, sectionPos, Quaternion.Euler(0, 180, 0), Vector3.one); } else { INTERNAL_B_MESH.AddPlane(bpr, bpl, tpr, tpl, wallSubmesh);//dormer front square } //front triangle INTERNAL_B_MESH.AddTri(tpl, tpr, tpc, Vector3.right, wallSubmesh); //roof Vector3 normalRoofRight = Vector3.Cross((tpr - tpc).normalized, (rpc - tpc).normalized); Vector4 tangentRoofRight = BuildRMesh.CalculateTangent(Vector3.back); Vector3 normalRoofLeft = Vector3.Cross((rpc - tpc).normalized, (tpl - tpc).normalized); Vector4 tangentRoofLeft = BuildRMesh.CalculateTangent(Vector3.forward); Vector2 roofUvMax = new Vector2(dormerDepth, Vector3.Distance(tpc, tpl)); INTERNAL_B_MESH.AddPlane(rpr, tpr, rpc, tpc, Vector2.zero, roofUvMax, normalRoofRight, tangentRoofRight, mainSubmesh, mainSurface); INTERNAL_B_MESH.AddPlane(rpc, tpc, rpl, tpl, Vector2.zero, roofUvMax, normalRoofLeft, tangentRoofLeft, mainSubmesh, mainSurface); //side triangles INTERNAL_B_MESH.AddTri(bpr, rpr, tpr, Vector3.back, wallSubmesh); INTERNAL_B_MESH.AddTri(bpl, tpl, rpl, Vector3.back, wallSubmesh); RawMeshData data = RawMeshData.CopyBuildRMesh(INTERNAL_B_MESH); int roofFaceCount = roofFaces.Count; for (int r = 0; r < roofFaceCount; r++) { Vector3[] roofFace = roofFaces[r]; Vector3 p0 = roofFace[0]; Vector3 p1 = roofFace[1]; Vector3 p2 = roofFace[2]; Vector3 p3 = roofFace[3]; //center line Vector3 pDB = Vector3.Lerp(p0, p1, 0.5f); Vector3 facadeVector = p1 - p0; Vector3 facadeDirection = facadeVector.normalized; Vector3 facadeNormal = Vector3.Cross(Vector3.up, facadeDirection); Vector3 projTL = p0 + Vector3.Project(p2 - p0, facadeDirection); Vector3 projTR = p1 + Vector3.Project(p3 - p1, facadeDirection); float sqrMagP0 = Vector3.SqrMagnitude(p0 - pDB); float sqrMagP1 = Vector3.SqrMagnitude(p1 - pDB); float sqrMagP2 = Vector3.SqrMagnitude(projTL - pDB); float sqrMagP3 = Vector3.SqrMagnitude(projTR - pDB); Vector3 dormerBaseLeft = sqrMagP0 < sqrMagP2 ? p0 : projTL; Vector3 dormerBaseRight = sqrMagP1 < sqrMagP3 ? p1 : projTR; Vector3 roofNormal = BuildRMesh.CalculateNormal(p0, p2, p1); Vector3 roofUp = Vector3.Cross(roofNormal, -facadeDirection); float actualHyp = sqrMagP0 < sqrMagP2?Vector3.Distance(p0, p2 + Vector3.Project(p0 - p2, facadeDirection)) : Vector3.Distance(projTL, p2); Vector3 dormerTopLeft = dormerBaseLeft + roofUp * actualHyp; Vector3 dormerTopRight = dormerBaseRight + roofUp * actualHyp; float topLength = Vector3.Distance(dormerBaseLeft, dormerBaseRight); int numberOfDormers = Mathf.FloorToInt((topLength - design.minimumDormerSpacing * 2) / (design.minimumDormerSpacing + dormerWidth)); if (numberOfDormers == 0) { if (topLength > sectionSize.x) { numberOfDormers = 1; } } for (int dr = 0; dr < dormerRows; dr++) { float rowPercent = dr / (dormerRows + 0f) + dormerSpaceLerp * 0.5f; //row vector Vector3 rl = Vector3.Lerp(dormerBaseLeft, dormerTopLeft, rowPercent); Vector3 rr = Vector3.Lerp(dormerBaseRight, dormerTopRight, rowPercent); for (int dc = 0; dc < numberOfDormers; dc++) { float columnPercent = (dc + 1f) / (numberOfDormers + 1f); Vector3 dormerBegin = Vector3.Lerp(rl, rr, columnPercent); Quaternion meshRot = Quaternion.LookRotation(facadeNormal, Vector3.up); Vector3 meshPos = dormerBegin; //TODO account for the mesh mode of the wall section - custom meshes mesh.AddDataKeepSubmeshStructure(data, meshPos, meshRot, Vector3.one); } } } }
public static void Generate(IBuilding building) { int numberOfVolumes = building.numberOfPlans; for (int v = 0; v < numberOfVolumes; v++) { IVolume volume = building[v]; volume.CheckVolume(); if (!volume.isLegal) { GenerateMesh.ClearVisuals(volume); continue; } int numberOfPoints = volume.numberOfPoints; float totalPlanHeight = volume.planHeight; Vector3 planUp = totalPlanHeight * Vector3.up; // List<Surface> usedFloorplanSurfaces = volume.CalculateSurfaceArray(); // VerticalOpening[] volumeOpenings = BuildrUtils.GetOpeningsQuick(building, volume); IVisualPart visual = volume.visualPart; BuildRMesh dMesh = visual.dynamicMesh; BuildRCollider cMesh = visual.colliderMesh; BuildingMeshTypes meshType = building.meshType; BuildingColliderTypes colliderType = building.colliderType; dMesh.Clear(); dMesh.ignoreSubmeshAssignment = true; cMesh.Clear(); cMesh.TogglePrimitives(colliderType == BuildingColliderTypes.Primitive); cMesh.thickness = volume.wallThickness; if (meshType == BuildingMeshTypes.None && colliderType == BuildingColliderTypes.None) { visual.Clear(); return; } Dictionary <int, List <Vector2Int> > anchorPoints = volume.facadeWallAnchors; Texture2D facadeTexture = null; Rect[] faciaRectangles = null; Rect[] faciaUVs = null; Rect roofRect = new Rect(); Rect roofPixelRect = new Rect(); #region Exteriors if (building.generateExteriors) { // List<Rect> faciaRectangles = null; faciaRectangles = new Rect[numberOfPoints + 1]; //one additional for the roof float foundation = building.IsBaseVolume(volume) ? building.foundationDepth : 0; //set suspended volumes foundation to 0 // faciaRectangles = new List<Rect>(); for (int p = 0; p < numberOfPoints; p++) { if (!volume[p].render) { continue; } int indexA = p; int indexB = (p < numberOfPoints - 1) ? p + 1 : 0; Vector2Int p0 = volume[indexA].position; Vector2Int p1 = volume[indexB].position; float facadeWidth = Vector2Int.DistanceWorld(p0, p1) * PIXELS_PER_METER; int floorBase = BuildRFacadeUtil.MinimumFloor(building, volume, indexA); int numberOfFloors = volume.floors - floorBase; if (numberOfFloors < 1)//no facade - adjacent facade is taller and covers this one { continue; } float floorHeight = volume.floorHeight; float facadeHeight = ((volume.floors - floorBase) * floorHeight) * PIXELS_PER_METER; if (facadeHeight < 0)//?? { facadeWidth = 0; facadeHeight = 0; } Rect newFacadeRect = new Rect(0, 0, facadeWidth, facadeHeight); faciaRectangles[p] = newFacadeRect; // Debug.Log(newFacadeRect); // faciaRectangles.Add(newFacadeRect); } roofRect = new Rect(0, 0, volume.bounds.size.x, volume.bounds.size.z); roofPixelRect = new Rect(0, 0, volume.bounds.size.x * PIXELS_PER_METER, volume.bounds.size.z * PIXELS_PER_METER); faciaRectangles[numberOfPoints] = roofPixelRect; // Debug.Log(roofRect); int currentWidth = RectanglePack.Pack(faciaRectangles, ATLAS_PADDING); currentWidth = RectanglePack.CheckMaxScale(faciaRectangles, currentWidth, MAXIMUM_TEXTURESIZE); faciaUVs = RectanglePack.ConvertToUVSpace(faciaRectangles, currentWidth); facadeTexture = new Texture2D(currentWidth, currentWidth); // float uvOffsetX = 0; int rectIndex = 0; for (int p = 0; p < numberOfPoints; p++) { if (!volume[p].render) { continue; } Vector3 p0 = volume.BuildingPoint(p); Vector3 p1 = volume.BuildingPoint((p + 1) % numberOfPoints); Vector3 p0u = p0 + planUp; Vector3 p1u = p1 + planUp; Vector3 cw0 = volume.BuildingControlPointA(p); Vector3 cw1 = volume.BuildingControlPointB(p); Facade facade = volume.GetFacade(p); bool isStraight = volume.IsWallStraight(p); Vector3 facadeVector = p1 - p0; Vector3 facadeDirection = facadeVector.normalized; FacadeGenerator.FacadeData fData = new FacadeGenerator.FacadeData(); fData.baseA = p0; fData.baseB = p1; fData.controlA = cw0; fData.controlB = cw1; fData.anchors = anchorPoints[p]; fData.isStraight = isStraight; fData.curveStyle = volume[p].curveStyle; fData.floorCount = volume.floors; fData.facadeDesign = facade; fData.wallThickness = volume.wallThickness; fData.minimumWallUnitLength = volume.minimumWallUnitLength; fData.floorHeight = volume.floorHeight; fData.floors = volume.floors; fData.meshType = building.meshType; fData.colliderType = building.colliderType; fData.cullDoors = building.cullDoors; fData.prefabs = volume.prefabs; // fData.submeshList = usedFloorplanSurfaces; fData.startFloor = BuildRFacadeUtil.MinimumFloor(building, volume, p); if (isStraight) { Vector3 normal = Vector3.Cross(Vector3.up, facadeDirection); Vector4 tangent = BuildRMesh.CalculateTangent(facadeDirection); Vector3 fp2 = p0; Vector3 fp3 = p1; Vector3 fp0 = fp2 + Vector3.down * foundation; Vector3 fp1 = fp3 + Vector3.down * foundation; if (meshType == BuildingMeshTypes.Simple) { // if(facade != null) // { if (facade != null) { SimpleTextureGenerator.GenerateFacade(fData, facadeTexture, faciaRectangles[rectIndex]); } Vector3[] verts = { p0, p1, p0u, p1u }; Vector2[] uvs = new Vector2[4]; Rect uvRect = faciaUVs[rectIndex]; uvs[0] = new Vector2(uvRect.xMin, uvRect.yMin); uvs[1] = new Vector2(uvRect.xMax, uvRect.yMin); uvs[2] = new Vector2(uvRect.xMin, uvRect.yMax); uvs[3] = new Vector2(uvRect.xMax, uvRect.yMax); int[] tris = { 0, 2, 1, 1, 2, 3 }; Vector3[] norms = { normal, normal, normal, normal }; Vector4[] tangents = { tangent, tangent, tangent, tangent }; dMesh.AddData(verts, uvs, tris, norms, tangents, 0); if (foundation > Mathf.Epsilon) { dMesh.AddPlane(fp0, fp1, fp2, fp3, uvs[0], uvs[0], normal, tangent, 0, null); } } else { dMesh.AddPlane(p0, p1, p0u, p1u, normal, tangent, 0); if (foundation > Mathf.Epsilon) { dMesh.AddPlane(fp0, fp1, fp2, fp3, normal, tangent, 0); } } if (colliderType != BuildingColliderTypes.None) { cMesh.AddPlane(p0, p1, p0u, p1u); if (foundation > Mathf.Epsilon) { cMesh.mesh.AddPlane(fp0, fp1, fp2, fp3, 0); } } } else { List <Vector2Int> facadeAnchorPoints = anchorPoints[p]; int anchorCount = facadeAnchorPoints.Count; for (int i = 0; i < anchorCount - 1; i++) { Vector3 c0 = facadeAnchorPoints[i].vector3XZ; c0.y = p0.y; Vector3 c1 = facadeAnchorPoints[i + 1].vector3XZ; c1.y = p0.y; Vector3 c2 = c0 + planUp; Vector3 c3 = c1 + planUp; Vector3 sectionDirection = (c1 - c0).normalized; Vector3 normal = Vector3.Cross(Vector3.up, sectionDirection); Vector4 tangent = BuildRMesh.CalculateTangent(sectionDirection); Vector3 fp2 = c0; Vector3 fp3 = c1; Vector3 fp0 = fp2 + Vector3.down * foundation; Vector3 fp1 = fp3 + Vector3.down * foundation; if (meshType == BuildingMeshTypes.Simple) { if (facade != null) { SimpleTextureGenerator.GenerateFacade(fData, facadeTexture, faciaRectangles[rectIndex]); } Rect uvRect = faciaUVs[rectIndex]; float facadePercentA = i / (float)(anchorCount - 1); float facadePercentB = (i + 1) / (float)(anchorCount - 1); float uvxa = uvRect.xMin + uvRect.width * facadePercentA; float uvxb = uvRect.xMin + uvRect.width * facadePercentB; Vector3[] verts = { c0, c1, c2, c3 }; Vector2[] uvs = new Vector2[4]; uvs[0] = new Vector2(uvxa, uvRect.yMin); uvs[1] = new Vector2(uvxb, uvRect.yMin); uvs[2] = new Vector2(uvxa, uvRect.yMax); uvs[3] = new Vector2(uvxb, uvRect.yMax); int[] tris = { 0, 2, 1, 1, 2, 3 }; Vector3[] norms = { normal, normal, normal, normal }; Vector4[] tangents = { tangent, tangent, tangent, tangent }; // Vector2 uvMin = new Vector2(uvOffsetX, 0); // Vector2 uvMax = new Vector2(uvOffsetX + facadeLength, totalPlanHeight); dMesh.AddData(verts, uvs, tris, norms, tangents, 0); // dMesh.AddPlane(p0, p1, p0u, p1u, uvMin, uvMax, normal, tangent, 0); //todo simple mesh with textured facade // rectIndex++; if (foundation > Mathf.Epsilon) { dMesh.AddPlane(fp0, fp1, fp2, fp3, uvs[0], uvs[0], normal, tangent, 0, null); } } else { dMesh.AddPlane(p0, p1, p0u, p1u, normal, tangent, 0); if (foundation > Mathf.Epsilon) { dMesh.AddPlane(fp0, fp1, fp2, fp3, normal, tangent, 0); } } if (colliderType != BuildingColliderTypes.None) { cMesh.AddPlane(c0, c1, c2, c3); if (foundation > Mathf.Epsilon) { cMesh.mesh.AddPlane(fp0, fp1, fp2, fp3, 0); } } } } rectIndex++; } } #endregion #region Interiors IFloorplan[] floorplans = volume.InteriorFloorplans(); int floors = volume.floors; for (int fl = 0; fl < floors; fl++) { floorplans[fl].visualPart.Clear(); } #endregion #region Volume Underside Generation BuildRVolumeUtil.VolumeShape[] underShapes = BuildRVolumeUtil.GetBottomShape(building, volume); int underShapeCount = underShapes.Length; // Debug.Log(underShapeCount); float volumeBaseHeight = volume.baseHeight; for (int u = 0; u < underShapeCount; u++) { // Debug.Log(underShapes[u].outer); if (underShapes[u].outer == null) { continue; //no underside shape } // Debug.Log(underShapes[u].outer.Length); Poly2TriWrapper.BMesh(dMesh, volumeBaseHeight, null, 0, underShapes[u].outer, new Rect(0, 0, 0, 0), false, underShapes[u].holes); } #endregion if (building.generateExteriors) { Surface roofSurface = volume.roof.mainSurface; if (roofSurface != null) { SimpleTextureGenerator.GenerateTexture(facadeTexture, roofSurface, faciaRectangles[faciaRectangles.Length - 1], roofRect); } RoofGenerator.Generate(building, volume, dMesh, cMesh, faciaUVs[faciaUVs.Length - 1]); visual.GenerateFromDynamicMesh(); } else { visual.Clear(); } switch (meshType) { case BuildingMeshTypes.Box: visual.materials = new[] { new Material(Shader.Find("Standard")) }; break; case BuildingMeshTypes.Simple: facadeTexture.filterMode = FilterMode.Bilinear; facadeTexture.Apply(true, false); Material simpleMaterial = new Material(Shader.Find("Standard")); simpleMaterial.mainTexture = facadeTexture; visual.materials = new[] { simpleMaterial }; break; } } }