private static void AddPlane(BuildrRoofDesign design, Vector3 w0, Vector3 w1, Vector3 w2, Vector3 w3, int subMesh, bool flipped) { int textureSubmesh = subMesh; BuildrTexture texture = textures[textureSubmesh]; Vector2 uvSize = Vector2.one; if (texture.tiled) { float planeWidth = Vector3.Distance(w0, w1); float planeHeight = Vector3.Distance(w0, w2); uvSize = new Vector2(planeWidth * (1.0f / texture.textureUnitSize.x), planeHeight * (1.0f / texture.textureUnitSize.y)); if (texture.patterned) { Vector2 uvunits = texture.tileUnitUV; uvSize.x = Mathf.Ceil(uvSize.x / uvunits.x) * uvunits.x; uvSize.y = Mathf.Ceil(uvSize.y / uvunits.y) * uvunits.y; } } else { uvSize.x = texture.tiledX; uvSize.y = texture.tiledY; } if (!flipped) { mesh.AddPlane(w0, w1, w2, w3, Vector2.zero, uvSize, textureSubmesh); } else { uvSize = new Vector2(uvSize.y, uvSize.x); mesh.AddPlane(w0, w1, w2, w3, Vector2.zero, uvSize, textureSubmesh); } }
public void RemoveRoofDesign(BuildrRoofDesign roof) { roofs.Remove(roof); int bRoofIndex = roofs.IndexOf(roof); int numberOfVolumes = plan.numberOfVolumes; for (int s = 0; s < numberOfVolumes; s++) { BuildrVolume volume = plan.volumes[s]; if (volume.roofDesignID >= bRoofIndex && volume.roofDesignID > 0) { volume.roofDesignID--; } } }
private static void Steeple(BuildrVolume volume, BuildrRoofDesign design) { BuildrPlan area = data.plan; int numberOfFloors = volume.numberOfFloors; float floorHeight = data.floorHeight; Vector3 volumeFloorHeight = Vector3.up * (numberOfFloors * floorHeight); Vector3 ridgeVector = Vector3.up * design.height; int numberOfVolumePoints = volume.points.Count; Vector3[] basePoints = new Vector3[numberOfVolumePoints]; Vector3 centrePoint = Vector3.zero; for (int l = 0; l < numberOfVolumePoints; l++) { basePoints[l] = area.points[volume.points[l]].vector3 + volumeFloorHeight; centrePoint += area.points[volume.points[l]].vector3; } centrePoint = (centrePoint / numberOfVolumePoints) + volumeFloorHeight + ridgeVector; for (int l = 0; l < numberOfVolumePoints; l++) { int pointIndexA = l; int pointIndexB = (l < numberOfVolumePoints - 1) ? l + 1 : 0; Vector3[] verts = new Vector3[3] { basePoints[pointIndexA], basePoints[pointIndexB], centrePoint }; float uvWdith = Vector3.Distance(basePoints[pointIndexA], basePoints[pointIndexB]); float uvHeight = design.height; int subMesh = design.GetTexture(BuildrRoofDesign.textureNames.tiles); BuildrTexture texture = textures[subMesh]; if (texture.tiled) { uvWdith *= (1.0f / texture.textureUnitSize.x); uvHeight *= (1.0f / texture.textureUnitSize.y); if (texture.patterned) { Vector2 uvunits = texture.tileUnitUV; uvWdith = Mathf.Ceil(uvWdith / uvunits.x) * uvunits.x; uvHeight = Mathf.Ceil(uvHeight / uvunits.y) * uvunits.y; } } else { uvWdith = texture.tiledX; uvHeight = texture.tiledY; } Vector2[] uvs = new Vector2[3] { new Vector2(-uvWdith / 2, 0), new Vector2(uvWdith / 2, 0), new Vector2(0, uvHeight) }; int[] tri = new int[3] { 1, 0, 2 }; AddData(verts, uvs, tri, subMesh); } }
private static void AddPlaneComplex(BuildrRoofDesign design, Vector3 w0, Vector3 w1, Vector3 w2, Vector3 w3, int subMesh, bool flipped, Vector3 facadeNormal) { Vector3[] verts = new Vector3[4] { w0, w1, w2, w3 }; Vector2[] uvs = BuildrProjectUVs.Project(verts, Vector2.zero, facadeNormal); int[] tris = new int[6] { 1, 0, 2, 1, 2, 3 }; float xDiff = uvs[1].x - uvs[0].x; float yDiff = uvs[1].y - uvs[0].y; for (int p = 1; p < 4; p++) { Vector2 uv = uvs[p]; float ratio = (uv.x - uvs[0].x) / xDiff; uv.y += -yDiff * ratio; uvs[p] = uv; } mesh.AddData(verts, uvs, tris, subMesh); }
private static void ImportRoofs(XmlDocument xml, BuildrData data) { foreach(XmlNode node in xml.SelectNodes("buildr/roofs/roof")) { BuildrRoofDesign roofDesign = new BuildrRoofDesign(""); data.roofs.Add(roofDesign); roofDesign.name = node["name"].FirstChild.Value; roofDesign.style = (BuildrRoofDesign.styles)System.Enum.Parse(typeof(BuildrRoofDesign.styles), node["style"].FirstChild.Value); roofDesign.height = float.Parse(node["height"].FirstChild.Value); roofDesign.depth = float.Parse(node["depth"].FirstChild.Value); roofDesign.floorDepth = float.Parse(node["floorDepth"].FirstChild.Value); roofDesign.direction = int.Parse(node["direction"].FirstChild.Value); roofDesign.sawtoothTeeth = int.Parse(node["sawtoothTeeth"].FirstChild.Value); roofDesign.barrelSegments = int.Parse(node["barrelSegments"].FirstChild.Value); roofDesign.parapet = node["parapet"].FirstChild.Value == valueTrue; roofDesign.parapetStyle = (BuildrRoofDesign.parapetStyles)System.Enum.Parse(typeof(BuildrRoofDesign.parapetStyles), node["parapetStyle"].FirstChild.Value); roofDesign.parapetDesignWidth = float.Parse(node["parapetDesignWidth"].FirstChild.Value); roofDesign.parapetHeight = float.Parse(node["parapetHeight"].FirstChild.Value); roofDesign.parapetFrontDepth = float.Parse(node["parapetFrontDepth"].FirstChild.Value); roofDesign.parapetBackDepth = float.Parse(node["parapetBackDepth"].FirstChild.Value); roofDesign.hasDormers = node["hasDormers"].FirstChild.Value == valueTrue; roofDesign.dormerWidth = float.Parse(node["dormerWidth"].FirstChild.Value); roofDesign.dormerHeight = float.Parse(node["dormerHeight"].FirstChild.Value); roofDesign.dormerRoofHeight = float.Parse(node["dormerRoofHeight"].FirstChild.Value); roofDesign.minimumDormerSpacing = float.Parse(node["minimumDormerSpacing"].FirstChild.Value); roofDesign.dormerHeightRatio = float.Parse(node["dormerHeightRatio"].FirstChild.Value); for(int i = 0; i < 8; i++) { roofDesign.textureValues[i] = int.Parse(node.SelectNodes("textures/texture")[i].FirstChild.Value); roofDesign.flipValues[i] = node.SelectNodes("flipvalues/flipvalue")[i].FirstChild.Value == valueTrue; } } }
private static void FlatRoof(BuildrVolume volume, BuildrRoofDesign design) { BuildrPlan area = data.plan; int volumeIndex = area.volumes.IndexOf(volume); int numberOfVolumePoints = volume.points.Count; int numberOfFloors = volume.numberOfFloors; float floorHeight = data.floorHeight; Vector3 volumeFloorHeight = Vector3.up * (numberOfFloors * floorHeight); //add top base of the flat roof Vector3[] newEndVerts = new Vector3[numberOfVolumePoints]; Vector2[] newEndUVs = new Vector2[numberOfVolumePoints]; int[] tris = new List<int>(area.GetTrianglesBySectorBase(volumeIndex)).ToArray(); int roofTextureID = design.GetTexture(BuildrRoofDesign.textureNames.floor); BuildrTexture texture = data.textures[roofTextureID]; for (int i = 0; i < numberOfVolumePoints; i++) { Vector2z point = area.points[volume.points[i]]; newEndVerts[i] = point.vector3 + volumeFloorHeight; newEndUVs[i] = new Vector2(point.vector2.x / texture.textureUnitSize.x, point.vector2.y / texture.textureUnitSize.y); } AddData(newEndVerts, newEndUVs, tris, design.GetTexture(BuildrRoofDesign.textureNames.floor)); }
private static void GenerateRoof(BuildrData data) { BuildrGenerateConstraints constraints = data.generatorConstraints; RandomGen rgen = constraints.rgen; BuildrRoofDesign roofDesign = new BuildrRoofDesign("default"); List<int> availableRoofStyles = new List<int>(); if(constraints.roofStyleFlat)availableRoofStyles.Add(0); if(constraints.roofStyleMansard)availableRoofStyles.Add(1); if(constraints.roofStyleBarrel)availableRoofStyles.Add(2); if(constraints.roofStyleGabled)availableRoofStyles.Add(3); if(constraints.roofStyleHipped)availableRoofStyles.Add(4); if(constraints.roofStyleLeanto)availableRoofStyles.Add(5); if(constraints.roofStyleSteepled)availableRoofStyles.Add(6); if(constraints.roofStyleSawtooth)availableRoofStyles.Add(7); System.Array A = System.Enum.GetValues(typeof(BuildrRoofDesign.styles)); roofDesign.style = (BuildrRoofDesign.styles)A.GetValue(availableRoofStyles[rgen.OutputRange(0, availableRoofStyles.Count - 1)]); roofDesign.height = rgen.OutputRange(constraints.minimumRoofHeight, constraints.maximumRoofHeight); roofDesign.floorDepth = rgen.OutputRange(constraints.minimumRoofFloorDepth, constraints.maximumRoofFloorDepth); roofDesign.depth = rgen.OutputRange(Mathf.Min(constraints.minimumRoofDepth, roofDesign.floorDepth), constraints.maximumRoofDepth); roofDesign.hasDormers = (constraints.allowDormers) && (rgen.output <= constraints.dormerChance); roofDesign.dormerWidth = rgen.OutputRange(constraints.dormerMinimumWidth, constraints.dormerMaximumWidth); roofDesign.dormerHeight = rgen.OutputRange(constraints.dormerMinimumHeight, Mathf.Min(roofDesign.height,constraints.dormerMaximumHeight)); roofDesign.dormerRoofHeight = rgen.OutputRange(constraints.dormerMinimumRoofHeight, constraints.dormerMaximumRoofHeight); roofDesign.minimumDormerSpacing = rgen.OutputRange(constraints.dormerMinimumSpacing, constraints.dormerMaximumSpacing); roofDesign.dormerHeightRatio = rgen.OutputRange(0.0f, 1.0f); roofDesign.parapet = (constraints.allowParapet) && (rgen.output <= constraints.parapetChance); roofDesign.parapetDesignWidth = rgen.OutputRange(constraints.parapetMinimumDesignWidth, constraints.parapetMaximumDesignWidth); roofDesign.parapetHeight = rgen.OutputRange(constraints.parapetMinimumHeight, constraints.parapetMaximumHeight); roofDesign.parapetFrontDepth = rgen.OutputRange(constraints.parapetMinimumFrontDepth, constraints.parapetMaximumFrontDepth); roofDesign.parapetBackDepth = rgen.OutputRange(constraints.parapetMinimumBackDepth, constraints.parapetMaximumBackDepth); if (roofDesign.style == BuildrRoofDesign.styles.sawtooth) { //make a new window texture for the sawtooth } data.roofs.Add(roofDesign); }
private static void GenerateRoof(BuildrData data) { BuildrGenerateConstraints constraints = data.generatorConstraints; RandomGen rgen = constraints.rgen; BuildrRoofDesign roofDesign = new BuildrRoofDesign("default"); List <int> availableRoofStyles = new List <int>(); if (constraints.roofStyleFlat) { availableRoofStyles.Add(0); } if (constraints.roofStyleMansard) { availableRoofStyles.Add(1); } if (constraints.roofStyleBarrel) { availableRoofStyles.Add(2); } if (constraints.roofStyleGabled) { availableRoofStyles.Add(3); } if (constraints.roofStyleHipped) { availableRoofStyles.Add(4); } if (constraints.roofStyleLeanto) { availableRoofStyles.Add(5); } if (constraints.roofStyleSteepled) { availableRoofStyles.Add(6); } if (constraints.roofStyleSawtooth) { availableRoofStyles.Add(7); } System.Array A = System.Enum.GetValues(typeof(BuildrRoofDesign.styles)); roofDesign.style = (BuildrRoofDesign.styles)A.GetValue(availableRoofStyles[rgen.OutputRange(0, availableRoofStyles.Count - 1)]); roofDesign.height = rgen.OutputRange(constraints.minimumRoofHeight, constraints.maximumRoofHeight); roofDesign.floorDepth = rgen.OutputRange(constraints.minimumRoofFloorDepth, constraints.maximumRoofFloorDepth); roofDesign.depth = rgen.OutputRange(Mathf.Min(constraints.minimumRoofDepth, roofDesign.floorDepth), constraints.maximumRoofDepth); roofDesign.hasDormers = (constraints.allowDormers) && (rgen.output <= constraints.dormerChance); roofDesign.dormerWidth = rgen.OutputRange(constraints.dormerMinimumWidth, constraints.dormerMaximumWidth); roofDesign.dormerHeight = rgen.OutputRange(constraints.dormerMinimumHeight, Mathf.Min(roofDesign.height, constraints.dormerMaximumHeight)); roofDesign.dormerRoofHeight = rgen.OutputRange(constraints.dormerMinimumRoofHeight, constraints.dormerMaximumRoofHeight); roofDesign.minimumDormerSpacing = rgen.OutputRange(constraints.dormerMinimumSpacing, constraints.dormerMaximumSpacing); roofDesign.dormerHeightRatio = rgen.OutputRange(0.0f, 1.0f); roofDesign.parapet = (constraints.allowParapet) && (rgen.output <= constraints.parapetChance); roofDesign.parapetDesignWidth = rgen.OutputRange(constraints.parapetMinimumDesignWidth, constraints.parapetMaximumDesignWidth); roofDesign.parapetHeight = rgen.OutputRange(constraints.parapetMinimumHeight, constraints.parapetMaximumHeight); roofDesign.parapetFrontDepth = rgen.OutputRange(constraints.parapetMinimumFrontDepth, constraints.parapetMaximumFrontDepth); roofDesign.parapetBackDepth = rgen.OutputRange(constraints.parapetMinimumBackDepth, constraints.parapetMaximumBackDepth); if (roofDesign.style == BuildrRoofDesign.styles.sawtooth) { //make a new window texture for the sawtooth } data.roofs.Add(roofDesign); }
private static void Hipped(BuildrVolume volume, BuildrRoofDesign design) { BuildrPlan area = data.plan; int numberOfFloors = volume.numberOfFloors; float baseHeight = data.floorHeight * numberOfFloors; float roofHeight = design.height; int numberOfVolumePoints = volume.points.Count; int subMesh = design.GetTexture(BuildrRoofDesign.textureNames.tiles); Vector2[] volumePoints = new Vector2[numberOfVolumePoints]; for(int i = 0; i < numberOfVolumePoints; i++) { volumePoints[i] = area.points[volume.points[i]].vector2; } Vector2[][] meshData = StraightSkeleton.Calculate(volumePoints); Vector2[] triData = meshData[0]; List<Vector2> interiorPoints = new List<Vector2>(meshData[1]); int numberOfVerts = triData.Length; Vector3[] verts = new Vector3[numberOfVerts]; Vector2[] uvs = new Vector2[numberOfVerts]; int[] tris = new int[numberOfVerts]; for(int i = 0; i < triData.Length; i+=3) { Vector2 pa = triData[i]; Vector2 pb = triData[i+1]; Vector2 pc = triData[i+2]; float ah = baseHeight + (interiorPoints.Contains(pa) ? roofHeight : 0); float bh = baseHeight + (interiorPoints.Contains(pb) ? roofHeight : 0); float ch = baseHeight + (interiorPoints.Contains(pc) ? roofHeight : 0); Vector3 v0 = new Vector3(pa.x, ah, pa.y); Vector3 v1 = new Vector3(pb.x, bh, pb.y); Vector3 v2 = new Vector3(pc.x, ch, pc.y); verts[i] = v0; verts[i+1] = v1; verts[i+2] = v2; Vector3 roofBaseDir = (interiorPoints.Contains(pc)) ? v1 - v0 : v2 - v1; Vector3 roofBaseNormal = Vector3.Cross(roofBaseDir, Vector3.up); Vector2[] uvsMansard = BuildrProjectUVs.Project(new Vector3[3] { v0, v1, v2 }, Vector2.zero, roofBaseNormal); uvs[i] = uvsMansard[0]; uvs[i + 1] = uvsMansard[1]; uvs[i + 2] = uvsMansard[2]; tris[i] = i; tris[i + 1] = i+2; tris[i + 2] = i+1; } AddData(verts,uvs,tris,subMesh); /*Vector3 ridgeVector = Vector3.up * design.height; Vector3[] basePoints = new Vector3[4]; if (design.direction == 0) { basePoints[0] = area.points[volume.points[0]].vector3 + volumeFloorHeight; basePoints[1] = area.points[volume.points[1]].vector3 + volumeFloorHeight; basePoints[2] = area.points[volume.points[2]].vector3 + volumeFloorHeight; basePoints[3] = area.points[volume.points[3]].vector3 + volumeFloorHeight; } else { basePoints[0] = area.points[volume.points[1]].vector3 + volumeFloorHeight; basePoints[1] = area.points[volume.points[2]].vector3 + volumeFloorHeight; basePoints[2] = area.points[volume.points[3]].vector3 + volumeFloorHeight; basePoints[3] = area.points[volume.points[0]].vector3 + volumeFloorHeight; } Vector3 centrePoint = Vector3.zero; for (int l = 0; l < 4; l++) centrePoint += area.points[volume.points[l]].vector3; centrePoint = (centrePoint / 4) + volumeFloorHeight + ridgeVector; Vector3 r0 = Vector3.Lerp(basePoints[0], basePoints[1], 0.5f) + ridgeVector; Vector3 r1 = Vector3.Lerp(basePoints[2], basePoints[3], 0.5f) + ridgeVector; Vector3 ridgeDirection = (r1 - r0); float roofLength = Vector3.Distance(r0, r1); float ridgeLengthA = Vector3.Distance(basePoints[0], basePoints[1]); if (ridgeLengthA > roofLength) ridgeLengthA = roofLength; float ridgeLengthB = Vector3.Distance(basePoints[2], basePoints[3]); if (ridgeLengthB > roofLength) ridgeLengthB = roofLength; r0 += ridgeDirection.normalized * ridgeLengthA / 2; r1 += -ridgeDirection.normalized * ridgeLengthB / 2; int subMesh = design.GetTexture(BuildrRoofDesign.textureNames.tiles); bool flipped = design.IsFlipped(BuildrRoofDesign.textureNames.tiles); AddPlane(design, basePoints[0], r0, basePoints[3], r1, subMesh, flipped);//top AddPlane(design, basePoints[2], r1, basePoints[1], r0, subMesh, flipped);//top Vector3[] vertsA = new Vector3[3] { basePoints[0], basePoints[1], r0 }; Vector3[] vertsB = new Vector3[3] { basePoints[2], basePoints[3], r1 }; float uvWdithA = Vector3.Distance(basePoints[0], basePoints[1]); float uvWdithB = Vector3.Distance(basePoints[2], basePoints[3]); float uvHeight = design.height; BuildrTexture texture = textures[subMesh]; if (texture.tiled) { uvWdithA *= (1.0f / texture.textureUnitSize.x); uvWdithB *= (1.0f / texture.textureUnitSize.x); uvHeight *= (1.0f / texture.textureUnitSize.y); if (texture.patterned) { Vector2 uvunits = texture.tileUnitUV; uvWdithA = Mathf.Ceil(uvWdithA / uvunits.x) * uvunits.x; uvWdithB = Mathf.Ceil(uvWdithB / uvunits.x) * uvunits.x; uvHeight = Mathf.Ceil(uvHeight / uvunits.y) * uvunits.y; } } else { uvWdithA = texture.tiledX; uvWdithB = texture.tiledX; uvHeight = texture.tiledY; } Vector2[] uvsA = new Vector2[3] { new Vector2(-uvWdithA / 2, 0), new Vector2(uvWdithA / 2, 0), new Vector2(0, uvHeight) }; Vector2[] uvsB = new Vector2[3] { new Vector2(-uvWdithB / 2, 0), new Vector2(uvWdithB / 2, 0), new Vector2(0, uvHeight) }; int[] tri = new int[3] { 1, 0, 2 }; AddData(vertsA, uvsA, tri, subMesh); AddData(vertsB, uvsB, tri, subMesh);*/ }
private static void Gabled(BuildrVolume volume, BuildrRoofDesign design) { BuildrPlan area = data.plan; int numberOfFloors = volume.numberOfFloors; float floorHeight = data.floorHeight; Vector3 volumeFloorHeight = Vector3.up * (numberOfFloors * floorHeight); Vector3 ridgeVector = Vector3.up * design.height; Vector3[] basePoints = new Vector3[4]; if (design.direction == 0) { basePoints[0] = area.points[volume.points[0]].vector3 + volumeFloorHeight; basePoints[1] = area.points[volume.points[1]].vector3 + volumeFloorHeight; basePoints[2] = area.points[volume.points[2]].vector3 + volumeFloorHeight; basePoints[3] = area.points[volume.points[3]].vector3 + volumeFloorHeight; } else { basePoints[0] = area.points[volume.points[1]].vector3 + volumeFloorHeight; basePoints[1] = area.points[volume.points[2]].vector3 + volumeFloorHeight; basePoints[2] = area.points[volume.points[3]].vector3 + volumeFloorHeight; basePoints[3] = area.points[volume.points[0]].vector3 + volumeFloorHeight; } Vector3 centrePoint = Vector3.zero; for (int l = 0; l < 4; l++) centrePoint += area.points[volume.points[l]].vector3; centrePoint = (centrePoint / 4) + volumeFloorHeight + ridgeVector; Vector3 r0 = Vector3.Lerp(basePoints[0], basePoints[1], 0.5f) + ridgeVector; Vector3 r1 = Vector3.Lerp(basePoints[2], basePoints[3], 0.5f) + ridgeVector; int subMesh = design.GetTexture(BuildrRoofDesign.textureNames.tiles); bool flipped = design.IsFlipped(BuildrRoofDesign.textureNames.tiles); AddPlane(design, basePoints[0], r0, basePoints[3], r1, subMesh, flipped);//top AddPlane(design, basePoints[2], r1, basePoints[1], r0, subMesh, flipped);//top Vector3[] vertsA = new Vector3[3] { basePoints[0], basePoints[1], r0 }; Vector3[] vertsB = new Vector3[3] { basePoints[2], basePoints[3], r1 }; float uvWdithA = Vector3.Distance(basePoints[0], basePoints[1]); float uvWdithB = Vector3.Distance(basePoints[2], basePoints[3]); float uvHeight = design.height; subMesh = design.GetTexture(BuildrRoofDesign.textureNames.wall); BuildrTexture texture = textures[subMesh]; if (texture.tiled) { uvWdithA *= (1.0f / texture.textureUnitSize.x); uvWdithB *= (1.0f / texture.textureUnitSize.x); uvHeight *= (1.0f / texture.textureUnitSize.y); if (texture.patterned) { Vector2 uvunits = texture.tileUnitUV; uvWdithA = Mathf.Ceil(uvWdithA / uvunits.x) * uvunits.x; uvWdithB = Mathf.Ceil(uvWdithB / uvunits.x) * uvunits.x; uvHeight = Mathf.Ceil(uvHeight / uvunits.y) * uvunits.y; } } else { uvWdithA = texture.tiledX; uvWdithB = texture.tiledX; uvHeight = texture.tiledY; } Vector2[] uvsA = new Vector2[3] { new Vector2(-uvWdithA / 2, 0), new Vector2(uvWdithA / 2, 0), new Vector2(0, uvHeight) }; Vector2[] uvsB = new Vector2[3] { new Vector2(-uvWdithB / 2, 0), new Vector2(uvWdithB / 2, 0), new Vector2(0, uvHeight) }; int[] tri = new int[3] { 1, 0, 2 }; AddData(vertsA, uvsA, tri, subMesh); AddData(vertsB, uvsB, tri, subMesh); }
private static void LeanTo(BuildrVolume volume, BuildrRoofDesign design) { BuildrPlan area = data.plan; int numberOfFloors = volume.numberOfFloors; float floorHeight = data.floorHeight; Vector3 volumeFloorHeight = Vector3.up * (numberOfFloors * floorHeight); Vector3 ridgeVector = Vector3.up * design.height; int[] pointIndexes = new int[4]; switch (design.direction) { case 0: pointIndexes = new int[4] { 0, 1, 2, 3 }; break; case 1: pointIndexes = new int[4] { 1, 2, 3, 0 }; break; case 2: pointIndexes = new int[4] { 2, 3, 0, 1 }; break; case 3: pointIndexes = new int[4] { 3, 0, 1, 2 }; break; } Vector3[] points = new Vector3[6]; points[0] = area.points[volume.points[pointIndexes[0]]].vector3 + volumeFloorHeight; points[1] = area.points[volume.points[pointIndexes[1]]].vector3 + volumeFloorHeight; points[2] = area.points[volume.points[pointIndexes[2]]].vector3 + volumeFloorHeight; points[3] = area.points[volume.points[pointIndexes[3]]].vector3 + volumeFloorHeight; points[4] = area.points[volume.points[pointIndexes[2]]].vector3 + volumeFloorHeight + ridgeVector; points[5] = area.points[volume.points[pointIndexes[3]]].vector3 + volumeFloorHeight + ridgeVector; //top int subMeshTop = design.GetTexture(BuildrRoofDesign.textureNames.tiles); bool flippedTop = design.IsFlipped(BuildrRoofDesign.textureNames.tiles); AddPlane(design, points[0], points[1], points[5], points[4], subMeshTop, flippedTop); //window int subMeshWindow = design.GetTexture(BuildrRoofDesign.textureNames.window); bool flippedWindow = design.IsFlipped(BuildrRoofDesign.textureNames.window); AddPlane(design, points[2], points[3], points[4], points[5], subMeshWindow, flippedWindow); //sides Vector3[] vertsA = new Vector3[3] { points[1], points[2], points[4] }; Vector3[] vertsB = new Vector3[3] { points[0], points[3], points[5] }; float uvWdith = Vector3.Distance(points[0], points[3]); float uvHeight = design.height; int subMesh = design.GetTexture(BuildrRoofDesign.textureNames.wall); BuildrTexture texture = textures[subMesh]; if (texture.tiled) { uvWdith *= (1.0f / texture.textureUnitSize.x); uvHeight *= (1.0f / texture.textureUnitSize.y); if (texture.patterned) { Vector2 uvunits = texture.tileUnitUV; uvWdith = Mathf.Ceil(uvWdith / uvunits.x) * uvunits.x; uvHeight = Mathf.Ceil(uvHeight / uvunits.y) * uvunits.y; } } else { uvWdith = texture.tiledX; uvHeight = texture.tiledY; } Vector2[] uvs = new Vector2[3] { new Vector2(0, 0), new Vector2(uvWdith, 0), new Vector2(uvWdith, uvHeight) }; if (!design.IsFlipped(BuildrRoofDesign.textureNames.wall)) uvs = new Vector2[3] { new Vector2(uvWdith, 0), new Vector2(0, 0), new Vector2(uvHeight, uvWdith / 2) }; int[] triA = new int[3] { 1, 0, 2 }; int[] triB = new int[3] { 0, 1, 2 }; AddData(vertsA, uvs, triA, subMesh); AddData(vertsB, uvs, triB, subMesh); }
public static void Build(DynamicMeshGenericMultiMaterialMesh _mesh, BuildrData _data, bool ignoreParapets) { data = _data; mesh = _mesh; textures = data.textures.ToArray(); BuildrPlan plan = data.plan; int numberOfVolumes = data.plan.numberOfVolumes; for (int s = 0; s < numberOfVolumes; s++) { BuildrVolume volume = plan.volumes[s]; BuildrRoofDesign design = data.roofs[volume.roofDesignID]; BuildrRoofDesign.styles style = design.style; if (volume.points.Count != 4) if (design.style == BuildrRoofDesign.styles.leanto || design.style == BuildrRoofDesign.styles.sawtooth || design.style == BuildrRoofDesign.styles.barrel) style = BuildrRoofDesign.styles.flat;//ignore style and just do a flat roof if (volume.points.Count != 4 && design.style == BuildrRoofDesign.styles.gabled) style = BuildrRoofDesign.styles.hipped;//ignore style and just do a hipped roof switch (style) { case BuildrRoofDesign.styles.flat: FlatRoof(volume, design); break; case BuildrRoofDesign.styles.mansard: Mansard(volume, design); if (design.hasDormers) Dormers(volume, design); break; case BuildrRoofDesign.styles.gabled: Gabled(volume, design); break; case BuildrRoofDesign.styles.hipped: Hipped(volume, design); break; case BuildrRoofDesign.styles.leanto: LeanTo(volume, design); break; case BuildrRoofDesign.styles.sawtooth: Sawtooth(volume, design); break; case BuildrRoofDesign.styles.barrel: Barrel(volume, design); break; case BuildrRoofDesign.styles.steepled: Steeple(volume, design); break; } if (design.parapet && !ignoreParapets) Parapet(volume, design); } data = null; mesh = null; textures = null; }
private static void Dormers(BuildrVolume volume, BuildrRoofDesign design) { BuildrPlan area = data.plan; int numberOfVolumePoints = volume.points.Count; int numberOfFloors = volume.numberOfFloors; float floorHeight = data.floorHeight; Vector3 volumeFloorHeight = Vector3.up * (numberOfFloors * floorHeight); for (int l = 0; l < numberOfVolumePoints; l++) { int indexA, indexB, indexA0, indexB0; Vector3 p0, p1, p00, p10; indexA = l; indexB = (l < numberOfVolumePoints - 1) ? l + 1 : 0; indexA0 = (l > 0) ? l - 1 : numberOfVolumePoints - 1; indexB0 = (l < numberOfVolumePoints - 2) ? l + 2 : l + 2 - numberOfVolumePoints; p0 = area.points[volume.points[indexA]].vector3; p1 = area.points[volume.points[indexB]].vector3; p00 = area.points[volume.points[indexA0]].vector3; p10 = area.points[volume.points[indexB0]].vector3; Vector3 facadeDirection = (p1 - p0).normalized; Vector3 facadeDirectionLeft = (p0 - p00).normalized; Vector3 facadeDirectionRight = (p10 - p1).normalized; Vector3 facadeNormal = Vector3.Cross(p1 - p0, Vector3.up).normalized; Vector3 facadeNormalLeft = Vector3.Cross(facadeDirectionLeft, Vector3.up); Vector3 facadeNormalRight = Vector3.Cross(facadeDirectionRight, Vector3.up); Vector3 leftDir = (facadeNormal + facadeNormalLeft).normalized; Vector3 rightDir = (facadeNormal + facadeNormalRight).normalized; float windowBottom = (design.height - design.dormerHeight) * design.dormerHeightRatio; float baseDepth = design.floorDepth; float cornerLeftRad = Vector3.Angle(facadeDirection, -facadeDirectionLeft) * Mathf.Deg2Rad / 2; float cornerRightRad = Vector3.Angle(-facadeDirection, facadeDirectionRight) * Mathf.Deg2Rad / 2; float cornerDepthLeft = baseDepth / Mathf.Sin(cornerLeftRad); float cornerDepthRight = baseDepth / Mathf.Sin(cornerRightRad); float topDepth = design.depth; float cornerTopDepthLeft = topDepth / Mathf.Sin(cornerLeftRad); float cornerTopDepthRight = topDepth / Mathf.Sin(cornerRightRad); float dormerDepth = design.depth * (design.dormerHeight / design.height); float windowBottomRat = Mathf.Lerp(0, 1 - design.dormerHeight / design.height, design.dormerHeightRatio); p0 += volumeFloorHeight + leftDir * cornerDepthLeft; p1 += volumeFloorHeight + rightDir * cornerDepthRight; float leftStartTopRad = Vector3.Angle(facadeDirectionLeft, facadeDirection) * Mathf.Deg2Rad * 0.5f; float leftStartMargin = cornerTopDepthLeft * Mathf.Sin(leftStartTopRad); float rightStartTopRad = Vector3.Angle(facadeDirection, facadeDirectionRight) * Mathf.Deg2Rad * 0.5f; float rightStartMargin = cornerTopDepthRight * Mathf.Sin(rightStartTopRad); Vector3 dormerStartPosition = leftDir * (windowBottomRat * cornerTopDepthLeft) + facadeDirection * (leftStartMargin); Vector3 dormerEndPosition = rightDir * (windowBottomRat * cornerTopDepthRight) - facadeDirection * (rightStartMargin + design.dormerWidth); float dormerPositionWidth = Vector3.Distance((p0 + dormerStartPosition), (p1 + dormerEndPosition)); int numberOfWindows = Mathf.FloorToInt((dormerPositionWidth) / (design.dormerWidth + design.minimumDormerSpacing)); float actualWindowSpacing = (dormerPositionWidth - (numberOfWindows * design.dormerWidth)) / (numberOfWindows + 1); numberOfWindows++;//add the final window Vector3 dormerWidthVector = facadeDirection * design.dormerWidth; Vector3 dormerHeightVectorA = Vector3.up * (design.dormerHeight - design.dormerRoofHeight); Vector3 dormerHeightVectorB = Vector3.up * design.dormerHeight; Vector3 dormerDepthVector = facadeNormal * dormerDepth; Vector3 dormerSpace = facadeDirection * (actualWindowSpacing + design.dormerWidth); Vector3 dormerSpacer = facadeDirection * (actualWindowSpacing); Vector3 dormerYPosition = Vector3.up * windowBottom; Vector3 w0, w1, w2, w3, w4, w5, w6, w7, w8, w9; for (int i = 0; i < numberOfWindows; i++) { w0 = p0 + dormerSpace * (i) + dormerStartPosition + dormerYPosition + dormerSpacer * 0.5f; w1 = w0 + dormerWidthVector; w2 = w0 + dormerHeightVectorA; w3 = w1 + dormerHeightVectorA; w4 = w0 + dormerWidthVector / 2 + dormerHeightVectorB; w5 = w0 + dormerDepthVector; w6 = w1 + dormerDepthVector; w7 = w2 + dormerDepthVector; w8 = w3 + dormerDepthVector; w9 = w4 + dormerDepthVector; int subMeshwindow = design.GetTexture(BuildrRoofDesign.textureNames.window); int subMeshwall = design.GetTexture(BuildrRoofDesign.textureNames.wall); int subMeshtiles = design.GetTexture(BuildrRoofDesign.textureNames.tiles); bool flippedwall = design.IsFlipped(BuildrRoofDesign.textureNames.wall); bool flippedtiles = design.IsFlipped(BuildrRoofDesign.textureNames.tiles); AddPlane(design, w1, w6, w3, w8, subMeshwall, flippedwall);//side AddPlane(design, w5, w0, w7, w2, subMeshwall, flippedwall);//side AddPlane(design, w3, w8, w4, w9, subMeshtiles, flippedtiles);//roof AddPlane(design, w7, w2, w9, w4, subMeshtiles, flippedtiles);//roof Vector3[] verts = new Vector3[5] { w0, w1, w2, w3, w4 }; float roofBottom = (design.dormerHeight - design.dormerRoofHeight) / design.dormerHeight; Vector2[] uvs = new Vector2[5]{ new Vector2(0,0), new Vector2(1,0), new Vector2(0,roofBottom), new Vector2(1,roofBottom), new Vector2(0.5f,1), }; int[] tris = new int[9] { 1, 0, 2, 1, 2, 3, 2, 4, 3 }; mesh.AddData(verts, uvs, tris, subMeshwindow); } } }
private static void Parapet(BuildrVolume volume, BuildrRoofDesign design) { BuildrPlan area = data.plan; int volumeIndex = area.volumes.IndexOf(volume); int numberOfVolumePoints = volume.points.Count; int numberOfFloors = volume.numberOfFloors; float floorHeight = data.floorHeight; Vector3 volumeFloorHeight = Vector3.up * (numberOfFloors * floorHeight); for (int l = 0; l < numberOfVolumePoints; l++) { int indexA, indexB, indexA0, indexB0; Vector3 p0, p1, p00, p10; indexA = l; indexB = (l < numberOfVolumePoints - 1) ? l + 1 : 0; indexA0 = (l > 0) ? l - 1 : numberOfVolumePoints - 1; indexB0 = (l < numberOfVolumePoints - 2) ? l + 2 : l + 2 - numberOfVolumePoints; int adjacentFloorHeight = area.GetFacadeFloorHeight(volumeIndex, volume.points[indexA], volume.points[indexB]); bool leftParapet = area.GetFacadeFloorHeight(volumeIndex, volume.points[indexA0], volume.points[indexA]) < numberOfFloors; bool rightParapet = area.GetFacadeFloorHeight(volumeIndex, volume.points[indexB], volume.points[indexB0]) < numberOfFloors; if (adjacentFloorHeight >= numberOfFloors) continue;//do not draw a roof edge p0 = area.points[volume.points[indexA]].vector3; p1 = area.points[volume.points[indexB]].vector3; p00 = area.points[volume.points[indexA0]].vector3; p10 = area.points[volume.points[indexB0]].vector3; float facadeWidth = Vector3.Distance(p0, p1); Vector3 facadeDirection = (p1 - p0).normalized; Vector3 facadeDirectionLeft = (p0 - p00).normalized; Vector3 facadeDirectionRight = (p10 - p1).normalized; Vector3 facadeNormal = Vector3.Cross(facadeDirection, Vector3.up); Vector3 facadeNormalLeft = Vector3.Cross(facadeDirectionLeft, Vector3.up); Vector3 facadeNormalRight = Vector3.Cross(facadeDirectionRight, Vector3.up); float parapetHeight = design.parapetHeight; float parapetFrontDepth = design.parapetFrontDepth; float parapetBackDepth = design.parapetBackDepth; Vector3 w0, w1, w2, w3, w4, w5, w6, w7; Vector3 pr = facadeDirection * facadeWidth; Vector3 pu = Vector3.up * parapetHeight; Vector3 pbdl, pbdr, pfdl, pfdr; if (leftParapet) { pbdl = -(facadeNormal + facadeNormalLeft).normalized * parapetFrontDepth; pfdl = (facadeNormal + facadeNormalLeft).normalized * parapetBackDepth; } else { pbdl = facadeDirectionLeft * parapetFrontDepth; pfdl = -facadeDirectionLeft * parapetBackDepth; } if (rightParapet) { pbdr = -(facadeNormal + facadeNormalRight).normalized * parapetFrontDepth; pfdr = (facadeNormal + facadeNormalRight).normalized * parapetBackDepth; } else { pbdr = -facadeDirectionRight * parapetFrontDepth; pfdr = facadeDirectionRight * parapetBackDepth; } p0 += volumeFloorHeight; p1 += volumeFloorHeight; w2 = p0 + pbdl;//front left w3 = p0 + pr + pbdr;//front right w0 = p0 + pfdl;//back left w1 = p0 + pr + pfdr;//back right w6 = p0 + pbdl + pu;//front left top w7 = p0 + pr + pbdr + pu;//front right top w4 = p0 + pfdl + pu;//back left top w5 = p0 + pr + pfdr + pu;//back right top int subMesh = design.GetTexture(BuildrRoofDesign.textureNames.parapet); bool flipped = design.IsFlipped(BuildrRoofDesign.textureNames.parapet); AddPlane(design, w1, w0, w5, w4, subMesh, flipped);//front AddPlaneComplex(design, w6, w7, w4, w5, subMesh, flipped, facadeNormal);//top AddPlane(design, w2, w3, w6, w7, subMesh, flipped);//back if (parapetFrontDepth > 0) AddPlaneComplex(design, w3, w2, w1, w0, subMesh, flipped, facadeNormal);//bottom if (!leftParapet) AddPlane(design, w0, w2, w4, w6, subMesh, flipped);//left cap if (!rightParapet) AddPlane(design, w3, w1, w7, w5, subMesh, flipped);//left cap } }
private static void Mansard(BuildrVolume volume, BuildrRoofDesign design) { BuildrPlan area = data.plan; int numberOfVolumePoints = volume.points.Count; int numberOfFloors = volume.numberOfFloors; float floorHeight = data.floorHeight; Vector3 volumeFloorHeight = Vector3.up * (numberOfFloors * floorHeight); //add top base of the flat roof Vector3[] topVerts = new Vector3[numberOfVolumePoints]; Vector2[] topUVs = new Vector2[numberOfVolumePoints]; int topTextureID = design.GetTexture(BuildrRoofDesign.textureNames.floorB); BuildrTexture texture = textures[topTextureID]; for (int l = 0; l < numberOfVolumePoints; l++) { int indexA, indexB, indexA0, indexB0; Vector3 p0, p1, p00, p10; indexA = l; indexB = (l < numberOfVolumePoints - 1) ? l + 1 : 0; indexA0 = (l > 0) ? l - 1 : numberOfVolumePoints - 1; indexB0 = (l < numberOfVolumePoints - 2) ? l + 2 : l + 2 - numberOfVolumePoints; p0 = area.points[volume.points[indexA]].vector3; p1 = area.points[volume.points[indexB]].vector3; p00 = area.points[volume.points[indexA0]].vector3; p10 = area.points[volume.points[indexB0]].vector3; float facadeWidth = Vector3.Distance(p0, p1); Vector3 facadeDirection = (p1 - p0).normalized; Vector3 facadeDirectionLeft = (p0 - p00).normalized; Vector3 facadeDirectionRight = (p10 - p1).normalized; Vector3 facadeNormal = Vector3.Cross(facadeDirection, Vector3.up); Vector3 facadeNormalLeft = Vector3.Cross(facadeDirectionLeft, Vector3.up); Vector3 facadeNormalRight = Vector3.Cross(facadeDirectionRight, Vector3.up); float roofHeight = design.height; float baseDepth = design.floorDepth; float cornerLeftRad = Vector3.Angle(facadeDirection, -facadeDirectionLeft) * Mathf.Deg2Rad / 2; float cornerRightRad = Vector3.Angle(-facadeDirection, facadeDirectionRight) * Mathf.Deg2Rad / 2; float cornerDepthLeft = baseDepth / Mathf.Sin(cornerLeftRad); float cornerDepthRight = baseDepth / Mathf.Sin(cornerRightRad); float topDepth = design.depth; float cornerTopDepthLeft = topDepth / Mathf.Sin(cornerLeftRad); float cornerTopDepthRight = topDepth / Mathf.Sin(cornerRightRad); Vector3 pr = facadeDirection * facadeWidth; Vector3 leftDir = (facadeNormal + facadeNormalLeft).normalized; Vector3 rightDir = (facadeNormal + facadeNormalRight).normalized; p0 += volumeFloorHeight; p1 += volumeFloorHeight; Vector3 w0, w1, w2, w3, w4, w5; w0 = p0; w1 = p0 + pr; w2 = w0 + leftDir * cornerDepthLeft; w3 = w1 + rightDir * cornerDepthRight; w4 = w2 + leftDir * cornerTopDepthLeft + Vector3.up * roofHeight; w5 = w3 + rightDir * cornerTopDepthRight + Vector3.up * roofHeight; Vector3[] verts = new Vector3[6] { w0, w1, w2, w3, w4, w5 }; // List<Vector2> uvs = new List<Vector2>(); Vector2[] uvsFloor = BuildrProjectUVs.Project(new Vector3[4] { w0, w1, w2, w3 }, Vector2.zero, facadeNormal); if(baseDepth == 0) uvsFloor[3].x = facadeWidth; Vector2[] uvsMansard = BuildrProjectUVs.Project(new Vector3[3] { w2, w4, w5 }, uvsFloor[2], facadeNormal); Vector3[] vertsA = new Vector3[4] { verts[0], verts[1], verts[2], verts[3] }; Vector2[] uvsA = new Vector2[4] { uvsFloor[0], uvsFloor[1], uvsFloor[2], uvsFloor[3] }; int[] trisA = new int[6] { 1, 0, 2, 1, 2, 3 }; int subMeshA = design.GetTexture(BuildrRoofDesign.textureNames.floor); mesh.AddData(vertsA, uvsA, trisA, subMeshA); Vector3[] vertsB = new Vector3[4] { verts[2], verts[3], verts[4], verts[5] }; Vector2[] uvsB = new Vector2[4] { uvsFloor[2], uvsFloor[3], uvsMansard[1], uvsMansard[2] }; int[] trisB = new int[6] { 0, 2, 1, 1, 2, 3 }; int subMeshB = design.GetTexture(BuildrRoofDesign.textureNames.tiles); mesh.AddData(vertsB, uvsB, trisB, subMeshB); //modify point for the top geometry Vector2z point = area.points[volume.points[l]]; topVerts[l] = point.vector3 + volumeFloorHeight + Vector3.up * roofHeight + leftDir * (cornerDepthLeft + cornerTopDepthLeft); topUVs[l] = new Vector2(topVerts[l].x / texture.textureUnitSize.x, topVerts[l].z / texture.textureUnitSize.y); } Vector2z[] topVertV2z = new Vector2z[topVerts.Length]; for (int i = 0; i < topVerts.Length; i++) topVertV2z[i] = new Vector2z(topVerts[i]); int[] topTris = EarClipper.Triangulate(topVertV2z); AddData(topVerts, topUVs, topTris, topTextureID);//top }
public void RemoveRoofDesign(BuildrRoofDesign roof) { roofs.Remove(roof); int bRoofIndex = roofs.IndexOf(roof); int numberOfVolumes = plan.numberOfVolumes; for (int s = 0; s < numberOfVolumes; s++) { BuildrVolume volume = plan.volumes[s]; if (volume.roofDesignID >= bRoofIndex && volume.roofDesignID > 0) volume.roofDesignID--; } }
private static void Barrel(BuildrVolume volume, BuildrRoofDesign design) { BuildrPlan area = data.plan; int numberOfFloors = volume.numberOfFloors; float floorHeight = data.floorHeight; Vector3 volumeFloorHeight = Vector3.up * (numberOfFloors * floorHeight); Vector3[] points = new Vector3[4]; //Vector3 ridgeVector; if (design.direction == 0) { points[0] = area.points[volume.points[0]].vector3 + volumeFloorHeight; points[1] = area.points[volume.points[3]].vector3 + volumeFloorHeight; points[2] = area.points[volume.points[1]].vector3 + volumeFloorHeight; points[3] = area.points[volume.points[2]].vector3 + volumeFloorHeight; } else { points[0] = area.points[volume.points[1]].vector3 + volumeFloorHeight; points[1] = area.points[volume.points[0]].vector3 + volumeFloorHeight; points[2] = area.points[volume.points[2]].vector3 + volumeFloorHeight; points[3] = area.points[volume.points[3]].vector3 + volumeFloorHeight; } int barrelSegments = design.barrelSegments + 1; Vector3[] bPoints = new Vector3[barrelSegments * 2]; for (int i = 0; i < barrelSegments; i++) { float lerp = (float)i / (float)(barrelSegments - 1); Vector3 height = Mathf.Sin(lerp * Mathf.PI) * design.height * Vector3.up; float cosLerp = 1 - (Mathf.Cos((lerp) * Mathf.PI) + 1) / 2; bPoints[i] = Vector3.Lerp(points[0], points[1], cosLerp) + height; bPoints[i + barrelSegments] = Vector3.Lerp(points[2], points[3], cosLerp) + height; } int topIterations = barrelSegments - 1; int subMesh = design.GetTexture(BuildrRoofDesign.textureNames.tiles); bool flipped = design.IsFlipped(BuildrRoofDesign.textureNames.tiles); for (int t = 0; t < topIterations; t++) AddPlane(design, bPoints[t + 1], bPoints[t], bPoints[t + barrelSegments + 1], bPoints[t + barrelSegments], subMesh, flipped);//top Vector3 centerA = Vector3.Lerp(points[0], points[1], 0.5f); Vector3 centerB = Vector3.Lerp(points[2], points[3], 0.5f); for (int e = 0; e < topIterations; e++) { float lerpA = ((float)(e) / (float)(topIterations)) * Mathf.PI; float lerpB = ((float)(e + 1) / (float)(topIterations)) * Mathf.PI; Vector2[] uvs = new Vector2[3]{ new Vector2(0.5f,0), new Vector2(1-(Mathf.Cos(lerpA)+1)/2,Mathf.Sin(lerpA)), new Vector2(1-(Mathf.Cos(lerpB)+1)/2,Mathf.Sin(lerpB)) }; Vector3[] verts = new Vector3[3] { centerA, bPoints[e], bPoints[e + 1] }; int[] tri = new int[3] { 0, 2, 1 }; AddData(verts, uvs, tri, design.GetTexture(BuildrRoofDesign.textureNames.window)); verts = new Vector3[3] { centerB, bPoints[e + barrelSegments], bPoints[e + 1 + barrelSegments] }; tri = new int[3] { 0, 1, 2 }; AddData(verts, uvs, tri, design.GetTexture(BuildrRoofDesign.textureNames.window)); } }
private static void Sawtooth(BuildrVolume volume, BuildrRoofDesign design) { BuildrPlan area = data.plan; int numberOfFloors = volume.numberOfFloors; float floorHeight = data.floorHeight; Vector3 volumeFloorHeight = Vector3.up * (numberOfFloors * floorHeight); Vector3 ridgeVector = Vector3.up * design.height; int[] pointIndexes = new int[4]; switch (design.direction) { case 0: pointIndexes = new int[4] { 0, 1, 2, 3 }; break; case 1: pointIndexes = new int[4] { 1, 2, 3, 0 }; break; case 2: pointIndexes = new int[4] { 2, 3, 0, 1 }; break; case 3: pointIndexes = new int[4] { 3, 0, 1, 2 }; break; } Vector3[] basepoints = new Vector3[4]; Vector3[] points = new Vector3[6]; for (int i = 0; i < design.sawtoothTeeth; i++) { Vector3 toothBaseMovementA = (area.points[volume.points[pointIndexes[3]]].vector3 - area.points[volume.points[pointIndexes[0]]].vector3).normalized; float roofDepthA = Vector3.Distance(area.points[volume.points[pointIndexes[3]]].vector3, area.points[volume.points[pointIndexes[0]]].vector3); float toothDepthA = roofDepthA / design.sawtoothTeeth; Vector3 toothVectorA = toothBaseMovementA * toothDepthA; Vector3 toothBaseMovementB = (area.points[volume.points[pointIndexes[2]]].vector3 - area.points[volume.points[pointIndexes[1]]].vector3).normalized; float roofDepthB = Vector3.Distance(area.points[volume.points[pointIndexes[2]]].vector3, area.points[volume.points[pointIndexes[1]]].vector3); float toothDepthB = roofDepthB / design.sawtoothTeeth; Vector3 toothVectorB = toothBaseMovementB * toothDepthB; basepoints[0] = area.points[volume.points[pointIndexes[0]]].vector3 + toothVectorA * i; basepoints[1] = area.points[volume.points[pointIndexes[1]]].vector3 + toothVectorB * i; basepoints[2] = basepoints[1] + toothVectorB; basepoints[3] = basepoints[0] + toothVectorA; points[0] = basepoints[0] + volumeFloorHeight; points[1] = basepoints[1] + volumeFloorHeight; points[2] = basepoints[2] + volumeFloorHeight; points[3] = basepoints[3] + volumeFloorHeight; points[4] = basepoints[2] + volumeFloorHeight + ridgeVector; points[5] = basepoints[3] + volumeFloorHeight + ridgeVector; //top int subMeshTop = design.GetTexture(BuildrRoofDesign.textureNames.tiles); bool flippedTop = design.IsFlipped(BuildrRoofDesign.textureNames.tiles); AddPlane(design, points[0], points[1], points[5], points[4], subMeshTop, flippedTop); //window int subMeshWindow = design.GetTexture(BuildrRoofDesign.textureNames.window); bool flippedWindow = design.IsFlipped(BuildrRoofDesign.textureNames.window); AddPlane(design, points[2], points[3], points[4], points[5], subMeshWindow, flippedWindow); //sides Vector3[] vertsA = new Vector3[3] { points[1], points[2], points[4] }; Vector3[] vertsB = new Vector3[3] { points[0], points[3], points[5] }; float uvWdith = Vector3.Distance(points[0], points[3]); float uvHeight = design.height; int subMesh = design.GetTexture(BuildrRoofDesign.textureNames.wall); BuildrTexture texture = textures[subMesh]; if (texture.tiled) { uvWdith *= (1.0f / texture.textureUnitSize.x); uvHeight *= (1.0f / texture.textureUnitSize.y); if (texture.patterned) { Vector2 uvunits = texture.tileUnitUV; uvWdith = Mathf.Ceil(uvWdith / uvunits.x) * uvunits.x; uvHeight = Mathf.Ceil(uvHeight / uvunits.y) * uvunits.y; } } else { uvWdith = texture.tiledX; uvHeight = texture.tiledY; } Vector2[] uvs = new Vector2[3] { new Vector2(0, 0), new Vector2(uvWdith, 0), new Vector2(uvWdith, uvHeight) }; int[] triA = new int[3] { 1, 0, 2 }; int[] triB = new int[3] { 0, 1, 2 }; AddData(vertsA, uvs, triA, subMesh); AddData(vertsB, uvs, triB, subMesh); } }
public static void InspectorGUI(BuildrEditMode editMode, BuildrData _data) { data = _data; Undo.RecordObject(data, "Roof Modified"); BuildrRoofDesign[] roofs = data.roofs.ToArray(); int numberOfRoofs = roofs.Length; selectedRoof = Mathf.Clamp(selectedRoof, 0, numberOfRoofs - 1); if (GUILayout.Button("Add new roof design")) { data.roofs.Add(new BuildrRoofDesign("new roof " + numberOfRoofs)); roofs = data.roofs.ToArray(); numberOfRoofs++; selectedRoof = numberOfRoofs - 1; } if (numberOfRoofs == 0) { EditorGUILayout.HelpBox("There are no roof designs to show", MessageType.Info); return; } EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("Design: ", GUILayout.Width(75)); string[] roofNames = new string[numberOfRoofs]; for (int f = 0; f < numberOfRoofs; f++) { roofNames[f] = roofs[f].name; } selectedRoof = EditorGUILayout.Popup(selectedRoof, roofNames); BuildrRoofDesign bRoof = roofs[selectedRoof]; EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); if (GUILayout.Button("Delete", GUILayout.Width(75))) { if (EditorUtility.DisplayDialog("Deleting Roof Design Entry", "Are you sure you want to delete this roof?", "Delete", "Cancel")) { data.RemoveRoofDesign(bRoof); selectedRoof = 0; GUI.changed = true; return; } } if (GUILayout.Button("Import", GUILayout.Width(71))) { string xmlPath = EditorUtility.OpenFilePanel("Select the XML file...", "Assets/BuildR/Exported/", "xml"); if (xmlPath == "") { return; } BuildrXMLImporter.ImportRoofs(xmlPath, _data); GUI.changed = true; } if (GUILayout.Button("Export", GUILayout.Width(71))) { string xmlPath = EditorUtility.SaveFilePanel("Export as...", "Assets/BuildR/Exported/", _data.name + "_roofLibrary", "xml"); if (xmlPath == "") { return; } BuildrXMLExporter.ExportRoofs(xmlPath, _data); GUI.changed = true; } EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("Name: ", GUILayout.Width(75)); bRoof.name = EditorGUILayout.TextField(bRoof.name); EditorGUILayout.EndHorizontal(); //ROOF STYLE EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("Style: ", GUILayout.Width(75)); BuildrRoofDesign.styles bRoofstyle = (BuildrRoofDesign.styles)EditorGUILayout.EnumPopup(bRoof.style); if (bRoofstyle != bRoof.style) { bRoof.style = bRoofstyle; } EditorGUILayout.EndHorizontal(); if (bRoof.style != BuildrRoofDesign.styles.flat && bRoof.style != BuildrRoofDesign.styles.mansard && bRoof.style != BuildrRoofDesign.styles.steepled && bRoof.style != BuildrRoofDesign.styles.hipped) { EditorGUILayout.HelpBox("Please note that this design can only be used on sections with 4 points." + "\nComplex sections can only use the Flat, Mansard and Steeple designs.", MessageType.Warning); } if (bRoof.style != BuildrRoofDesign.styles.flat) { bRoof.height = Mathf.Max(EditorGUILayout.FloatField("Height", bRoof.height), 0); } if (bRoof.style == BuildrRoofDesign.styles.mansard) { bRoof.floorDepth = Mathf.Max(EditorGUILayout.FloatField("Base Depth", bRoof.floorDepth), 0); bRoof.depth = Mathf.Max(EditorGUILayout.FloatField("Top Depth", bRoof.depth), 0); } if (bRoof.style == BuildrRoofDesign.styles.barrel) { bRoof.barrelSegments = Mathf.Max(EditorGUILayout.IntField("Barrel Segments", bRoof.barrelSegments), 3); } if (bRoof.style == BuildrRoofDesign.styles.barrel || bRoof.style == BuildrRoofDesign.styles.gabled || bRoof.style == BuildrRoofDesign.styles.hipped) { //two directions of the ridge bRoof.direction = Mathf.Clamp(bRoof.direction, 0, 1); string[] options = new string[2] { "short", "long" }; bRoof.direction = EditorGUILayout.Popup(bRoof.direction, options); } if (bRoof.style == BuildrRoofDesign.styles.leanto || bRoof.style == BuildrRoofDesign.styles.sawtooth) { //four directions of the ridge bRoof.direction = Mathf.Clamp(bRoof.direction, 0, 3); string[] options = new string[4] { "left", "up", "right", "down" }; bRoof.direction = EditorGUILayout.Popup(bRoof.direction, options); } if (bRoof.style == BuildrRoofDesign.styles.sawtooth) { bRoof.sawtoothTeeth = Mathf.Max(EditorGUILayout.IntField("Number of 'teeth'", bRoof.sawtoothTeeth), 2); } //PARAPET bool bRoofparapet = EditorGUILayout.Toggle("Has Parapet", bRoof.parapet); if (bRoofparapet != bRoof.parapet) { bRoof.parapet = bRoofparapet; } if (bRoof.parapet) { float bRoofparapetHeight = Mathf.Max(EditorGUILayout.FloatField("Parapet Width", bRoof.parapetHeight), 0); if (bRoofparapetHeight != bRoof.parapetHeight) { bRoof.parapetHeight = bRoofparapetHeight; } float bRoofparapetFrontDepth = Mathf.Max(EditorGUILayout.FloatField("Parapet Front Depth", bRoof.parapetFrontDepth), 0); if (bRoofparapetFrontDepth != bRoof.parapetFrontDepth) { bRoof.parapetFrontDepth = bRoofparapetFrontDepth; } float bRoofparapetBackDepth = Mathf.Max(EditorGUILayout.FloatField("Parapet Back Depth", bRoof.parapetBackDepth), 0); if (bRoofparapetBackDepth != bRoof.parapetBackDepth) { bRoof.parapetBackDepth = bRoofparapetBackDepth; } if (bRoof.parapetStyle == BuildrRoofDesign.parapetStyles.fancy)//NOT IMPLMENTED...YET... { EditorGUILayout.HelpBox("This allows you to specify a model mesh that will be used to create a parapet." + "\nIt should not repeat as Buildr will attempt to repeat the style to fit the length of the facade.", MessageType.Info); bRoof.parapetDesign = (Mesh)EditorGUILayout.ObjectField("Parapet Mesh", bRoof.parapetDesign, typeof(Mesh), false); bRoof.parapetDesignWidth = Mathf.Max(EditorGUILayout.FloatField("Parapet Design Width", bRoof.parapetDesignWidth), 0); } } //DORMERS if (bRoof.style == BuildrRoofDesign.styles.mansard) { bool bRoofhasDormers = EditorGUILayout.Toggle("Has Dormers", bRoof.hasDormers); if (bRoofhasDormers != bRoof.hasDormers) { bRoof.hasDormers = bRoofhasDormers; } if (bRoof.hasDormers) { float bRoofdormerWidth = Mathf.Max(EditorGUILayout.FloatField("Dormer Width", bRoof.dormerWidth), 0); if (bRoofdormerWidth != bRoof.dormerWidth) { bRoof.dormerWidth = bRoofdormerWidth; } float bRoofdormerHeight = Mathf.Clamp(EditorGUILayout.FloatField("Dormer Height", bRoof.dormerHeight), 0, bRoof.height); if (bRoofdormerHeight != bRoof.dormerHeight) { bRoof.dormerHeight = bRoofdormerHeight; } float bRoofdormerRoofHeight = Mathf.Clamp(EditorGUILayout.FloatField("Dormer Roof Height", bRoof.dormerRoofHeight), 0, bRoof.dormerHeight); if (bRoofdormerRoofHeight != bRoof.dormerRoofHeight) { bRoof.dormerRoofHeight = bRoofdormerRoofHeight; } float bRoofminimumDormerSpacing = Mathf.Max(EditorGUILayout.FloatField("Dormer Minimum Spacing", bRoof.minimumDormerSpacing), 0); if (bRoofminimumDormerSpacing != bRoof.minimumDormerSpacing) { bRoof.minimumDormerSpacing = bRoofminimumDormerSpacing; } float bRoofdormerHeightRatio = EditorGUILayout.Slider("Dormer Height Ratio", bRoof.dormerHeightRatio, 0, 1); if (bRoofdormerHeightRatio != bRoof.dormerHeightRatio) { bRoof.dormerHeightRatio = bRoofdormerHeightRatio; } } } //TEXTURES int numberOfTextures = data.textures.Count; string[] textureNames = new string[numberOfTextures]; for (int t = 0; t < numberOfTextures; t++) { textureNames[t] = data.textures[t].name; } int numberOfTextureSlots = bRoof.numberOfTextures; string[] titles = new string[numberOfTextureSlots]; for (int brt = 0; brt < numberOfTextureSlots; brt++) { titles[brt] = ((BuildrRoofDesign.textureNames)(brt)).ToString(); } editTextureOnRoof = EditorGUILayout.Popup("Texture Surface:", editTextureOnRoof, titles); int selectedRoofTexture = EditorGUILayout.Popup("Selected Texture:", bRoof.textureValues[editTextureOnRoof], textureNames); if (selectedRoofTexture != bRoof.textureValues[editTextureOnRoof]) { bRoof.textureValues[editTextureOnRoof] = selectedRoofTexture; } BuildrTexture bTexture = data.textures[bRoof.textureValues[editTextureOnRoof]]; Texture2D texture = bTexture.texture; EditorGUILayout.BeginHorizontal(); if (texture != null) { GUILayout.Label(texture, GUILayout.Width(100), GUILayout.Height(100)); } else { EditorGUILayout.HelpBox("No texture assigned for '" + textureNames[bRoof.textureValues[editTextureOnRoof]] + "', assign one in the Textures menu above", MessageType.Warning); } bRoof.flipValues[editTextureOnRoof] = EditorGUILayout.Toggle("Flip 90\u00B0", bRoof.flipValues[editTextureOnRoof]); EditorGUILayout.EndHorizontal(); }