示例#1
0
        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);
        }
示例#2
0
        public static void GenerateFacade(FacadeGenerator.FacadeData data, Texture2D texture, Rect space)
        {
            Vector3    facadeVector = data.baseB - data.baseA;
            int        wallSections = 0;
            Vector2    wallSectionPhyicalSize;
            Vector2Int wallSectionPixelSize;

            if (data.isStraight)
            {
                var facadeLength = facadeVector.magnitude;
                wallSections = Mathf.FloorToInt(facadeLength / data.minimumWallUnitLength);
            }
            else
            {
                wallSections = data.anchors.Count - 1;
            }
            wallSectionPhyicalSize = new Vector2(Vector2.Distance(data.anchors[0].vector2, data.anchors[1].vector2), data.floorHeight);
            wallSectionPixelSize   = new Vector2Int(Mathf.RoundToInt(space.width / wallSections), Mathf.RoundToInt(space.height / data.floors));
            Dictionary <WallSection, Color32[]> generatedSections = new Dictionary <WallSection, Color32[]>();

            int startFloor = data.startFloor;

            for (int fl = startFloor; fl < data.floorCount; fl++)
            {
                for (int s = 0; s < wallSections; s++)
                {
                    //                    Debug.Log(s);
                    WallSection section = data.facadeDesign.GetWallSection(s, fl, wallSections, data.floorCount);
                    //                    Debug.Log(section);
                    if (section == null)
                    {
                        continue;
                    }
                    //                    Texture2D generatedTexture;
                    Color32[] wallsectionColourArray;
                    if (generatedSections.ContainsKey(section))
                    {
                        wallsectionColourArray = generatedSections[section];
                    }
                    else
                    {
                        WallSectionGenerator.Texture(out wallsectionColourArray, section, wallSectionPixelSize, wallSectionPhyicalSize);
                        generatedSections.Add(section, wallsectionColourArray);
                    }

                    int xPosition = Mathf.RoundToInt(space.x) + wallSectionPixelSize.x * s;
                    int yPosition = Mathf.RoundToInt(space.y) + wallSectionPixelSize.y * fl;
                    texture.SetPixels32(xPosition, yPosition, wallSectionPixelSize.x, wallSectionPixelSize.y, wallsectionColourArray);
                }
                //note string courses ignored for now
            }
        }
示例#3
0
        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);
        }
示例#4
0
        private void UpdatePreview()
        {
            FacadeGenerator.FacadeData fData = new FacadeGenerator.FacadeData();
            Vector2 sectionSize = new Vector2(2, 3);

            fData.baseA    = new Vector3(0, 0, 0);
            fData.baseB    = new Vector3(sectionSize.x * SIZE.x, 0, 0);
            fData.controlA = Vector3.zero;
            fData.controlB = Vector3.zero;
            List <Vector2Int> anchors = new List <Vector2Int>();

            fData.anchors               = anchors;
            fData.isStraight            = true;
            fData.curveStyle            = VolumePoint.CurveStyles.Distance;
            fData.floorCount            = SIZE.y;
            fData.facadeDesign          = _facade;
            fData.startFloor            = 0;
            fData.actualStartFloor      = 0;
            fData.foundationDepth       = 0;
            fData.wallThickness         = 0.25f;
            fData.minimumWallUnitLength = sectionSize.x;
            fData.floorHeight           = sectionSize.y;
            fData.meshType              = BuildingMeshTypes.Full;
            fData.colliderType          = BuildingColliderTypes.None;
            fData.cullDoors             = false;
            fData.prefabs               = null;

            BuildRMesh dMesh = new BuildRMesh("facade preview");

            FacadeGenerator.GenerateFacade(fData, dMesh);
            _mesh = new Mesh();
            dMesh.Build(_mesh);
            if (_materialList == null)
            {
                _materialList = new List <Material>();
            }
            _materialList.Clear();
            _materialList.AddRange(dMesh.materials);
        }
示例#5
0
        public static void Generate(IBuilding building)
        {
            int numberOfVolumes = building.numberOfVolumes;

//            Debug.Log("n vol "+numberOfVolumes);
            for (int v = 0; v < numberOfVolumes; v++)
            {
                IVolume volume = building[v];
                volume.CheckVolume();
                if (!volume.isLegal)
                {
                    GenerateMesh.ClearVisuals(volume);
                    continue;
                }

                int                   numberOfPoints  = volume.numberOfPoints;
                float                 totalPlanHeight = volume.planHeight;
                Vector3               planUp          = totalPlanHeight * Vector3.up;
                VerticalOpening[]     volumeOpenings  = BuildrUtils.GetOpeningsQuick(building, volume);
                float                 foundation      = building.IsBaseVolume(volume) ? building.foundationDepth : 0;//set suspended volumes foundation to 0
                IVisualPart           visual          = volume.visualPart;
                BuildRMesh            dMesh           = visual.dynamicMesh;
                BuildRCollider        cMesh           = visual.colliderMesh;
                BuildingMeshTypes     meshType        = building.meshType;
                BuildingColliderTypes colliderType    = building.colliderType;
                dMesh.Clear();
                cMesh.Clear();
                cMesh.TogglePrimitives(colliderType == BuildingColliderTypes.Primitive);
                cMesh.thickness = volume.wallThickness;
                if (colliderType == BuildingColliderTypes.None)
                {
                    cMesh = null;
                }
                Transform[] prefabs     = volume.prefabs.GetComponentsInChildren <Transform>();
                int         prefabCount = prefabs.Length;
                for (int p = 0; p < prefabCount; p++)
                {
                    if (prefabs[p] == volume.prefabs)
                    {
                        continue;
                    }
                    if (prefabs[p] == null)
                    {
                        continue;                   //gone already man
                    }
#if UNITY_EDITOR
                    Object.DestroyImmediate(prefabs[p].gameObject);
#else
                    Object.Destroy(prefabs[p].gameObject);
#endif
                }

                Dictionary <int, List <Vector2Int> > anchorPoints = volume.facadeWallAnchors;
                Texture2D facadeTexture = null;

                #region Exteriors

//                Debug.Log("ext");
                if (building.generateExteriors)
                {
                    for (int p = 0; p < numberOfPoints; p++)
                    {
                        if (!volume[p].render)
                        {
                            continue;
                        }
                        Vector3 p0              = volume.BuildingPoint(p);
                        Vector3 p1              = volume.BuildingPoint((p + 1) % numberOfPoints);
                        Vector3 p0u             = p0 + planUp;
                        Vector3 p1u             = p1 + planUp;
                        Vector3 cw0             = volume.BuildingControlPointA(p);
                        Vector3 cw1             = volume.BuildingControlPointB(p);
                        Facade  facade          = volume.GetFacade(p);
                        bool    isStraight      = volume.IsWallStraight(p);
                        Vector3 facadeVector    = p1 - p0;
                        Vector3 facadeDirection = facadeVector.normalized;
                        float   facadeLength    = facadeVector.magnitude;
                        if (facadeLength < Mathf.Epsilon)
                        {
                            continue;
                        }

//                        Debug.Log("flength "+facadeLength);
                        if (facade == null || colliderType == BuildingColliderTypes.Simple)
                        {
//                            Debug.Log("simple");
                            if (isStraight)
                            {
                                Vector3 normal  = Vector3.Cross(Vector3.up, facadeDirection);
                                Vector4 tangent = BuildRMesh.CalculateTangent(facadeDirection);
                                if (facade == null)
                                {
                                    dMesh.AddPlane(p0, p1, p0u, p1u, normal, tangent, 0);
                                }

                                if (colliderType != BuildingColliderTypes.None)
                                {
                                    cMesh.AddPlane(p0, p1, p0u, p1u);
                                }

                                if (foundation > Mathf.Epsilon)
                                {
                                    Vector3 fp2 = p0;
                                    Vector3 fp3 = p1;
                                    Vector3 fp0 = fp2 + Vector3.down * foundation;
                                    Vector3 fp1 = fp3 + Vector3.down * foundation;
                                    if (facade == null)
                                    {
                                        Surface foundationSurface = building.foundationSurface != null ? building.foundationSurface : null;
                                        int     foundationSubmesh = dMesh.submeshLibrary.SubmeshAdd(foundationSurface);
                                        Vector2 uxmax             = new Vector2(Vector3.Distance(p0, p1), foundation);
                                        dMesh.AddPlane(fp0, fp1, fp2, fp3, Vector2.zero, uxmax, normal, tangent, foundationSubmesh, foundationSurface);
                                    }

                                    if (colliderType != BuildingColliderTypes.None)
                                    {
                                        cMesh.mesh.AddPlane(fp0, fp1, fp2, fp3, 0);
                                    }
                                }
                            }
                            else
                            {
                                List <Vector2Int> facadeAnchorPoints = anchorPoints[p];
                                int anchorCount = facadeAnchorPoints.Count;
                                for (int i = 0; i < anchorCount - 1; i++)
                                {
                                    Vector3 c0 = facadeAnchorPoints[i].vector3XZ;
                                    c0.y = p0.y;
                                    Vector3 c1 = facadeAnchorPoints[i + 1].vector3XZ;
                                    c1.y = p0.y;
                                    Vector3 c2 = c0 + planUp;
                                    Vector3 c3 = c1 + planUp;
                                    Vector3 sectionDirection = (c1 - c0).normalized;
                                    Vector3 normal           = Vector3.Cross(Vector3.up, sectionDirection);
                                    Vector4 tangent          = BuildRMesh.CalculateTangent(sectionDirection);
                                    if (facade == null)
                                    {
                                        dMesh.AddPlane(c0, c1, c2, c3, normal, tangent, 0);
                                    }
                                    if (colliderType != BuildingColliderTypes.None)
                                    {
                                        cMesh.AddPlane(c0, c1, c2, c3);
                                    }
                                    if (foundation > Mathf.Epsilon)
                                    {
                                        Vector3 fp2 = c0;
                                        Vector3 fp3 = c1;
                                        Vector3 fp0 = fp2 + Vector3.down * foundation;
                                        Vector3 fp1 = fp3 + Vector3.down * foundation;

                                        if (facade == null)
                                        {
                                            Surface foundationSurface = building.foundationSurface != null ? building.foundationSurface : null;
                                            int     foundationSubmesh = dMesh.submeshLibrary.SubmeshAdd(foundationSurface);
                                            Vector2 uxmax             = new Vector2(Vector3.Distance(c0, c1), foundation);
                                            dMesh.AddPlane(fp0, fp1, fp2, fp3, Vector2.zero, uxmax, normal, tangent, foundationSubmesh, foundationSurface);
                                        }

                                        if (colliderType != BuildingColliderTypes.None)
                                        {
                                            cMesh.AddPlane(fp0, fp1, fp2, fp3);
                                        }
                                    }
                                }
                            }

//                                                        Debug.Log("Generate facade " + p + " " + dMesh.vertexCount  );
                        }

//                        Debug.Log("fac "+p);
                        if (facade != null && (meshType == BuildingMeshTypes.Full || colliderType == BuildingColliderTypes.Primitive || colliderType == BuildingColliderTypes.Complex))
                        {
                            //generate the facade
//                            Debug.Log("full");
                            FacadeGenerator.FacadeData fData = new FacadeGenerator.FacadeData();
                            //                            fData.building = building;
                            //                            fData.volume = volume;
                            fData.baseA        = p0;
                            fData.baseB        = p1;
                            fData.controlA     = cw0;
                            fData.controlB     = cw1;
                            fData.anchors      = anchorPoints[p];
                            fData.isStraight   = isStraight;
                            fData.curveStyle   = volume[p].curveStyle;
                            fData.floorCount   = volume.floors;
                            fData.facadeDesign = facade;
                            //                            fData.submeshList = usedFloorplanSurfaces;
                            fData.startFloor            = BuildRFacadeUtil.MinimumFloor(building, volume, p);
                            fData.actualStartFloor      = building.VolumeBaseFloor(volume);
                            fData.foundationDepth       = foundation;
                            fData.foundationSurface     = building.foundationSurface;
                            fData.wallThickness         = volume.wallThickness;
                            fData.minimumWallUnitLength = volume.minimumWallUnitLength;
                            fData.floorHeight           = volume.floorHeight;
                            fData.floors       = volume.floors;
                            fData.meshType     = building.meshType;
                            fData.colliderType = building.colliderType;
                            fData.cullDoors    = building.cullDoors;
                            fData.prefabs      = volume.prefabs;

//                            Debug.Log("mesh");
                            FacadeGenerator.GenerateFacade(fData, dMesh, cMesh);
//                            Debug.Log("pref");
                            FacadeGenerator.GeneratePrefabs(fData);
//                                                        Debug.Log("Generate facade "+p+" "+dMesh.vertexCount);
                        }
                    }
                }

                #endregion

                #region Interiors

//                Debug.Log("int");
                bool generateInteriors = building.generateInteriors && meshType == BuildingMeshTypes.Full;
                if (generateInteriors)
                {
                    int          floors     = volume.floors;
                    IFloorplan[] floorplans = volume.InteriorFloorplans();
                    for (int fl = 0; fl < floors; fl++)
                    {
                        IFloorplan     floorplan   = floorplans[fl];
                        IVisualPart    floorVisual = floorplan.visualPart;
                        BuildRMesh     flMesh      = floorVisual.dynamicMesh;
                        BuildRCollider flCollider  = floorVisual.colliderMesh;
                        flMesh.Clear();
                        flCollider.Clear();
                        flCollider.TogglePrimitives(colliderType == BuildingColliderTypes.Primitive);
                        FloorplanGenerator.Generate(building, volume, floorplans[fl], fl, volumeOpenings, flMesh, flCollider);
                        floorVisual.GenerateFromDynamicMesh();
                        floorplan.transform.localPosition   = Vector3.up * (fl * volume.floorHeight);
                        floorVisual.transform.localPosition = Vector3.zero;//
                        floorVisual.transform.localRotation = Quaternion.identity;
                    }
                }
                else
                {
                    IFloorplan[] floorplans = volume.InteriorFloorplans();
                    int          floors     = floorplans.Length;
                    for (int fl = 0; fl < floors; fl++)
                    {
                        floorplans[fl].visualPart.Clear();
                    }
                }

                #endregion

                #region Volume Underside Generation

//                Debug.Log("und");
                BuildRVolumeUtil.VolumeShape[] underShapes = BuildRVolumeUtil.GetBottomShape(building, volume);
                int   underShapeCount  = underShapes.Length;
                float volumeBaseHeight = volume.baseHeight - building.foundationDepth;
                for (int u = 0; u < underShapeCount; u++)
                {
                    if (underShapes[u].outer == null)
                    {
                        continue;                             //no underside shape
                    }
                    int undersideSubmesh = dMesh.submeshLibrary.SubmeshAdd(volume.undersideSurafce);
                    Poly2TriWrapper.BMesh(dMesh, volumeBaseHeight, null, undersideSubmesh, underShapes[u].outer, new Rect(0, 0, 0, 0), false, underShapes[u].holes);
                }

                #endregion

//                Debug.Log("roof");
                if (building.generateExteriors)
                {
                    RoofGenerator.Generate(building, volume, dMesh, cMesh);
                    visual.GenerateFromDynamicMesh();
                }
                else
                {
                    visual.Clear();
                }

//                Debug.Log("mat");
                switch (meshType)
                {
                case BuildingMeshTypes.None:
                    visual.materials = null;
                    break;

                case BuildingMeshTypes.Box:
                    visual.materials = new[] { new Material(Shader.Find("Standard")) };
                    break;

                case BuildingMeshTypes.Simple:
                    facadeTexture.filterMode = FilterMode.Bilinear;
                    facadeTexture.Apply(true, false);
                    Material simpleMaterial = new Material(Shader.Find("Standard"));
                    simpleMaterial.mainTexture = facadeTexture;
                    visual.materials           = new[] { simpleMaterial };
                    break;

                case BuildingMeshTypes.Full:
                    visual.materials = dMesh.materials.ToArray();
                    break;
                }
            }
        }
        public static void Generate(IBuilding building)
        {
            int numberOfVolumes = building.numberOfPlans;

            for (int v = 0; v < numberOfVolumes; v++)
            {
                IVolume volume = building[v];
                volume.CheckVolume();
                if (!volume.isLegal)
                {
                    GenerateMesh.ClearVisuals(volume);
                    continue;
                }
                int     numberOfPoints  = volume.numberOfPoints;
                float   totalPlanHeight = volume.planHeight;
                Vector3 planUp          = totalPlanHeight * Vector3.up;
//                List<Surface> usedFloorplanSurfaces = volume.CalculateSurfaceArray();
                //                VerticalOpening[] volumeOpenings = BuildrUtils.GetOpeningsQuick(building, volume);

                IVisualPart           visual       = volume.visualPart;
                BuildRMesh            dMesh        = visual.dynamicMesh;
                BuildRCollider        cMesh        = visual.colliderMesh;
                BuildingMeshTypes     meshType     = building.meshType;
                BuildingColliderTypes colliderType = building.colliderType;
                dMesh.Clear();
                dMesh.ignoreSubmeshAssignment = true;
                cMesh.Clear();
                cMesh.TogglePrimitives(colliderType == BuildingColliderTypes.Primitive);
                cMesh.thickness = volume.wallThickness;

                if (meshType == BuildingMeshTypes.None && colliderType == BuildingColliderTypes.None)
                {
                    visual.Clear();
                    return;
                }

                Dictionary <int, List <Vector2Int> > anchorPoints = volume.facadeWallAnchors;
                Texture2D facadeTexture   = null;
                Rect[]    faciaRectangles = null;
                Rect[]    faciaUVs        = null;
                Rect      roofRect        = new Rect();
                Rect      roofPixelRect   = new Rect();

                #region Exteriors

                if (building.generateExteriors)
                {
                    //                    List<Rect> faciaRectangles = null;
                    faciaRectangles = new Rect[numberOfPoints + 1];                                  //one additional for the roof
                    float foundation = building.IsBaseVolume(volume) ? building.foundationDepth : 0; //set suspended volumes foundation to 0

                    //                    faciaRectangles = new List<Rect>();
                    for (int p = 0; p < numberOfPoints; p++)
                    {
                        if (!volume[p].render)
                        {
                            continue;
                        }
                        int        indexA = p;
                        int        indexB = (p < numberOfPoints - 1) ? p + 1 : 0;
                        Vector2Int p0     = volume[indexA].position;
                        Vector2Int p1     = volume[indexB].position;

                        float facadeWidth = Vector2Int.DistanceWorld(p0, p1) * PIXELS_PER_METER;
                        int   floorBase   = BuildRFacadeUtil.MinimumFloor(building, volume, indexA);

                        int numberOfFloors = volume.floors - floorBase;
                        if (numberOfFloors < 1)//no facade - adjacent facade is taller and covers this one
                        {
                            continue;
                        }

                        float floorHeight  = volume.floorHeight;
                        float facadeHeight = ((volume.floors - floorBase) * floorHeight) * PIXELS_PER_METER;
                        if (facadeHeight < 0)//??
                        {
                            facadeWidth  = 0;
                            facadeHeight = 0;
                        }

                        Rect newFacadeRect = new Rect(0, 0, facadeWidth, facadeHeight);
                        faciaRectangles[p] = newFacadeRect;
                        //                        Debug.Log(newFacadeRect);
                        //                        faciaRectangles.Add(newFacadeRect);
                    }

                    roofRect      = new Rect(0, 0, volume.bounds.size.x, volume.bounds.size.z);
                    roofPixelRect = new Rect(0, 0, volume.bounds.size.x * PIXELS_PER_METER, volume.bounds.size.z * PIXELS_PER_METER);
                    faciaRectangles[numberOfPoints] = roofPixelRect;
                    //                    Debug.Log(roofRect);

                    int currentWidth = RectanglePack.Pack(faciaRectangles, ATLAS_PADDING);
                    currentWidth  = RectanglePack.CheckMaxScale(faciaRectangles, currentWidth, MAXIMUM_TEXTURESIZE);
                    faciaUVs      = RectanglePack.ConvertToUVSpace(faciaRectangles, currentWidth);
                    facadeTexture = new Texture2D(currentWidth, currentWidth);


                    //                    float uvOffsetX = 0;
                    int rectIndex = 0;
                    for (int p = 0; p < numberOfPoints; p++)
                    {
                        if (!volume[p].render)
                        {
                            continue;
                        }

                        Vector3 p0 = volume.BuildingPoint(p);
                        Vector3 p1 = volume.BuildingPoint((p + 1) % numberOfPoints);

                        Vector3 p0u        = p0 + planUp;
                        Vector3 p1u        = p1 + planUp;
                        Vector3 cw0        = volume.BuildingControlPointA(p);
                        Vector3 cw1        = volume.BuildingControlPointB(p);
                        Facade  facade     = volume.GetFacade(p);
                        bool    isStraight = volume.IsWallStraight(p);

                        Vector3 facadeVector    = p1 - p0;
                        Vector3 facadeDirection = facadeVector.normalized;

                        FacadeGenerator.FacadeData fData = new FacadeGenerator.FacadeData();
                        fData.baseA        = p0;
                        fData.baseB        = p1;
                        fData.controlA     = cw0;
                        fData.controlB     = cw1;
                        fData.anchors      = anchorPoints[p];
                        fData.isStraight   = isStraight;
                        fData.curveStyle   = volume[p].curveStyle;
                        fData.floorCount   = volume.floors;
                        fData.facadeDesign = facade;

                        fData.wallThickness         = volume.wallThickness;
                        fData.minimumWallUnitLength = volume.minimumWallUnitLength;
                        fData.floorHeight           = volume.floorHeight;
                        fData.floors       = volume.floors;
                        fData.meshType     = building.meshType;
                        fData.colliderType = building.colliderType;
                        fData.cullDoors    = building.cullDoors;
                        fData.prefabs      = volume.prefabs;
                        //                        fData.submeshList = usedFloorplanSurfaces;
                        fData.startFloor = BuildRFacadeUtil.MinimumFloor(building, volume, p);

                        if (isStraight)
                        {
                            Vector3 normal  = Vector3.Cross(Vector3.up, facadeDirection);
                            Vector4 tangent = BuildRMesh.CalculateTangent(facadeDirection);

                            Vector3 fp2 = p0;
                            Vector3 fp3 = p1;
                            Vector3 fp0 = fp2 + Vector3.down * foundation;
                            Vector3 fp1 = fp3 + Vector3.down * foundation;

                            if (meshType == BuildingMeshTypes.Simple)
                            {
                                //                                if(facade != null)
                                //                                {
                                if (facade != null)
                                {
                                    SimpleTextureGenerator.GenerateFacade(fData, facadeTexture, faciaRectangles[rectIndex]);
                                }
                                Vector3[] verts  = { p0, p1, p0u, p1u };
                                Vector2[] uvs    = new Vector2[4];
                                Rect      uvRect = faciaUVs[rectIndex];
                                uvs[0] = new Vector2(uvRect.xMin, uvRect.yMin);
                                uvs[1] = new Vector2(uvRect.xMax, uvRect.yMin);
                                uvs[2] = new Vector2(uvRect.xMin, uvRect.yMax);
                                uvs[3] = new Vector2(uvRect.xMax, uvRect.yMax);
                                int[]     tris     = { 0, 2, 1, 1, 2, 3 };
                                Vector3[] norms    = { normal, normal, normal, normal };
                                Vector4[] tangents = { tangent, tangent, tangent, tangent };
                                dMesh.AddData(verts, uvs, tris, norms, tangents, 0);

                                if (foundation > Mathf.Epsilon)
                                {
                                    dMesh.AddPlane(fp0, fp1, fp2, fp3, uvs[0], uvs[0], normal, tangent, 0, null);
                                }
                            }
                            else
                            {
                                dMesh.AddPlane(p0, p1, p0u, p1u, normal, tangent, 0);

                                if (foundation > Mathf.Epsilon)
                                {
                                    dMesh.AddPlane(fp0, fp1, fp2, fp3, normal, tangent, 0);
                                }
                            }

                            if (colliderType != BuildingColliderTypes.None)
                            {
                                cMesh.AddPlane(p0, p1, p0u, p1u);
                                if (foundation > Mathf.Epsilon)
                                {
                                    cMesh.mesh.AddPlane(fp0, fp1, fp2, fp3, 0);
                                }
                            }
                        }
                        else
                        {
                            List <Vector2Int> facadeAnchorPoints = anchorPoints[p];
                            int anchorCount = facadeAnchorPoints.Count;
                            for (int i = 0; i < anchorCount - 1; i++)
                            {
                                Vector3 c0 = facadeAnchorPoints[i].vector3XZ;
                                c0.y = p0.y;
                                Vector3 c1 = facadeAnchorPoints[i + 1].vector3XZ;
                                c1.y = p0.y;
                                Vector3 c2 = c0 + planUp;
                                Vector3 c3 = c1 + planUp;
                                Vector3 sectionDirection = (c1 - c0).normalized;
                                Vector3 normal           = Vector3.Cross(Vector3.up, sectionDirection);
                                Vector4 tangent          = BuildRMesh.CalculateTangent(sectionDirection);

                                Vector3 fp2 = c0;
                                Vector3 fp3 = c1;
                                Vector3 fp0 = fp2 + Vector3.down * foundation;
                                Vector3 fp1 = fp3 + Vector3.down * foundation;

                                if (meshType == BuildingMeshTypes.Simple)
                                {
                                    if (facade != null)
                                    {
                                        SimpleTextureGenerator.GenerateFacade(fData, facadeTexture, faciaRectangles[rectIndex]);
                                    }
                                    Rect      uvRect         = faciaUVs[rectIndex];
                                    float     facadePercentA = i / (float)(anchorCount - 1);
                                    float     facadePercentB = (i + 1) / (float)(anchorCount - 1);
                                    float     uvxa           = uvRect.xMin + uvRect.width * facadePercentA;
                                    float     uvxb           = uvRect.xMin + uvRect.width * facadePercentB;
                                    Vector3[] verts          = { c0, c1, c2, c3 };
                                    Vector2[] uvs            = new Vector2[4];
                                    uvs[0] = new Vector2(uvxa, uvRect.yMin);
                                    uvs[1] = new Vector2(uvxb, uvRect.yMin);
                                    uvs[2] = new Vector2(uvxa, uvRect.yMax);
                                    uvs[3] = new Vector2(uvxb, uvRect.yMax);
                                    int[]     tris     = { 0, 2, 1, 1, 2, 3 };
                                    Vector3[] norms    = { normal, normal, normal, normal };
                                    Vector4[] tangents = { tangent, tangent, tangent, tangent };
                                    //                                        Vector2 uvMin = new Vector2(uvOffsetX, 0);
                                    //                                        Vector2 uvMax = new Vector2(uvOffsetX + facadeLength, totalPlanHeight);

                                    dMesh.AddData(verts, uvs, tris, norms, tangents, 0);
                                    //                                    dMesh.AddPlane(p0, p1, p0u, p1u, uvMin, uvMax, normal, tangent, 0);
                                    //todo simple mesh with textured facade
                                    //                                    rectIndex++;

                                    if (foundation > Mathf.Epsilon)
                                    {
                                        dMesh.AddPlane(fp0, fp1, fp2, fp3, uvs[0], uvs[0], normal, tangent, 0, null);
                                    }
                                }
                                else
                                {
                                    dMesh.AddPlane(p0, p1, p0u, p1u, normal, tangent, 0);

                                    if (foundation > Mathf.Epsilon)
                                    {
                                        dMesh.AddPlane(fp0, fp1, fp2, fp3, normal, tangent, 0);
                                    }
                                }

                                if (colliderType != BuildingColliderTypes.None)
                                {
                                    cMesh.AddPlane(c0, c1, c2, c3);

                                    if (foundation > Mathf.Epsilon)
                                    {
                                        cMesh.mesh.AddPlane(fp0, fp1, fp2, fp3, 0);
                                    }
                                }
                            }
                        }
                        rectIndex++;
                    }
                }

                #endregion

                #region Interiors

                IFloorplan[] floorplans = volume.InteriorFloorplans();
                int          floors     = volume.floors;
                for (int fl = 0; fl < floors; fl++)
                {
                    floorplans[fl].visualPart.Clear();
                }

                #endregion

                #region Volume Underside Generation

                BuildRVolumeUtil.VolumeShape[] underShapes = BuildRVolumeUtil.GetBottomShape(building, volume);
                int underShapeCount = underShapes.Length;
                //                Debug.Log(underShapeCount);
                float volumeBaseHeight = volume.baseHeight;
                for (int u = 0; u < underShapeCount; u++)
                {
                    //                    Debug.Log(underShapes[u].outer);
                    if (underShapes[u].outer == null)
                    {
                        continue;                              //no underside shape
                    }
                    //                    Debug.Log(underShapes[u].outer.Length);

                    Poly2TriWrapper.BMesh(dMesh, volumeBaseHeight, null, 0, underShapes[u].outer, new Rect(0, 0, 0, 0), false, underShapes[u].holes);
                }

                #endregion

                if (building.generateExteriors)
                {
                    Surface roofSurface = volume.roof.mainSurface;
                    if (roofSurface != null)
                    {
                        SimpleTextureGenerator.GenerateTexture(facadeTexture, roofSurface, faciaRectangles[faciaRectangles.Length - 1], roofRect);
                    }
                    RoofGenerator.Generate(building, volume, dMesh, cMesh, faciaUVs[faciaUVs.Length - 1]);
                    visual.GenerateFromDynamicMesh();
                }
                else
                {
                    visual.Clear();
                }

                switch (meshType)
                {
                case BuildingMeshTypes.Box:
                    visual.materials = new[] { new Material(Shader.Find("Standard")) };
                    break;

                case BuildingMeshTypes.Simple:
                    facadeTexture.filterMode = FilterMode.Bilinear;
                    facadeTexture.Apply(true, false);
                    Material simpleMaterial = new Material(Shader.Find("Standard"));
                    simpleMaterial.mainTexture = facadeTexture;
                    visual.materials           = new[] { simpleMaterial };
                    break;
                }
            }
        }