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);
                }
            }
        }
Exemple #7
0
        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();
                    }
                }
            }
        }