public bool CheckPlan() { List <Vector2z> lines = new List <Vector2z>();//this will be a list of lines in sets of two vector points int volumeCount = numberOfVolumes; for (int s = 0; s < volumeCount; s++) { int volumeLinkCount = volumes[s].Count; for (int l = 0; l < volumeLinkCount; l++) { int indexB = (l < volumeLinkCount - 1) ? l + 1 : 0; lines.Add(points[volumes[s].points[l]]); lines.Add(points[volumes[s].points[indexB]]); } int numberOfCores = cores.Count; for (int coreIndex = 0; coreIndex < numberOfCores; coreIndex++) { Rect coreOutline = cores[coreIndex]; Vector2z coreBL = new Vector2z(coreOutline.xMin, coreOutline.yMin); Vector2z coreBR = new Vector2z(coreOutline.xMax, coreOutline.yMin); Vector2z coreTL = new Vector2z(coreOutline.xMin, coreOutline.yMax); Vector2z coreTR = new Vector2z(coreOutline.xMax, coreOutline.yMax); lines.Add(coreBL); lines.Add(coreBR); lines.Add(coreBR); lines.Add(coreTR); lines.Add(coreTR); lines.Add(coreTL); lines.Add(coreTL); lines.Add(coreBL); } } _illegalPoints.Clear(); int numberOfLines = lines.Count; Vector2z a, b, c, d; while (numberOfLines > 2) { //get the first line a = lines[0]; b = lines[1]; for (int i = 2; i < numberOfLines; i += 2) { c = lines[i]; d = lines[i + 1]; if (a == c || a == d || b == c || b == d) //don't test lines that connect { continue; } if (BuildrUtils.FastLineIntersection(a, b, c, d)) { _illegalPoints.Add(a); _illegalPoints.Add(b); _illegalPoints.Add(c); _illegalPoints.Add(d); } } lines.RemoveRange(0, 2); //remove the first linked line numberOfLines = lines.Count; } return(_illegalPoints.Count > 0); }
//TODO: functions to find out minimum footprint of stairwell for checking against cores? public static void Build(DynamicMeshGenericMultiMaterialMesh _mesh, BuildrData _data, int volumeIndex, StairModes stairMode, bool zeroMesh) { data = _data; mesh = _mesh; mesh.name = "Stairs Mesh Volume " + volumeIndex; textures = data.textures.ToArray(); // BuildrFacadeDesign facadeDesign = data.facades[0]; BuildrPlan plan = data.plan; BuildrVolume volume = plan.volumes[volumeIndex]; float floorHeight = data.floorHeight; // Vector3 floorHeightVector = Vector3.up * floorHeight; if (!volume.generateStairs) { return; } //Calculate the internal floor plan points int numberOfVolumePoints = volume.points.Count; Vector2z[] volumePoints = new Vector2z[numberOfVolumePoints]; for (int i = 0; i < numberOfVolumePoints; i++) { volumePoints[i] = plan.points[volume.points[i]]; } List <Rect> volumeCores = new List <Rect>(); // List<int> linkedPoints = new List<int>(); foreach (Rect core in plan.cores) { Vector2z coreCenter = new Vector2z(core.center); if (BuildrUtils.PointInsidePoly(coreCenter, volumePoints)) { volumeCores.Add(core); } } int numberOfVolumeCores = volumeCores.Count; int numberOfFloors = volume.numberOfFloors + volume.numberOfBasementFloors; float basementBaseHeight = (volume.numberOfBasementFloors) * floorHeight;//plus one for the initial floor float staircaseWidth = volume.staircaseWidth; float stairwellWidth = staircaseWidth * 2.5f; float stairwellDepth = staircaseWidth * 2 + Mathf.Sqrt(floorHeight + floorHeight); float staircaseThickness = Mathf.Sqrt(volume.stepHeight * volume.stepHeight + volume.stepHeight * volume.stepHeight); Vector3 flightVector = floorHeight * Vector3.up; Vector3 staircaseWidthVector = staircaseWidth * Vector3.right; Vector3 staircaseDepthVector = stairwellDepth * 0.5f * Vector3.forward; Vector3 stairHeightVector = staircaseThickness * Vector3.up; Vector3 landingDepthVector = staircaseWidth * Vector3.forward; //Texture submeshes int floorSubmesh = volume.stairwellFloorTexture; int stepSubmesh = volume.stairwellStepTexture; int wallSubmesh = volume.stairwellWallTexture; int ceilingSubmesh = volume.stairwellCeilingTexture; volume.stairBaseVector.Clear(); for (int c = 0; c < numberOfVolumeCores; c++) { Rect coreBounds = volumeCores[c]; Vector3 stairBaseVector = new Vector3(-stairwellWidth / 2, 0, -stairwellDepth / 2); Vector3 stairPosition = new Vector3(coreBounds.xMin, -basementBaseHeight, coreBounds.yMin) - stairBaseVector; for (int f = 0; f < numberOfFloors; f++) { Vector3 flightBaseVector = stairBaseVector + (flightVector * f); if (!zeroMesh) { flightBaseVector += stairPosition; } Vector3 landingStart0 = flightBaseVector; Vector3 landingStart1 = landingStart0 + staircaseWidthVector * 2.5f; Vector3 landingStart2 = landingStart0 + landingDepthVector; Vector3 landingStart3 = landingStart1 + landingDepthVector; Vector3 landingStart4 = landingStart0 - stairHeightVector; Vector3 landingStart5 = landingStart1 - stairHeightVector; Vector3 landingStart6 = landingStart2 - stairHeightVector; Vector3 landingStart7 = landingStart3 - stairHeightVector; if (f > 0) { AddPlane(landingStart1, landingStart0, landingStart3, landingStart2, floorSubmesh, false, Vector2.zero, new Vector2(staircaseWidth * 2.5f, staircaseWidth)); //top AddPlane(landingStart4, landingStart5, landingStart6, landingStart7, ceilingSubmesh, false, Vector2.zero, new Vector2(staircaseWidth * 2.5f, staircaseWidth)); //bottom AddPlane(landingStart0, landingStart1, landingStart4, landingStart5, wallSubmesh, false, Vector2.zero, new Vector2(staircaseWidth * 2.5f, staircaseThickness)); //frontside AddPlane(landingStart3, landingStart2, landingStart7, landingStart6, wallSubmesh, false, Vector2.zero, new Vector2(staircaseWidth * 2.5f, staircaseThickness)); //backside AddPlane(landingStart0, landingStart4, landingStart2, landingStart6, wallSubmesh, false, Vector2.zero, new Vector2(staircaseThickness, staircaseWidth)); //sideleft AddPlane(landingStart5, landingStart1, landingStart7, landingStart3, wallSubmesh, false, Vector2.zero, new Vector2(staircaseThickness, staircaseWidth)); //sideright } if (f < numberOfFloors - 1) { Vector3 bottom0 = landingStart2; Vector3 bottom1 = landingStart2 + staircaseWidthVector; Vector3 bottom2 = bottom0 - stairHeightVector; Vector3 bottom3 = bottom1 - stairHeightVector; Vector3 top0 = bottom0 + (flightVector * 0.5f) + staircaseDepthVector; Vector3 top1 = bottom1 + (flightVector * 0.5f) + staircaseDepthVector; Vector3 top2 = top0 - stairHeightVector; Vector3 top3 = top1 - stairHeightVector; Vector3 bottomB0 = top1 + Vector3.right * staircaseWidth * 0.5f; Vector3 bottomB1 = bottomB0 + staircaseWidthVector; Vector3 bottomB2 = bottomB0 - stairHeightVector; Vector3 bottomB3 = bottomB1 - stairHeightVector; Vector3 topB0 = bottomB0 + (flightVector * 0.5f) - staircaseDepthVector; Vector3 topB1 = bottomB1 + (flightVector * 0.5f) - staircaseDepthVector; Vector3 topB2 = topB0 - stairHeightVector; Vector3 topB3 = topB1 - stairHeightVector; float stairHypontenuse = Vector3.Distance(bottom0, top0); int numberOfSteps = Mathf.CeilToInt((floorHeight / 2.0f) / volume.stepHeight); switch (stairMode) { case StairModes.Flat: //flight A AddPlane(bottom1, bottom0, top1, top0, stepSubmesh, false, Vector2.zero, new Vector2(1, numberOfSteps)); //step face AddPlane(bottom3, bottom1, top3, top1, ceilingSubmesh, false, Vector2.zero, new Vector2(staircaseWidth, stairHypontenuse)); //underside AddPlane(bottom0, bottom2, top0, top2, wallSubmesh, false, new Vector2(bottom2.z, bottom2.y), new Vector2(top0.z, top0.y)); //left side AddPlane(bottom2, bottom3, top2, top3, wallSubmesh, false, new Vector2(bottom3.z, bottom3.y), new Vector2(top2.z, top2.y)); //right side //flight B AddPlane(bottomB0, bottomB1, topB0, topB1, stepSubmesh, false, Vector2.zero, new Vector2(1, numberOfSteps)); //step face AddPlane(bottomB1, bottomB3, topB1, topB3, ceilingSubmesh, false, Vector2.zero, new Vector2(staircaseWidth, stairHypontenuse)); //underside AddPlane(bottomB2, bottomB0, topB2, topB0, wallSubmesh, false, Vector2.zero, Vector2.one); //left side AddPlane(bottomB3, bottomB2, topB3, topB2, wallSubmesh, false, Vector2.zero, Vector2.one); //right side break; case StairModes.Stepped: float stepHypontenuse = stairHypontenuse / numberOfSteps; float stairAngle = Mathf.Atan2(floorHeight, stairwellDepth); float stepDepth = Mathf.Cos(stairAngle) * stepHypontenuse; float skipStep = (stepDepth / (numberOfSteps - 1)); stepDepth += skipStep; float stepRiser = Mathf.Sin(stairAngle) * stepHypontenuse; //flight one float lerpIncrement = 1.0f / numberOfSteps; float lerpIncrementB = 1.0f / (numberOfSteps - 1); for (int s = 0; s < numberOfSteps - 1; s++) { float lerpValue = lerpIncrement * s; Vector3 skipStepVector = Vector3.forward * (skipStep * s); Vector3 s0 = Vector3.Lerp(bottom1, top1, lerpValue) + skipStepVector; Vector3 s1 = Vector3.Lerp(bottom0, top0, lerpValue) + skipStepVector; Vector3 s2 = s0 + Vector3.up * stepRiser; Vector3 s3 = s1 + Vector3.up * stepRiser; Vector3 s4 = s2 + Vector3.forward * stepDepth; Vector3 s5 = s3 + Vector3.forward * stepDepth; AddPlane(s0, s1, s2, s3, wallSubmesh, false, Vector2.zero, new Vector2(1, staircaseWidth)); AddPlane(s2, s3, s4, s5, stepSubmesh, false, Vector2.zero, new Vector2(1, staircaseWidth)); //sides float lerpValueB = lerpIncrementB * s; Vector3 s6 = Vector3.Lerp(bottom3, top3, lerpValueB); Vector3 s7 = Vector3.Lerp(bottom3, top3, lerpValueB + lerpIncrementB); AddPlane(s2, s4, s6, s7, wallSubmesh, false, Vector2.zero, new Vector2(stepDepth, staircaseThickness)); Vector3 s8 = Vector3.Lerp(bottom2, top2, lerpValueB); Vector3 s9 = Vector3.Lerp(bottom2, top2, lerpValueB + lerpIncrementB); AddPlane(s5, s3, s9, s8, wallSubmesh, false, Vector2.zero, new Vector2(stepDepth, staircaseThickness)); } AddPlane(bottom2, bottom3, top2, top3, ceilingSubmesh, false, Vector2.zero, Vector2.one); //flight two for (int s = 0; s < numberOfSteps - 1; s++) { float lerpValue = lerpIncrement * s; Vector3 skipStepVector = -Vector3.forward * (skipStep * s); Vector3 s0 = Vector3.Lerp(bottomB0, topB0, lerpValue) + skipStepVector; Vector3 s1 = Vector3.Lerp(bottomB1, topB1, lerpValue) + skipStepVector; Vector3 s2 = s0 + Vector3.up * stepRiser; Vector3 s3 = s1 + Vector3.up * stepRiser; Vector3 s4 = s2 - Vector3.forward * stepDepth; Vector3 s5 = s3 - Vector3.forward * stepDepth; AddPlane(s0, s1, s2, s3, wallSubmesh, false, Vector2.zero, new Vector2(1, staircaseWidth)); AddPlane(s2, s3, s4, s5, stepSubmesh, false, Vector2.zero, new Vector2(1, staircaseWidth)); float lerpValueB = lerpIncrementB * s; //sides Vector3 s6 = Vector3.Lerp(bottomB2, topB2, lerpValueB); Vector3 s7 = Vector3.Lerp(bottomB2, topB2, lerpValueB + lerpIncrementB); AddPlane(s2, s4, s6, s7, wallSubmesh, false, Vector2.zero, new Vector2(stepDepth, staircaseThickness)); Vector3 s8 = Vector3.Lerp(bottomB3, topB3, lerpValueB); Vector3 s9 = Vector3.Lerp(bottomB3, topB3, lerpValueB + lerpIncrementB); AddPlane(s5, s3, s9, s8, wallSubmesh, false, Vector2.zero, new Vector2(stepDepth, staircaseThickness)); } AddPlane(bottomB3, bottomB2, topB3, topB2, ceilingSubmesh, false, Vector2.zero, Vector2.one); break; } Vector3 landingEnd0 = top0 + landingDepthVector; Vector3 landingEnd1 = bottomB1 + landingDepthVector; Vector3 landingEnd2 = landingEnd0 - stairHeightVector; Vector3 landingEnd3 = landingEnd1 - stairHeightVector; Vector3 landingEnd4 = top0 - stairHeightVector; Vector3 landingEnd5 = bottomB1 - stairHeightVector; AddPlane(bottomB1, top0, landingEnd1, landingEnd0, floorSubmesh, false, Vector2.zero, new Vector2(staircaseWidth * 2.5f, staircaseWidth)); //top AddPlane(landingEnd4, landingEnd5, landingEnd2, landingEnd3, ceilingSubmesh, false, Vector2.zero, new Vector2(staircaseWidth * 2.5f, staircaseWidth)); //bottom AddPlane(top0, bottomB1, landingEnd4, landingEnd5, wallSubmesh, false, Vector2.zero, new Vector2(staircaseWidth * 2.5f, staircaseThickness)); //frontside AddPlane(landingEnd1, landingEnd0, landingEnd3, landingEnd2, wallSubmesh, false, Vector2.zero, new Vector2(staircaseWidth * 2.5f, staircaseThickness)); //backside AddPlane(landingEnd0, top0, landingEnd2, landingEnd4, wallSubmesh, false, Vector2.zero, new Vector2(staircaseWidth, staircaseThickness)); //sideleft AddPlane(bottomB1, landingEnd1, landingEnd5, landingEnd3, wallSubmesh, false, Vector2.zero, new Vector2(staircaseWidth, staircaseThickness)); //sideright } } //Center wall float coreHeight = (numberOfFloors * floorHeight); Vector3 coreHeightVector = Vector3.up * coreHeight; Vector3 corePosition = (zeroMesh) ? Vector3.zero : stairPosition; Vector3 w0 = new Vector3(-staircaseWidth / 4.0f, 0, -(stairwellDepth - (staircaseWidth * 2)) / 2.0f) + corePosition; Vector3 w1 = w0 + Vector3.right * staircaseWidth / 2; Vector3 w2 = w0 + staircaseDepthVector; Vector3 w3 = w1 + staircaseDepthVector; Vector3 w4 = w0 + coreHeightVector; Vector3 w5 = w1 + coreHeightVector; Vector3 w6 = w2 + coreHeightVector; Vector3 w7 = w3 + coreHeightVector; AddPlane(w1, w0, w5, w4, wallSubmesh, false, Vector2.zero, new Vector2(staircaseWidth / 2, coreHeight)); // AddPlane(w3, w1, w7, w5, wallSubmesh, false, Vector2.zero, new Vector2(stairwellDepth / 2, coreHeight)); // AddPlane(w2, w3, w6, w7, wallSubmesh, false, Vector2.zero, new Vector2(staircaseWidth / 2, coreHeight)); // AddPlane(w0, w2, w4, w6, wallSubmesh, false, Vector2.zero, new Vector2(stairwellDepth / 2, coreHeight)); // int it = 100; while (volume.stairBaseVector.Count < mesh.meshCount) { if (zeroMesh) { volume.stairBaseVector.Add(stairPosition); } else { volume.stairBaseVector.Add(Vector3.zero); } it--; if (it == 0) { break; } } if (c < numberOfVolumeCores - 1) { mesh.ForceNewMesh(); } } }
private static void CalculateHypotenuse(int pointIndex) { // bool drawLine = numberOfPoints == 4; int pointIndexB = (pointIndex + 1) % numberOfPoints; Vector2 pa = usePoints[pointIndex]; Vector2 pb = usePoints[pointIndexB]; Vector2 baseDir = pa - pb; float baseLength = Vector2.Distance(pa, pb); float aa = pointAngles[pointIndex]; float ab = pointAngles[pointIndexB]; float baseAngle = Vector2.Angle(Vector2.up, baseDir); if (baseAngle < 0) { baseAngle += 360; } baseAngle = baseAngle * Mathf.Deg2Rad * Mathf.Sign(Vector2.Dot(Vector2.right, baseDir)); Vector2 aDir = new Vector2(Mathf.Sin(aa + Mathf.PI * 0.5f), Mathf.Cos(aa + Mathf.PI * 0.5f)); Vector2 bDir = new Vector2(Mathf.Sin(ab), Mathf.Cos(ab)); float hypDot = Vector2.Dot(aDir, bDir); if (hypDot > -0.01f)//reflex - it'll never intersect laddey { return; } float relAngA = aa - baseAngle; float relAngB = ab - baseAngle; //triangulate the adjacent length float adjactentLength = (baseLength * Mathf.Sin(relAngA) * Mathf.Sin(relAngB)) / Mathf.Sin(relAngA - relAngB); //Vector3 midPoint = new Vector3((pa.x+pb.x)*0.5f,0,(pa.y+pb.y)*0.5f); //float relMid = Mathf.LerpAngle(aa, ab, 0.5f); //Vector3 adjPoint = midPoint + new Vector3(Mathf.Sin(relMid), 0, Mathf.Cos(relMid)) * adjactentLength; //Debug.DrawLine(midPoint, adjPoint, BLUE); float hypA = adjactentLength / Mathf.Sin(relAngA);//trig get the hypot float hypB = adjactentLength / Mathf.Sin(relAngB); //Fast line intersection HERE int numberOfOriginalPoints = originalPoints.Length; Vector2 pB0A = pa; Vector2 pB1ha = pa + new Vector2(Mathf.Sin(aa), Mathf.Cos(aa)) * hypA; Vector2 pB0B = pb; Vector2 pB1hb = pb + new Vector2(Mathf.Sin(ab), Mathf.Cos(ab)) * hypB; bool calculateForward = true; bool calculateBackward = true; for (int i = 0; i < numberOfOriginalPoints; i++) { if (i == pointIndex) { continue; } bool skipForard = false, skipBackward = false; if (i == ((pointIndex > 0) ? pointIndex - 1 : numberOfPoints - 1)) { skipForard = true; } if (i == (pointIndex + 1) % numberOfPoints) { skipBackward = true; } Vector2 pA0 = originalPoints[i]; Vector2 pA1 = originalPoints[(i + 1) % numberOfOriginalPoints]; if (pA0 == pB0A || pA1 == pB0A) { skipForard = true; } if (pA0 == pB0B || pA1 == pB0B) { skipBackward = true; } if (calculateForward && !skipForard) { if (BuildrUtils.FastLineIntersection(pA0, pA1, pB0A, pB1ha)) { //hypontenuse intersects building plan hypsForward[pointIndex] = float.PositiveInfinity; calculateForward = false; // if (drawLine) Debug.DrawLine(new Vector3(pB0A.x, 0, pB0A.y), new Vector3(pB1ha.x, 0, pB1ha.y), YELLOW); // if (drawLine) Debug.DrawLine(new Vector3(pA0.x, 0, pA0.y), new Vector3(pA1.x, 0, pA1.y), RED); } } if (calculateBackward && !skipBackward) { if (BuildrUtils.FastLineIntersection(pA0, pA1, pB0B, pB1hb)) { //hypontenuse intersects building plan hypsBackward[pointIndexB] = float.PositiveInfinity; calculateBackward = false; // if (drawLine) Debug.DrawLine(new Vector3(pB0B.x, 0, pB0B.y), new Vector3(pB1hb.x, 0, pB1hb.y), YELLOW); // if (drawLine) Debug.DrawLine(new Vector3(pA0.x, 0, pA0.y), new Vector3(pA1.x, 0, pA1.y), RED); } } } if (calculateForward) { hypsForward[pointIndex] = hypA; // if (drawLine) Debug.DrawLine(new Vector3(pB0A.x, 0, pB0A.y), new Vector3(pB1ha.x, 0, pB1ha.y), BLUE); } if (calculateBackward) { hypsBackward[pointIndexB] = hypB; // if (drawLine) Debug.DrawLine(new Vector3(pB0B.x, 0, pB0B.y), new Vector3(pB1hb.x, 0, pB1hb.y), CYAN); } }
public static void Build(DynamicMeshGenericMultiMaterialMesh _mesh, BuildrData _data, int volumeIndex) { data = _data; mesh = _mesh; mesh.name = "Interior Mesh Volume " + volumeIndex; textures = data.textures.ToArray(); if (!data.renderInteriors) { return; } float largestDepthValue = 0;//deepest value of a bay design in the building float tallestBay = 0; foreach (BuildrBay bay in data.bays) { largestDepthValue = Mathf.Max(largestDepthValue, bay.deepestValue);//get the deepest value tallestBay = Mathf.Max(tallestBay, bay.openingHeight + (data.floorHeight - bay.openingHeight) * bay.openingHeightRatio); } foreach (BuildrFacadeDesign facade in data.facades) { if (facade.type != BuildrFacadeDesign.types.simple) { continue; } largestDepthValue = Mathf.Max(largestDepthValue, facade.simpleBay.deepestValue);//get the deepest value if (facade.simpleBay.isOpening) { tallestBay = Mathf.Max(tallestBay, facade.simpleBay.openingHeight + (data.floorHeight - facade.simpleBay.openingHeight) * facade.simpleBay.openingHeightRatio); } } BuildrFacadeDesign facadeDesign = data.facades[0]; BuildrPlan plan = data.plan; BuildrVolume volume = plan.volumes[volumeIndex]; int numberOfFloors = volume.numberOfFloors; float floorHeight = data.floorHeight; Vector3 floorHeightVector = Vector3.up * floorHeight; float ceilingHeight = tallestBay + (floorHeight - tallestBay) * data.interiorCeilingHeight; //Calculate the internal floor plan points int numberOfVolumePoints = volume.points.Count; Vector2z[] interiorVolumePoints = new Vector2z[numberOfVolumePoints]; for (int i = 0; i < numberOfVolumePoints; i++) { Vector3 lastPoint = plan.points[volume.points[(i > 0) ? i - 1 : numberOfVolumePoints - 1]].vector3; Vector3 thisPoint = plan.points[volume.points[i]].vector3; Vector3 nextPoint = plan.points[volume.points[(i + 1) % numberOfVolumePoints]].vector3; Vector3 normalA = Vector3.Cross(thisPoint - lastPoint, Vector3.up).normalized; Vector3 normalB = Vector3.Cross(nextPoint - thisPoint, Vector3.up).normalized; Vector2z facadeALine = new Vector2z(thisPoint - lastPoint); Vector2z facadeBLine = new Vector2z(thisPoint - nextPoint); //Calculate facade inner origins for floors Vector3 facadeOriginV3A = lastPoint + normalA * largestDepthValue; Vector3 facadeOriginV3B = nextPoint + normalB * largestDepthValue; Vector2z facadeOriginA = new Vector2z(facadeOriginV3A); Vector2z facadeOriginB = new Vector2z(facadeOriginV3B); Vector2z facadeLineIntersection = BuildrUtils.FindIntersection(facadeALine, facadeOriginA, facadeBLine, facadeOriginB); interiorVolumePoints[i] = facadeLineIntersection; } List <Vector2z> interiorVolumePointList = new List <Vector2z>(interiorVolumePoints); List <Rect> volumeCores = new List <Rect>(); List <int> linkedPoints = new List <int>(); foreach (Rect core in plan.cores) { Vector2z coreCenter = new Vector2z(core.center); if (BuildrUtils.PointInsidePoly(coreCenter, interiorVolumePoints)) { volumeCores.Add(core); } } int numberOfVolumeCores = volumeCores.Count; bool print = plan.volumes.IndexOf(volume) == 3; for (int c = 0; c < numberOfVolumeCores; c++) { int numberOfInteriorPoints = interiorVolumePointList.Count; Rect coreBounds = volumeCores[c]; Vector2z coreCenter = new Vector2z(coreBounds.center); Vector2z coreBL = new Vector2z(coreBounds.xMin, coreBounds.yMin); Vector2z coreBR = new Vector2z(coreBounds.xMax, coreBounds.yMin); Vector2z coreTL = new Vector2z(coreBounds.xMin, coreBounds.yMax); Vector2z coreTR = new Vector2z(coreBounds.xMax, coreBounds.yMax); Vector2z[] corePointArray; corePointArray = new[] { coreBL, coreBR, coreTR, coreTL }; //Find the nearest legal cut we can make to join the core and interior point poly int connectingPoint = -1; float connectingPointDistance = Mathf.Infinity; for (int p = 0; p < numberOfInteriorPoints; p++) { if (linkedPoints.Contains(p)) { continue; } Vector2z thisPoint = interiorVolumePointList[p]; float thisPointDistance = Vector2z.SqrMag(thisPoint, coreCenter); if (thisPointDistance < connectingPointDistance) { bool legalCut = true; for (int pc = 0; pc < numberOfInteriorPoints; pc++) { Vector2z p0 = interiorVolumePointList[pc]; Vector2z p1 = interiorVolumePointList[(pc + 1) % numberOfInteriorPoints]; if (BuildrUtils.FastLineIntersection(coreCenter, thisPoint, p0, p1))//check against all lines that this new cut doesn't intersect { if (print) { Debug.Log("FLI " + pc + " " + coreCenter + " " + thisPoint + " " + p0 + " " + p1); } legalCut = false; break; } } if (legalCut) { connectingPoint = p; connectingPointDistance = thisPointDistance; } } } if (connectingPoint == -1) { Debug.Log("Buildr Could not place core"); continue; } Vector2z chosenPoint = interiorVolumePointList[connectingPoint]; int connectingCorePoint = 0; float connectingCorePointDistance = Mathf.Infinity; // Vector2z.SqrMag(corePointArray[0], chosenPoint); for (int cp = 0; cp < 4; cp++) //find the core point to make the cut { float thisCorePointDistance = Vector2z.SqrMag(corePointArray[cp], chosenPoint); if (thisCorePointDistance < connectingCorePointDistance) { connectingCorePoint = cp; connectingCorePointDistance = thisCorePointDistance; } } interiorVolumePointList.Insert(connectingPoint, chosenPoint); //loop back on the floorplan to close it for (int acp = 0; acp < 5; acp++) //loop back on itself to close the core { interiorVolumePointList.Insert(connectingPoint + 1, corePointArray[(connectingCorePoint + acp) % 4]); } for (int i = 0; i < linkedPoints.Count; i++) { if (linkedPoints[i] > connectingPoint) { linkedPoints[i] += 7; } } linkedPoints.AddRange(new[] { connectingPoint, connectingPoint + 1, connectingPoint + 2, connectingPoint + 3, connectingPoint + 4, connectingPoint + 5, connectingPoint + 6 }); // linkedPoints.AddRange(new []{connectingPoint,connectingPoint+6}); } // if(linkedPoints.Count > 0) // Debug.Log(linkedPoints.Count+" "+linkedPoints[0]); Vector2z[] interiorPointListCore = interiorVolumePointList.ToArray(); for (int f = 0; f < numberOfVolumePoints; f++) { ///WALLS int indexAM = Mathf.Abs((f - 1) % numberOfVolumePoints); int indexA = f; int indexB = (f + 1) % numberOfVolumePoints; int indexBP = (f + 2) % numberOfVolumePoints; Vector3 p0m = plan.points[volume.points[indexAM]].vector3; Vector3 p0 = plan.points[volume.points[indexA]].vector3; Vector3 p1 = plan.points[volume.points[indexB]].vector3; Vector3 p1p = plan.points[volume.points[indexBP]].vector3; Vector3 p0interior = interiorVolumePoints[indexA].vector3; Vector3 p1interior = interiorVolumePoints[indexB].vector3; float facadeWidth = Vector3.Distance(p0, p1) - largestDepthValue * 2.0f; Vector3 facadeDirection = (p1 - p0).normalized; Vector3 facadeCross = Vector3.Cross(facadeDirection, Vector3.up); Vector3 lastFacadeDirection = (p0 - p0m).normalized; Vector3 nextFacadeDirection = (p1p - p1).normalized; //only bother with facade directions when facade may intersect inverted geometry float facadeDirDotL = Vector3.Dot(-facadeDirection, lastFacadeDirection); float facadeCrossDotL = Vector3.Dot(-facadeCross, lastFacadeDirection); if (facadeDirDotL <= 0 || facadeCrossDotL <= 0) { lastFacadeDirection = -facadeCross; } float facadeDirDotN = Vector3.Dot(-facadeDirection, nextFacadeDirection); float facadeCrossDotN = Vector3.Dot(-facadeCross, nextFacadeDirection); if (facadeDirDotN <= 0 || facadeCrossDotN <= 0) { nextFacadeDirection = facadeCross; } int floorBase = plan.GetFacadeFloorHeight(volumeIndex, volume.points[indexA], volume.points[indexB]); BuildrVolumeStylesUnit[] styleUnits = volume.styles.GetContentsByFacade(volume.points[indexA]); int floorPatternSize = 0; List <int> facadePatternReference = new List <int>(); //this contains a list of all the facade style indices to refence when looking for the appropriate style per floor int patternCount = 0; foreach (BuildrVolumeStylesUnit styleUnit in styleUnits) //need to knw how big all the styles are together so we can loop through them { floorPatternSize += styleUnit.floors; for (int i = 0; i < styleUnit.floors; i++) { facadePatternReference.Add(patternCount); } patternCount++; } facadePatternReference.Reverse(); int rows = numberOfFloors; Vector2 facadeUV = Vector2.zero; for (int r = 0; r < rows; r++) { float currentFloorHeight = floorHeight * r; Vector3 currentFloorHeightVector = Vector3.up * (data.floorHeight * r); Vector3 facadeFloorBaseVector = p0 + Vector3.up * currentFloorHeight; Vector3 ceilingVector = Vector3.up * ceilingHeight; if (r < floorBase) { //no facade rendered //facade gap filler //interior gap points Vector3 i0 = p1 - facadeDirection.normalized * largestDepthValue; Vector3 i1 = p0 + facadeDirection.normalized * largestDepthValue; Vector3 w0 = i0 + currentFloorHeightVector; Vector3 w1 = i1 + currentFloorHeightVector; Vector3 w2 = w0 + facadeCross * largestDepthValue; Vector3 w3 = w1 + facadeCross * largestDepthValue; Vector3 w4 = w0 + ceilingVector; Vector3 w5 = w1 + ceilingVector; Vector3 w6 = w2 + ceilingVector; Vector3 w7 = w3 + ceilingVector; Vector3 w8 = p1interior + currentFloorHeightVector; Vector3 w9 = p0interior + currentFloorHeightVector; Vector3 w10 = w8 + ceilingVector; Vector3 w11 = w9 + ceilingVector; //floor AddData(new[] { w0, w1, w2, w3 }, new[] { 0, 1, 2, 1, 3, 2 }, volume.FloorTexture(r), false); //ceiling AddData(new[] { w5, w4, w7, w6 }, new[] { 0, 1, 2, 1, 3, 2 }, volume.CeilingTexture(r), false); //sides int wallSubmesh = volume.WallTexture(r); AddPlane(w0, w2, w4, w6, wallSubmesh, false, Vector3.zero, new Vector2(largestDepthValue, floorHeight)); AddPlane(w3, w1, w7, w5, wallSubmesh, false, Vector3.zero, new Vector2(largestDepthValue, floorHeight)); //other gaps float uvWidth1 = Vector3.Distance(w2, w8); AddPlane(w2, w8, w6, w10, wallSubmesh, false, Vector3.zero, new Vector2(uvWidth1, floorHeight)); float uvWidth2 = Vector3.Distance(w3, w9); AddPlane(w9, w3, w11, w7, wallSubmesh, false, Vector3.zero, new Vector2(uvWidth2, floorHeight)); continue; } //Get the facade style id //need to loop through the facade designs floor by floor until we get to the right one int modFloor = ((r - floorBase) % floorPatternSize); facadeDesign = data.facades[styleUnits[facadePatternReference[modFloor]].styleID]; bool isBlankWall = !facadeDesign.hasWindows; if (facadeDesign.type == BuildrFacadeDesign.types.patterned) { if (data.bays.Count == 0 || facadeDesign.bayPattern.Count == 0) { data.illegal = true; return; } BuildrBay firstBay = data.bays[facadeDesign.bayPattern[0]]; if (firstBay.openingWidth > facadeWidth) { isBlankWall = true; } if (facadeDesign.bayPattern.Count == 0) { isBlankWall = true; } } else { if (facadeDesign.simpleBay.openingWidth + facadeDesign.simpleBay.minimumBayWidth > facadeWidth) { isBlankWall = true; } } if (!isBlankWall) { float patternSize = 0;//the space the pattern fills, there will be a gap that will be distributed to all bay styles int numberOfBays = 0; BuildrBay[] bayDesignPattern; int numberOfBayDesigns; if (facadeDesign.type == BuildrFacadeDesign.types.patterned) { numberOfBayDesigns = facadeDesign.bayPattern.Count; bayDesignPattern = new BuildrBay[numberOfBayDesigns]; for (int i = 0; i < numberOfBayDesigns; i++) { bayDesignPattern[i] = data.bays[facadeDesign.bayPattern[i]]; } } else { bayDesignPattern = new[] { facadeDesign.simpleBay }; numberOfBayDesigns = 1; } //start with first window width - we'll be adding to this until we have filled the facade width int it = 100; while (true) { int patternModIndex = numberOfBays % numberOfBayDesigns; float patternAddition = bayDesignPattern[patternModIndex].openingWidth + bayDesignPattern[patternModIndex].minimumBayWidth; if (patternSize + patternAddition < facadeWidth) { patternSize += patternAddition; numberOfBays++; } else { break; } it--; if (it < 0) { break; } } Vector3 windowBase = facadeFloorBaseVector; facadeUV.x = 0; facadeUV.y += floorHeight; float perBayAdditionalSpacing = (facadeWidth - patternSize) / numberOfBays; for (int c = 0; c < numberOfBays; c++) { BuildrBay bayStyle; BuildrBay lastBay; BuildrBay nextBay; bool firstColumn = c == 0; bool lastColumn = c == numberOfBays - 1; if (facadeDesign.type == BuildrFacadeDesign.types.patterned) { int numberOfBayStyles = facadeDesign.bayPattern.Count; bayStyle = bayDesignPattern[c % numberOfBayStyles]; int lastBayIndex = (c > 0) ? (c - 1) % numberOfBayStyles : 0; lastBay = bayDesignPattern[lastBayIndex]; nextBay = bayDesignPattern[(c + 1) % numberOfBayStyles]; } else { bayStyle = facadeDesign.simpleBay; lastBay = facadeDesign.simpleBay; nextBay = facadeDesign.simpleBay; } float actualWindowSpacing = bayStyle.minimumBayWidth + perBayAdditionalSpacing; float leftWidth = actualWindowSpacing * bayStyle.openingWidthRatio; float rightWidth = actualWindowSpacing - leftWidth; float openingWidth = bayStyle.openingWidth; if (firstColumn) { leftWidth += largestDepthValue; } if (lastColumn) { rightWidth += largestDepthValue; } BuildrTexture columnTexture = textures[bayStyle.GetTexture(BuildrBay.TextureNames.ColumnTexture)]; Vector2 columnuvunits = columnTexture.tileUnitUV; float openingHeight = bayStyle.openingHeight; if (columnTexture.patterned) { openingHeight = Mathf.Ceil(bayStyle.openingHeight / columnuvunits.y) * columnuvunits.y; } if (bayStyle.openingHeight == floorHeight) { bayStyle.openingHeight = floorHeight; } float rowBottomHeight = ((floorHeight - openingHeight) * bayStyle.openingHeightRatio); if (columnTexture.patterned) { rowBottomHeight = Mathf.Ceil(rowBottomHeight / columnuvunits.y) * columnuvunits.y; } float rowTopHeight = (floorHeight - rowBottomHeight - openingHeight); bool previousBayIdentical = bayStyle == lastBay; bool nextBayIdentical = bayStyle == nextBay; if (previousBayIdentical && !firstColumn) { leftWidth = actualWindowSpacing;//if next design is identical - add the two parts together the reduce polycount } Vector3 w0, w1, w2, w3; int wallSubmesh = volume.WallTexture(r); bool wallFlipped = false; if (!bayStyle.isOpening) { float bayWidthSize = openingWidth + actualWindowSpacing; if (firstColumn || lastColumn) { bayWidthSize += largestDepthValue; } Vector3 bayWidth = facadeDirection * bayWidthSize; Vector3 bayHeight = Vector3.up * floorHeight; Vector3 bayDepth = facadeCross * largestDepthValue; w0 = windowBase + bayDepth; w1 = windowBase + bayWidth + bayDepth; w2 = windowBase + bayHeight + bayDepth; w3 = windowBase + bayWidth + bayHeight + bayDepth; Vector2 bayOpeningUVEnd = facadeUV + new Vector2(openingWidth + actualWindowSpacing, floorHeight); AddPlane(w0, w1, w2, w3, wallSubmesh, wallFlipped, facadeUV, bayOpeningUVEnd); windowBase = windowBase + bayWidth; //move base vertor to next bay facadeUV.x += openingWidth + actualWindowSpacing; continue; //bay filled - move onto next bay } var verts = new Vector3[16]; verts[0] = windowBase; verts[1] = verts[0] + leftWidth * facadeDirection; verts[2] = verts[1] + openingWidth * facadeDirection; verts[3] = verts[2] + rightWidth * facadeDirection; windowBase = (nextBayIdentical) ? verts[2] : verts[3];//move to next window - if next design is identical - well add the two parts together the reduce polycount facadeUV.x += (nextBayIdentical) ? openingWidth : openingWidth + rightWidth; Vector3 rowBottomVector = Vector3.up * rowBottomHeight; verts[4] = verts[0] + rowBottomVector; verts[5] = verts[1] + rowBottomVector; verts[6] = verts[2] + rowBottomVector; verts[7] = verts[3] + rowBottomVector; Vector3 openingVector = Vector3.up * openingHeight; verts[8] = verts[4] + openingVector; verts[9] = verts[5] + openingVector; verts[10] = verts[6] + openingVector; verts[11] = verts[7] + openingVector; Vector3 rowTopVector = Vector3.up * rowTopHeight; verts[12] = verts[8] + rowTopVector; verts[13] = verts[9] + rowTopVector; verts[14] = verts[10] + rowTopVector; verts[15] = verts[11] + rowTopVector; //Realign facade end points if (firstColumn) { verts[0] = p0interior - facadeCross * largestDepthValue + currentFloorHeightVector; verts[4] = verts[0] + rowBottomVector; verts[8] = verts[4] + openingVector; verts[12] = verts[8] + rowTopVector; } if (lastColumn) { verts[3] = p1interior - facadeCross * largestDepthValue + currentFloorHeightVector; verts[7] = verts[3] + rowBottomVector; verts[11] = verts[7] + openingVector; verts[15] = verts[11] + rowTopVector; } Vector3 openingDepthVector = facadeCross * bayStyle.openingDepth; Vector3 wallDepthVecotr = facadeCross * largestDepthValue; ///WINDOWS int windowSubmesh = bayStyle.GetTexture(BuildrBay.TextureNames.OpeningBackTexture); bool windowFlipped = bayStyle.IsFlipped(BuildrBay.TextureNames.OpeningBackTexture); w0 = verts[10] + openingDepthVector; w1 = verts[9] + openingDepthVector; w2 = verts[6] + openingDepthVector; w3 = verts[5] + openingDepthVector; Vector2 windowUVStart = new Vector2(0, 0); Vector2 windowUVEnd = new Vector2(openingWidth, openingHeight); if (bayStyle.renderBack && !data.cullBays) { AddPlane(w0, w1, w2, w3, windowSubmesh, windowFlipped, windowUVStart, windowUVEnd); } ///COLUMNS //Column Face if (leftWidth > 0)//Column Face Left { w0 = verts[4] + wallDepthVecotr; w1 = verts[5] + wallDepthVecotr; w2 = verts[8] + wallDepthVecotr; w3 = verts[9] + wallDepthVecotr; Vector2 leftColumnUVStart = facadeUV + new Vector2(0, rowBottomHeight); Vector2 leftColumnUVEnd = leftColumnUVStart + new Vector2(leftWidth, openingHeight); AddPlane(w0, w1, w2, w3, wallSubmesh, wallFlipped, leftColumnUVStart, leftColumnUVEnd); } if ((!nextBayIdentical || lastColumn) && rightWidth > 0)//Column Right { w0 = verts[6] + wallDepthVecotr; w1 = verts[7] + wallDepthVecotr; w2 = verts[10] + wallDepthVecotr; w3 = verts[11] + wallDepthVecotr; Vector2 rightColumnUVStart = facadeUV + new Vector2(leftWidth + openingWidth, rowBottomHeight); Vector2 rightColumnUVEnd = rightColumnUVStart + new Vector2(rightWidth, openingHeight); AddPlane(w0, w1, w2, w3, wallSubmesh, wallFlipped, rightColumnUVStart, rightColumnUVEnd); } ///ROWS //Row Bottom if (rowBottomHeight > 0) { w0 = verts[1] + wallDepthVecotr; w1 = verts[2] + wallDepthVecotr; w2 = verts[5] + wallDepthVecotr; w3 = verts[6] + wallDepthVecotr; Vector2 bottomRowUVStart = facadeUV + new Vector2(leftWidth, 0); Vector2 bottomRowUVEnd = bottomRowUVStart + new Vector2(openingWidth, rowBottomHeight); AddPlane(w0, w1, w2, w3, wallSubmesh, wallFlipped, bottomRowUVStart, bottomRowUVEnd); } //Row Top if (rowTopHeight > 0) { w0 = verts[9] + wallDepthVecotr; w1 = verts[10] + wallDepthVecotr; w2 = verts[13] + wallDepthVecotr; w3 = verts[14] + wallDepthVecotr; Vector2 topRowUVStart = facadeUV + new Vector2(leftWidth, rowBottomHeight + openingHeight); Vector2 topRowUVEnd = topRowUVStart + new Vector2(openingWidth, rowTopHeight); AddPlane(w0, w1, w2, w3, wallSubmesh, wallFlipped, topRowUVStart, topRowUVEnd); } //Cross Left Bottom w0 = verts[0] + wallDepthVecotr; w1 = verts[1] + wallDepthVecotr; w2 = verts[4] + wallDepthVecotr; w3 = verts[5] + wallDepthVecotr; Vector2 crossLBUVStart = facadeUV + new Vector2(0, 0); Vector2 crossLBUVEnd = crossLBUVStart + new Vector2(leftWidth, rowBottomHeight); AddPlane(w0, w1, w2, w3, wallSubmesh, wallFlipped, crossLBUVStart, crossLBUVEnd); //Cross Left Top w0 = verts[8] + wallDepthVecotr; w1 = verts[9] + wallDepthVecotr; w2 = verts[12] + wallDepthVecotr; w3 = verts[13] + wallDepthVecotr; Vector2 crossLTUVStart = facadeUV + new Vector2(0, rowBottomHeight + openingHeight); Vector2 crossLTUVEnd = crossLTUVStart + new Vector2(leftWidth, rowTopHeight); AddPlane(w0, w1, w2, w3, wallSubmesh, wallFlipped, crossLTUVStart, crossLTUVEnd); if ((!nextBayIdentical || lastColumn) && rightWidth > 0) { //Cross Right Bottom w0 = verts[2] + wallDepthVecotr; w1 = verts[3] + wallDepthVecotr; w2 = verts[6] + wallDepthVecotr; w3 = verts[7] + wallDepthVecotr; Vector2 crossRBUVStart = facadeUV + new Vector2(leftWidth + openingWidth, 0); Vector2 crossRBUVEnd = crossRBUVStart + new Vector2(rightWidth, rowBottomHeight); AddPlane(w0, w1, w2, w3, wallSubmesh, wallFlipped, crossRBUVStart, crossRBUVEnd); //Cross Right Top w0 = verts[10] + wallDepthVecotr; w1 = verts[11] + wallDepthVecotr; w2 = verts[14] + wallDepthVecotr; w3 = verts[15] + wallDepthVecotr; Vector2 crossRTUVStart = facadeUV + new Vector2(leftWidth + openingWidth, rowBottomHeight + openingHeight); Vector2 crossRTUVEnd = crossRTUVStart + new Vector2(rightWidth, rowTopHeight); AddPlane(w0, w1, w2, w3, wallSubmesh, wallFlipped, crossRTUVStart, crossRTUVEnd); } } } else { // windowless wall Vector3 interiorStart = p0interior + currentFloorHeightVector; Vector3 interiorEnd = p1interior + currentFloorHeightVector; // Vector3 wallVector = (facadeDirection * facadeWidth); Vector3 wallHeightVector = Vector3.up * floorHeight; Vector3 w0 = interiorStart; Vector3 w1 = interiorEnd; Vector3 w2 = interiorStart + wallHeightVector; Vector3 w3 = interiorEnd + wallHeightVector; BuildrTexture texture = textures[facadeDesign.simpleBay.GetTexture(BuildrBay.TextureNames.WallTexture)]; var uvSize = new Vector2(facadeWidth * (1.0f / texture.textureUnitSize.x), floorHeight * (1.0f / texture.textureUnitSize.y)); Vector2 uvunits = texture.tileUnitUV; uvSize.x = Mathf.Ceil(uvSize.x / uvunits.x) * uvunits.x; uvSize.y = Mathf.Ceil(uvSize.y / uvunits.y) * uvunits.y; int wallSubmesh = 0; bool flipped = false; Vector2 wallUVStart = facadeUV; Vector2 wallUVEnd = facadeUV + new Vector2(facadeWidth, floorHeight); AddPlane(w0, w1, w2, w3, wallSubmesh, flipped, wallUVStart, wallUVEnd); } } } ///FLOORS AND CEILING int numberOfBasements = volume.numberOfBasementFloors; int numberOfFloorPoints = interiorVolumePoints.Length; int[] baseFloorPlanTriangles = EarClipper.Triangulate(interiorVolumePoints); int baseFloorVectors = interiorVolumePoints.Length; var newEndVerts = new Vector3[baseFloorVectors]; Vector3 basementBaseDrop = -floorHeightVector * numberOfBasements; for (int i = 0; i < baseFloorVectors; i++) { newEndVerts[i] = interiorVolumePoints[i].vector3 + basementBaseDrop; } var tris = new List <int>(baseFloorPlanTriangles); //Bottom Floor int floorSubmesh = volume.FloorTexture(-numberOfBasements); AddData(newEndVerts, baseFloorPlanTriangles, floorSubmesh, false); //Top Ceiling if (true)//Todo: add conditional for roof opening { Vector3 ceilingHeightVector = floorHeightVector * (numberOfFloors - 1 + numberOfBasements) + Vector3.up * ceilingHeight; for (int i = 0; i < baseFloorVectors; i++) { newEndVerts[i] += ceilingHeightVector; } tris.Reverse(); AddData(newEndVerts, tris.ToArray(), volume.CeilingTexture(numberOfFloors - 1), false); } //inner floors int[] floorPlanTriangles = EarClipper.Triangulate(interiorPointListCore); int numberOfFloorVectors = interiorPointListCore.Length; for (int floorIndex = -numberOfBasements; floorIndex < numberOfFloors; floorIndex++) { Vector3 floorVectorHeight = floorHeightVector * floorIndex; newEndVerts = new Vector3[numberOfFloorVectors]; for (int i = 0; i < numberOfFloorVectors; i++) { newEndVerts[i] = interiorPointListCore[i].vector3 + floorVectorHeight; } tris = new List <int>(floorPlanTriangles); //Floor if (floorIndex > -numberOfBasements) { AddData(newEndVerts, tris.ToArray(), volume.FloorTexture(floorIndex), false); } //Ceiling if (floorIndex < numberOfFloors - 1) { Vector3 ceilingHeightVector = Vector3.up * ceilingHeight; for (int i = 0; i < numberOfFloorVectors; i++) { newEndVerts[i] += ceilingHeightVector; } tris.Reverse(); AddData(newEndVerts, tris.ToArray(), volume.CeilingTexture(floorIndex), false); } //basement walls if (floorIndex < 0) { for (int f = 0; f < numberOfFloorPoints; f++) { Vector3 basementVector = floorHeightVector * floorIndex; int indexA = f; int indexB = (f + 1) % numberOfFloorPoints; Vector3 p0 = interiorVolumePoints[indexA].vector3 + basementVector; Vector3 p1 = interiorVolumePoints[indexB].vector3 + basementVector; Vector3 p2 = p0 + floorHeightVector; Vector3 p3 = p1 + floorHeightVector; Vector2 uv1 = new Vector2(Vector3.Distance(p0, p1), floorHeight); AddPlane(p0, p1, p2, p3, volume.WallTexture(floorIndex), false, Vector2.zero, uv1); } } } //Core walls for (int c = 0; c < numberOfVolumeCores; c++) { Rect coreBounds = volumeCores[c]; Vector3 coreBL = new Vector3(coreBounds.xMin, 0, coreBounds.yMin); Vector3 coreBR = new Vector3(coreBounds.xMax, 0, coreBounds.yMin); Vector3 coreTL = new Vector3(coreBounds.xMin, 0, coreBounds.yMax); Vector3 coreTR = new Vector3(coreBounds.xMax, 0, coreBounds.yMax); for (int floorIndex = -numberOfBasements; floorIndex < numberOfFloors - 1; floorIndex++) { Vector3 c0 = floorHeightVector * floorIndex + Vector3.up * ceilingHeight; Vector3 f0 = floorHeightVector * floorIndex + Vector3.up * floorHeight; float gapHeight = floorHeight - ceilingHeight; AddPlane(coreBL + c0, coreBR + c0, coreBL + f0, coreBR + f0, 0, false, Vector2.zero, new Vector2(coreBounds.width, gapHeight)); AddPlane(coreBR + c0, coreTR + c0, coreBR + f0, coreTR + f0, 0, false, Vector2.zero, new Vector2(coreBounds.width, gapHeight)); AddPlane(coreTR + c0, coreTL + c0, coreTR + f0, coreTL + f0, 0, false, Vector2.zero, new Vector2(coreBounds.width, gapHeight)); AddPlane(coreTL + c0, coreBL + c0, coreTL + f0, coreBL + f0, 0, false, Vector2.zero, new Vector2(coreBounds.width, gapHeight)); } } }