Пример #1
0
    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);
    }
Пример #2
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();
            }
        }
    }
Пример #3
0
    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);
        }
    }
Пример #4
0
    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));
            }
        }
    }