public static float CalculateArcLength(FacadeGenerator.FacadeData facade) { float roughArcLength = 0; roughArcLength += Vector3.Distance(facade.baseA, facade.controlA); roughArcLength += Vector3.Distance(facade.controlA, facade.controlB); roughArcLength += Vector3.Distance(facade.controlB, facade.baseB); int subdivisions = Mathf.RoundToInt(roughArcLength); float output = 0; Vector3 p0 = facade.baseA; Vector3 p1 = facade.baseB; Vector3 cw0 = facade.controlA; Vector3 cw1 = facade.controlB; Vector3 last = p0; for (int i = 1; i < subdivisions + 1; i++) { float t = i / (float)subdivisions; Vector3 cp = FacadeSpline.Calculate(p0, cw0, cw1, p1, t); float dist = Vector3.Distance(last, cp); output += dist; last = cp; } return(output); }
public static Vector3[] CalculateCurvedFacadeBasePoints(FacadeGenerator.FacadeData facade, int pointCount) { Vector3 p0 = facade.baseA; Vector3 p1 = facade.baseB; Vector3 cw0 = facade.controlA; Vector3 cw1 = facade.controlB; Vector3[] output = new Vector3[pointCount]; for (int t = 0; t < pointCount; t++) { Vector3 cp = FacadeSpline.Calculate(p0, cw0, cw1, p1, t / (pointCount - 1f)); output[t] = cp; } return(output); }
private static List<Vector3[]> GetFacadeTriangles(IVolume volume) { List<Vector3[]> output = new List<Vector3[]>(); int numberOfPoints = volume.numberOfPoints; Vector3 pU = Vector3.up * volume.planHeight; for (int p = 0; p < numberOfPoints; p++) { if (volume[p].IsWallStraight()) { Vector3 p0 = volume.WorldPoint(p); Vector3 p1 = volume.WorldPoint((p + 1) % numberOfPoints); Vector3[] triA = new Vector3[6]; //tri a triA[0] = (p0); triA[1] = (p1); triA[2] = (p0 + pU); //tri b triA[3] = (p1); triA[4] = (p1 + pU); triA[5] = (p0 + pU); output.Add(triA); } else { Vector3 p0 = volume.WorldPoint(p); Vector3 p1 = volume.WorldPoint((p + 1) % numberOfPoints);//rotation * floorplan.BuildingPoint((p + 1) % numberOfPoints) + position); Vector3 cw0 = volume.WorldControlPointA(p);//rotation * floorplan.BuildingControlPoint(p) + position); Vector3 cw1 = volume.WorldControlPointB(p);//rotation * floorplan.BuildingControlPoint(p) + position); Vector3[] curveWall = new Vector3[10]; for (int t = 0; t < 10; t++) curveWall[t] = FacadeSpline.Calculate(p0, cw0, cw1, p1, t / 9f); Vector3[] tris = new Vector3[6 * 9]; for (int t = 0; t < 9; t++) { tris[t * 6 + 0] = curveWall[t]; tris[t * 6 + 1] = curveWall[t + 1]; tris[t * 6 + 2] = curveWall[t] + pU; tris[t * 6 + 3] = curveWall[t + 1]; tris[t * 6 + 4] = curveWall[t + 1] + pU; tris[t * 6 + 5] = curveWall[t] + pU; } output.Add(tris); } } return output; }
private static List<Vector3[]> GetFacadeQuads(IVolume volume) { List<Vector3[]> output = new List<Vector3[]>(); int numberOfPoints = volume.numberOfPoints; Vector3 pU = Vector3.up * volume.planHeight; for (int p = 0; p < numberOfPoints; p++) { if (volume[p].IsWallStraight()) { Vector3 p0 = volume.WorldPoint(p); Vector3 p1 = volume.WorldPoint((p + 1) % numberOfPoints); Vector3[] quad = new Vector3[4]; quad[0] = p0; quad[1] = p1; quad[2] = p1 + pU; quad[3] = p0 + pU; output.Add(quad); } else { Vector3 p0 = volume.WorldPoint(p); Vector3 p1 = volume.WorldPoint((p + 1) % numberOfPoints);//rotation * floorplan.BuildingPoint((p + 1) % numberOfPoints) + position); Vector3 cw0 = volume.WorldControlPointA(p);//rotation * floorplan.BuildingControlPoint(p) + position); Vector3 cw1 = volume.WorldControlPointB(p);//rotation * floorplan.BuildingControlPoint(p) + position); Vector3[] curveWall = new Vector3[10]; for (int t = 0; t < 10; t++) curveWall[t] = FacadeSpline.Calculate(p0, cw0, cw1, p1, t / 9f); Vector3[] quads = new Vector3[4 * 9]; for (int t = 0; t < 9; t++) { quads[t * 4 + 0] = curveWall[t]; quads[t * 4 + 1] = curveWall[t + 1]; quads[t * 4 + 2] = curveWall[t + 1] + pU; quads[t * 4 + 3] = curveWall[t] + pU; } output.Add(quads); } } return output; }
public void CalculateExternalWallAnchors() { HUtils.log(); if (_externalFacadeWallAnchors == null) { _externalFacadeWallAnchors = new Dictionary <int, List <Vector2Int> >(); } if (_externalWallAnchorsFacades == null) { _externalWallAnchorsFacades = new Dictionary <Vector2Int, List <int> >(); } if (_externalWallAnchors == null) { _externalWallAnchors = new List <Vector2Int>(); } _externalFacadeWallAnchors.Clear(); _externalWallAnchorsFacades.Clear(); _externalWallAnchors.Clear(); int pointCount = _points.Count; // int anchorCount = 0; for (int p = 0; p < pointCount; p++) { VolumePoint a = _points[p]; VolumePoint b = _points[(p + 1) % pointCount]; Vector2 av = a.position.vector2; Vector2 bv = b.position.vector2; _externalFacadeWallAnchors.Add(p, new List <Vector2Int>()); //new facade entry if (IsWallStraight(p)) { float length = Vector2.Distance(av, bv); int wallSections = Mathf.FloorToInt(length / _minimumWallUnitLength); if (wallSections < 1) { wallSections = 1; } for (int ws = 0; ws < wallSections + 1; ws++) { float lerp = ws / ((float)wallSections); Vector2Int point = new Vector2Int(Vector2.Lerp(av, bv, lerp)); _externalFacadeWallAnchors[p].Add(point); AddFacadeWallAnchors(point, p); if (ws < wallSections) { _externalWallAnchors.Add(point); } } } else { Vector2 cw0 = a.controlA.vector2; Vector2 cw1 = a.controlB.vector2; Vector2 last = Vector2.zero; float arcLength = 0; for (int t = 0; t < 10; t++) { Vector2 cp = FacadeSpline.Calculate(av, cw0, cw1, bv, t / 9f); if (t > 0) { arcLength += Vector2.Distance(cp, last); } last = cp; } int wallSections = Mathf.FloorToInt(arcLength / _minimumWallUnitLength); if (wallSections < 1) { wallSections = 1; } float sectionLength = arcLength / Mathf.Max(wallSections - 1f, 1f); int movement = wallSections * 10; int currentIndex = 0; Vector2 lastCP = av; Vector2 lastA = av; float lastDist = 0; Vector2Int avi = new Vector2Int(av); _externalFacadeWallAnchors[p].Add(avi); AddFacadeWallAnchors(avi, p); _externalWallAnchors.Add(avi); for (int m = 0; m < movement; m++) { float percent = m / (float)movement; Vector2 cp = FacadeSpline.Calculate(av, cw0, cw1, bv, percent); float dist = Vector2.Distance(lastA, cp); // Debug.Log(dist); if (dist >= sectionLength) { float cpDist = dist - lastDist; float overDist = dist - sectionLength; float targetPercent = 1 - Mathf.Clamp01(overDist / cpDist); Vector2 usePoint = Vector2.Lerp(lastCP, cp, targetPercent); lastA = usePoint; currentIndex++; Vector2Int upi = new Vector2Int(usePoint); _externalFacadeWallAnchors[p].Add(upi); AddFacadeWallAnchors(upi, p); _externalWallAnchors.Add(upi); if (currentIndex == wallSections - 2) { break; } } lastCP = cp; lastDist = dist; } Vector2Int bvi = new Vector2Int(bv); _externalFacadeWallAnchors[p].Add(bvi); AddFacadeWallAnchors(bvi, p); // _externalWallAnchors.Add(bvi); } } }
private static void DrawFloorplans(Building _building) { int numberOfFloorplans = _building.numberOfPlans; // Vector3 position = _building.transform.position; // Quaternion rotation = _building.transform.rotation; Camera sceneCamera = Camera.current; // Ray ray = sceneCamera.ScreenPointToRay(new Vector3(Event.current.mousePosition.x, Screen.height - Event.current.mousePosition.y - 30, 0)); // Volume mouseOverPlan = BuildrUtils.OnFloorplanSelectionClick(_building, ray).volume; for (int f = 0; f < numberOfFloorplans; f++) { IVolume volume = _building[f]; int numberOfPoints = volume.numberOfPoints; int numberOfFloors = volume.floors; float planHeight = volume.floorHeight; float totalPlanHeight = volume.planHeight; Vector3 planHeightV = totalPlanHeight * Vector3.up; Handles.color = Color.magenta; for (int p = 0; p < numberOfPoints; p++) { Vector3 p0 = volume.WorldPoint(p); Vector3 p1 = volume.WorldPoint((p + 1) % numberOfPoints); Vector3 facadeDirection = Vector3.Cross(Vector3.up, (p1 - p0).normalized); Plane facadePlane = new Plane(facadeDirection, p0); bool planeVisible = facadePlane.SameSide(p0 + facadeDirection, sceneCamera.transform.position); if (!planeVisible) continue; // Vector3 cameraDirection = sceneCamera.transform.forward; // float facadeDot = Vector3.Dot(facadeDirection, cameraDirection); Facade facadeDesign = volume.GetFacade(p); string facadeDesignTitle = (facadeDesign != null) ? facadeDesign.name : "no facade design set(BuildingFacadeEditor)"; Handles.Label(Vector3.Lerp(p0, p1, 0.5f), facadeDesignTitle); // if (facadeDot > -0.1f) // continue; //Render handles if (volume.IsWallStraight(p)) { int wallSections = Mathf.FloorToInt(Vector3.Distance(p0, p1) / volume.minimumWallUnitLength); if (wallSections < 1) wallSections = 1; for (int ws = 0; ws < wallSections + 1; ws++) { float lerp = ws / ((float)wallSections); Vector3 basePos = Vector3.Lerp(p0, p1, lerp); Handles.DrawLine(basePos, basePos + planHeightV); } for (int fl = 0; fl < numberOfFloors + 1; fl++) { // Handles.color = fl == 0 || fl == numberOfFloors ? MAIN_LINE_COLOUR : SUB_LINE_COLOUR; float lineHeight = fl * planHeight; Vector3 lineHeightV = lineHeight * Vector3.up; Handles.DrawLine(p0 + lineHeightV, p1 + lineHeightV); } } else { Vector3 cw0 = volume.WorldControlPointA(p); Vector3 cw1 = volume.WorldControlPointB(p); Vector3[] curveWall = new Vector3[10]; float arcLength = 0; for (int t = 0; t < 10; t++) { Vector3 cp = FacadeSpline.Calculate(p0, cw0, cw1, p1, t / 9f); curveWall[t] = cp; if (t > 0) arcLength += Vector3.Distance(curveWall[t - 1], curveWall[t]); } for (int fl = 0; fl < numberOfFloors + 1; fl++) { // Handles.color = fl == 0 || fl == numberOfFloors ? MAIN_LINE_COLOUR : SUB_LINE_COLOUR; float lineHeight = fl * planHeight; Vector3 lineHeightV = lineHeight * Vector3.up; for (int t = 0; t < 9; t++) { Vector3 cwp0 = curveWall[t]; Vector3 cwp1 = curveWall[t + 1]; Handles.DrawLine(cwp0 + lineHeightV, cwp1 + lineHeightV); } // Handles.DrawLine(p0 + lineHeightV, p1 + lineHeightV); } } // Handles.color = MAIN_LINE_COLOUR; Handles.DrawLine(p0, p0 + Vector3.up * totalPlanHeight); } } }
private static void DrawFloorplans(IBuilding _building, IVolume mouseOverPlan) { int numberOfFloorplans = _building.numberOfPlans; Vector3 position = _building.transform.position; Quaternion rotation = _building.transform.rotation; Camera sceneCamera = Camera.current; Vector3[] centerPoints = new Vector3[numberOfFloorplans]; for (int f = 0; f < numberOfFloorplans; f++) { centerPoints[f] = BuildrUtils.CalculateFloorplanCenter(_building[f]); } // Ray ray = sceneCamera.ScreenPointToRay(new Vector3(Event.current.mousePosition.x, Screen.height - Event.current.mousePosition.y - 30, 0)); // Floorplan mouseOverPlan = BuildrUtils.OnFloorplanSelectionClick(_building, ray); //Draw Floorplan outlines for (int f = 0; f < numberOfFloorplans; f++) { IVolume volume = _building[f]; int numberOfPoints = volume.numberOfPoints; Vector2 leftPoint = Vector2.right; Vector3 labelPoint = volume.BuildingPoint(0) + position; int numberOfTopPoints = 0; for (int p = 0; p < numberOfPoints; p++) { if (volume.IsWallStraight(p)) { numberOfTopPoints++; } else { numberOfTopPoints += 9; } } Vector3[] planVs = new Vector3[numberOfTopPoints]; int planVIndex = 0; Vector3 planUp = Vector3.up * volume.planHeight; for (int p = 0; p < numberOfPoints; p++) { Vector3 p0 = volume.WorldPoint(p) + planUp;//rotation * floorplan.BuildingPoint(p) + position); Vector2 p0ss = sceneCamera.WorldToScreenPoint(p0); if (p0ss.x < leftPoint.x) { leftPoint = p0ss; labelPoint = p0; } //Render handles if (volume.IsWallStraight(p)) { planVs[planVIndex] = p0; planVIndex++; } else { Vector3 p1 = volume.WorldPoint((p + 1) % numberOfPoints) + planUp; //rotation * floorplan.BuildingPoint((p + 1) % numberOfPoints) + position); Vector3 cw0 = volume.WorldControlPointA(p) + planUp; //rotation * floorplan.BuildingControlPoint(p) + position); Vector3 cw1 = volume.WorldControlPointB(p) + planUp; //rotation * floorplan.BuildingControlPoint(p) + position); Vector3[] curveWall = new Vector3[10]; for (int t = 0; t < 10; t++) { Vector3 cp = FacadeSpline.Calculate(p0, cw0, cw1, p1, t / 9f); curveWall[t] = cp; if (t < 9) { planVs[planVIndex] = cp; planVIndex++; } } } } if ((Volume)volume == BuildingEditor.volume) { Handles.color = SELECTED_BLUEPRINT_COLOUR; } else if (mouseOverPlan == volume) { Handles.color = HIGHLIGHTED_BLUEPRINT_COLOUR; } else { Handles.color = UNSELECTED_BLUEPRINT_COLOUR; } // Handles.DrawAAConvexPolygon(planVs);//draw plan outline DrawConcavePolygonHandle.Shape(planVs, Handles.color); // Vector2 textDimensions = GUI.skin.label.CalcSize(new GUIContent(volume.name)); Handles.Label(labelPoint, volume.name); int linkCount = volume.linkPlanCount; Vector3 thisCenter = centerPoints[f]; Handles.color = Color.green; for (int l = 0; l < linkCount; l++) { if (f == l) { continue; } // Volume link = volume.linkedPlans[l]; Vector3 linkCenter = centerPoints[l]; Handles.DrawDottedLine(thisCenter, linkCenter, 5); } int numberOfFloors = volume.floors; float planHeight = volume.floorHeight; float totalPlanHeight = volume.planHeight; Vector3 planHeightV = totalPlanHeight * Vector3.up; Handles.color = new Color(0, 0.2f, 1, 0.5f); for (int p = 0; p < numberOfPoints; p++) { Vector3 p0 = rotation * volume.BuildingPoint(p) + position; Vector3 p1 = rotation * volume.BuildingPoint((p + 1) % numberOfPoints) + position; //Render handles if (volume.IsWallStraight(p)) { int wallSections = Mathf.FloorToInt(Vector3.Distance(p0, p1) / volume.minimumWallUnitLength); if (wallSections < 1) { wallSections = 1; } for (int ws = 0; ws < wallSections + 1; ws++) { float lerp = ws / ((float)wallSections); Vector3 basePos = Vector3.Lerp(p0, p1, lerp); Handles.DrawLine(basePos, basePos + planHeightV); } for (int fl = 0; fl < numberOfFloors + 1; fl++) { Handles.color = fl == 0 || fl == numberOfFloors ? MAIN_LINE_COLOUR : SUB_LINE_COLOUR; float lineHeight = fl * planHeight; Vector3 lineHeightV = lineHeight * Vector3.up; Handles.DrawLine(p0 + lineHeightV, p1 + lineHeightV); } } else { Vector3 cw0 = volume.WorldControlPointA(p); Vector3 cw1 = volume.WorldControlPointB(p); Vector3[] curveWall = new Vector3[10]; float arcLength = 0; for (int t = 0; t < 10; t++) { Vector3 cp = FacadeSpline.Calculate(p0, cw0, cw1, p1, t / 9f); curveWall[t] = cp; if (t > 0) { arcLength += Vector3.Distance(curveWall[t - 1], curveWall[t]); } } for (int fl = 0; fl < numberOfFloors + 1; fl++) { Handles.color = fl == 0 || fl == numberOfFloors ? MAIN_LINE_COLOUR : SUB_LINE_COLOUR; float lineHeight = fl * planHeight; Vector3 lineHeightV = lineHeight * Vector3.up; for (int t = 0; t < 9; t++) { Vector3 cwp0 = curveWall[t]; Vector3 cwp1 = curveWall[t + 1]; Handles.DrawLine(cwp0 + lineHeightV, cwp1 + lineHeightV); } // Handles.DrawLine(p0 + lineHeightV, p1 + lineHeightV); } } Handles.color = MAIN_LINE_COLOUR; Handles.DrawLine(p0, p0 + Vector3.up * totalPlanHeight); if ((Volume)volume == BuildingEditor.volume) { Vector3 facadeCenter = Vector3.Lerp(p0, p1, 0.5f) + planUp; // float gtbSize = HandleUtility.GetHandleSize(facadeCenter) * 0.1f; // Handles.Label(facadeCenter, "Is gabled"); // Handles.Button(facadeCenter, Quaternion.identity, gtbSize, gtbSize, Handles.DotCap); Handles.BeginGUI(); Vector2 portalScreenPos = Camera.current.WorldToScreenPoint(facadeCenter); portalScreenPos.y = Camera.current.pixelHeight - portalScreenPos.y; Rect screenRect = new Rect(portalScreenPos, new Vector2(350, 500)); GUILayout.BeginArea(screenRect); EditorGUILayout.LabelField(string.Format("Facade: {0}", p + 1)); // RoofFacadeInspectorGUI(volume, p); GUILayout.EndArea(); Handles.EndGUI(); } } } }