Example #1
0
    public int AddVolume()
    {
        BuildrVolume newVolume = ScriptableObject.CreateInstance <BuildrVolume>();

        newVolume.numberOfFloors = Mathf.FloorToInt(newVolume.height / BuildrMeasurements.FLOOR_HEIGHT_MIN);
        volumes.Add(newVolume);
        newVolume.styles = ScriptableObject.CreateInstance <BuildrVolumeStyles>();
        return(numberOfVolumes - 1);
    }
Example #2
0
    public void SplitVolume(int volumeIndexA, int pointIndexA, int pointIndexB)
    {
        //add second volume
        int          volumeIndexB      = AddVolume();
        BuildrVolume volumeA           = volumes[volumeIndexA];
        BuildrVolume volumeB           = volumes[volumeIndexB];
        int          volumeASize       = volumeA.Count;
        int          volumePointIndexA = volumeA.IndexOf(pointIndexA);
        int          volumePointIndexB = volumeA.IndexOf(pointIndexB);

        //switchy
        if (volumePointIndexB < volumePointIndexA)
        {
            volumePointIndexA = volumeA.IndexOf(pointIndexB);
            volumePointIndexB = volumeA.IndexOf(pointIndexA);
            pointIndexA       = volumeA.points[volumePointIndexA];
            pointIndexB       = volumeA.points[volumePointIndexB];
        }

        List <int> pointIndices = new List <int>();

        for (int i = 0; i < volumeASize; i++)
        {
            pointIndices.Add(volumeA.points[i]);

            if (i == volumePointIndexA)
            {
                i = volumePointIndexB;
                pointIndices.Add(volumeA.points[i]);
            }
        }

        //Add the points from the first volume to the new volume
        for (int i = 0; i < volumeASize; i++)
        {
            int facadeIndex = volumeA.points[i];
            if (!pointIndices.Contains(facadeIndex) || facadeIndex == pointIndexA || facadeIndex == pointIndexB)
            {
                BuildrVolumeStylesUnit[] styleUnits = volumeA.styles.GetContentsByFacade(facadeIndex);
                volumeB.Add(facadeIndex, styleUnits);
            }
        }

        //Remove point from the first volume
        for (int i = 0; i < volumeASize; i++)
        {
            int pointIndex = volumeA.points[i];
            if (!pointIndices.Contains(pointIndex))
            {
                volumeA.Remove(pointIndex);
                volumeASize--;
                i--;
            }
        }
    }
Example #3
0
    private static int[] ExportStairwells(BuildrData data)
    {
        int numberOfVolumes = data.plan.numberOfVolumes;

        int[] returnNumberOfMeshes = new int[numberOfVolumes];

        for (int v = 0; v < numberOfVolumes; v++)
        {
            BuildrVolume volume = data.plan.volumes[v];

            int numberOfUnpackedTextures         = data.textures.Count;
            List <ExportMaterial> exportTextures = new List <ExportMaterial>();

            if (!volume.generateStairs)
            {
                continue;
            }
            DynamicMeshGenericMultiMaterialMesh INT_STAIRWELL = new DynamicMeshGenericMultiMaterialMesh();
            INT_STAIRWELL.subMeshCount = data.textures.Count;
            BuildrStairs.Build(INT_STAIRWELL, data, v, BuildrStairs.StairModes.Stepped, true);
            INT_STAIRWELL.Build(data.includeTangents);

            List <int> unusedStairTextures = INT_STAIRWELL.unusedSubmeshes;
            numberOfUnpackedTextures = data.textures.Count;
            for (int t = 0; t < numberOfUnpackedTextures; t++)
            {
                if (unusedStairTextures.Contains(t))
                {
                    continue;//skip, unused
                }
                ExportMaterial newTexture = new ExportMaterial();
                newTexture.name      = data.textures[t].name;
                newTexture.material  = data.textures[t].material;
                newTexture.generated = false;
                newTexture.filepath  = data.textures[t].filePath;
                exportTextures.Add(newTexture);
            }

            int numberOfStairMeshes = INT_STAIRWELL.meshCount;
            for (int i = 0; i < numberOfStairMeshes; i++)
            {
                MeshUtility.Optimize(INT_STAIRWELL[i].mesh);
                string VolumeSuffix      = ((numberOfVolumes > 1) ? "_" + v : "");
                string DetailSuffixIndex = ((numberOfStairMeshes > 1) ? "_" + i : "");
                string DetailFileName    = data.exportFilename + STAIR_SUFFIX + VolumeSuffix + DetailSuffixIndex;
                string DetailFolder      = ROOT_FOLDER + data.exportFilename + "/";
                Export(DetailFileName, DetailFolder, data, INT_STAIRWELL[i].mesh, exportTextures.ToArray());
            }

            returnNumberOfMeshes[v] = numberOfStairMeshes;
        }

        return(returnNumberOfMeshes);
    }
Example #4
0
    private static void ImportVolumes(XmlDocument xml, BuildrData data)
    {
        foreach(XmlNode node in xml.SelectNodes("buildr/plan/volumes/volume"))
        {
            BuildrVolume volume = ScriptableObject.CreateInstance<BuildrVolume>();
            BuildrVolumeStyles styles = ScriptableObject.CreateInstance<BuildrVolumeStyles>();
            data.plan.volumes.Add(volume);

            foreach(XmlNode pointnode in node.SelectNodes("points/point"))
            {
                volume.points.Add(int.Parse(pointnode.FirstChild.Value));
            }
            foreach(XmlNode pointnode in node.SelectNodes("facades/render"))
            {
                volume.renderFacade.Add(pointnode.FirstChild.Value == valueTrue);
            }
            volume.height = float.Parse(node["height"].FirstChild.Value);
            volume.numberOfFloors = int.Parse(node["numberoffloors"].FirstChild.Value);
            volume.roofDesignID = int.Parse(node["roofdesignid"].FirstChild.Value);

            foreach(XmlNode stylenode in node.SelectNodes("styles/style"))
            {
                int styleID = int.Parse(stylenode["styleid"].FirstChild.Value);
                int facadeID = int.Parse(stylenode["facadeid"].FirstChild.Value);
                int floors = int.Parse(stylenode["floors"].FirstChild.Value);
                styles.AddStyle(styleID, facadeID, floors);
            }
            volume.styles = styles;


            volume.generateStairs = bool.Parse(node["generateStairs"].FirstChild.Value);
            volume.staircaseWidth = float.Parse(node["staircaseWidth"].FirstChild.Value);
            volume.stepHeight = float.Parse(node["stepHeight"].FirstChild.Value);
            volume.stairwellCeilingTexture = int.Parse(node["stairwellCeilingTexture"].FirstChild.Value);
            volume.stairwellFloorTexture = int.Parse(node["stairwellFloorTexture"].FirstChild.Value);
            volume.stairwellStepTexture = int.Parse(node["stairwellStepTexture"].FirstChild.Value);
            volume.stairwellWallTexture = int.Parse(node["stairwellWallTexture"].FirstChild.Value);
            volume.numberOfBasementFloors = int.Parse(node["numberOfBasementFloors"].FirstChild.Value);

            int itemCount = 0;
            foreach (XmlNode basementNode in node.SelectNodes("basementtextures/basementfloortextures"))
            {
                volume.FloorTexture(itemCount, int.Parse(basementNode["FloorTexture"].FirstChild.Value));
                volume.WallTexture(itemCount, int.Parse(basementNode["WallTexture"].FirstChild.Value));
                volume.CeilingTexture(itemCount, int.Parse(basementNode["CeilingTexture"].FirstChild.Value));
                itemCount++;
            }
        }
    }
Example #5
0
    public void RemoveRoofDesign(BuildrRoofDesign roof)
    {
        roofs.Remove(roof);
        int bRoofIndex      = roofs.IndexOf(roof);
        int numberOfVolumes = plan.numberOfVolumes;

        for (int s = 0; s < numberOfVolumes; s++)
        {
            BuildrVolume volume = plan.volumes[s];
            if (volume.roofDesignID >= bRoofIndex && volume.roofDesignID > 0)
            {
                volume.roofDesignID--;
            }
        }
    }
Example #6
0
    private static void Steeple(BuildrVolume volume, BuildrRoofDesign design)
    {
        BuildrPlan area = data.plan;
        int numberOfFloors = volume.numberOfFloors;
        float floorHeight = data.floorHeight;
        Vector3 volumeFloorHeight = Vector3.up * (numberOfFloors * floorHeight);
        Vector3 ridgeVector = Vector3.up * design.height;

        int numberOfVolumePoints = volume.points.Count;
        Vector3[] basePoints = new Vector3[numberOfVolumePoints];
        Vector3 centrePoint = Vector3.zero;
        for (int l = 0; l < numberOfVolumePoints; l++)
        {
            basePoints[l] = area.points[volume.points[l]].vector3 + volumeFloorHeight;
            centrePoint += area.points[volume.points[l]].vector3;
        }
        centrePoint = (centrePoint / numberOfVolumePoints) + volumeFloorHeight + ridgeVector;
        for (int l = 0; l < numberOfVolumePoints; l++)
        {
            int pointIndexA = l;
            int pointIndexB = (l < numberOfVolumePoints - 1) ? l + 1 : 0;
            Vector3[] verts = new Vector3[3] { basePoints[pointIndexA], basePoints[pointIndexB], centrePoint };
            float uvWdith = Vector3.Distance(basePoints[pointIndexA], basePoints[pointIndexB]);
            float uvHeight = design.height;
            int subMesh = design.GetTexture(BuildrRoofDesign.textureNames.tiles);
            BuildrTexture texture = textures[subMesh];

            if (texture.tiled)
            {
                uvWdith *= (1.0f / texture.textureUnitSize.x);
                uvHeight *= (1.0f / texture.textureUnitSize.y);
                if (texture.patterned)
                {
                    Vector2 uvunits = texture.tileUnitUV;
                    uvWdith = Mathf.Ceil(uvWdith / uvunits.x) * uvunits.x;
                    uvHeight = Mathf.Ceil(uvHeight / uvunits.y) * uvunits.y;
                }
            }
            else
            {
                uvWdith = texture.tiledX;
                uvHeight = texture.tiledY;
            }
            Vector2[] uvs = new Vector2[3] { new Vector2(-uvWdith / 2, 0), new Vector2(uvWdith / 2, 0), new Vector2(0, uvHeight) };
            int[] tri = new int[3] { 1, 0, 2 };
            AddData(verts, uvs, tri, subMesh);
        }
    }
Example #7
0
    public void RemovePoint(int removePointIndex)
    {
        points.RemoveAt(removePointIndex);
        int volumeCount = numberOfVolumes;

        for (int v = 0; v < volumeCount; v++)
        {
            volumes[v].RemoveAndUpdate(removePointIndex);
        }
        for (int v = 0; v < volumeCount; v++)
        {
            BuildrVolume volume = volumes[v];
            if (volume.Count < 3)
            {
                RemoveVolume(volume);
                volumeCount--;
                v--;
            }
        }
        CleanUpVolumes();
    }
Example #8
0
    private static void FlatRoof(BuildrVolume volume, BuildrRoofDesign design)
    {
        BuildrPlan area = data.plan;
        int volumeIndex = area.volumes.IndexOf(volume);
        int numberOfVolumePoints = volume.points.Count;
        int numberOfFloors = volume.numberOfFloors;
        float floorHeight = data.floorHeight;
        Vector3 volumeFloorHeight = Vector3.up * (numberOfFloors * floorHeight);

        //add top base of the flat roof
        Vector3[] newEndVerts = new Vector3[numberOfVolumePoints];
        Vector2[] newEndUVs = new Vector2[numberOfVolumePoints];
        int[] tris = new List<int>(area.GetTrianglesBySectorBase(volumeIndex)).ToArray();
        int roofTextureID = design.GetTexture(BuildrRoofDesign.textureNames.floor);
        BuildrTexture texture = data.textures[roofTextureID];
        for (int i = 0; i < numberOfVolumePoints; i++)
        {
            Vector2z point = area.points[volume.points[i]];
            newEndVerts[i] = point.vector3 + volumeFloorHeight;
            newEndUVs[i] = new Vector2(point.vector2.x / texture.textureUnitSize.x, point.vector2.y / texture.textureUnitSize.y);
        }

        AddData(newEndVerts, newEndUVs, tris, design.GetTexture(BuildrRoofDesign.textureNames.floor));
    }
Example #9
0
    public void UpdateInteriors()
    {
        while (interiorMeshHolders.Count > 0)
        {
            GameObject destroyOld = interiorMeshHolders[0];
            interiorMeshHolders.RemoveAt(0);
            DestroyImmediate(destroyOld);
        }

        interiorMeshes.Clear();

        if (data.renderInteriors)
        {
            int numberOfVolumes = data.plan.numberOfVolumes;
            for (int v = 0; v < numberOfVolumes; v++)
            {
                DynamicMeshGenericMultiMaterialMesh interiorMesh = new DynamicMeshGenericMultiMaterialMesh();
                interiorMesh.subMeshCount = data.textures.Count;
                BuildrVolume volume = _data.plan.volumes[v];
                BuildrInteriors.Build(interiorMesh, data, v);
                interiorMesh.Build(false);

                List <int>      unusedInteriorTextures    = interiorMesh.unusedSubmeshes;
                int             numberOfInteriorMaterials = data.textures.Count;
                List <Material> interiorMaterials         = new List <Material>();
                for (int m = 0; m < numberOfInteriorMaterials; m++)
                {
                    if (unusedInteriorTextures.Contains(m))
                    {
                        continue;//skip, unused
                    }
                    BuildrTexture bTexture = data.textures[m];
                    interiorMaterials.Add(bTexture.usedMaterial);
                }

                int numberOfInteriorMeshes = interiorMesh.meshCount;
                for (int i = 0; i < numberOfInteriorMeshes; i++)
                {
                    string meshName = "model interior";
                    if (numberOfVolumes > 0)
                    {
                        meshName += " volume " + (v + 1);
                    }
                    if (numberOfInteriorMeshes > 1)
                    {
                        meshName += " mesh " + (i + 1);
                    }
                    GameObject newMeshHolder = new GameObject(meshName);
                    newMeshHolder.transform.parent        = transform;
                    newMeshHolder.transform.localPosition = Vector3.zero;
                    meshFilt      = newMeshHolder.AddComponent <MeshFilter>();
                    meshRend      = newMeshHolder.AddComponent <MeshRenderer>();
                    meshFilt.mesh = interiorMesh[i].mesh;
                    interiorMeshHolders.Add(newMeshHolder);

                    int numberOfInterior = interiorMeshHolders.Count;
                    for (int m = 0; m < numberOfInterior; m++)
                    {
                        meshRend.sharedMaterials = interiorMaterials.ToArray();
                    }
                }
                interiorMeshes.Add(interiorMesh);

                if (!volume.generateStairs)
                {
                    continue;
                }

                DynamicMeshGenericMultiMaterialMesh stairwellMesh = new DynamicMeshGenericMultiMaterialMesh();
                stairwellMesh.subMeshCount = data.textures.Count;
                BuildrStairs.Build(stairwellMesh, data, v, BuildrStairs.StairModes.Stepped, true);
                stairwellMesh.Build(false);


                List <int>      unusedStairTextures    = stairwellMesh.unusedSubmeshes;
                int             numberOfStairMaterials = data.textures.Count;
                List <Material> stairMaterials         = new List <Material>();
                for (int m = 0; m < numberOfStairMaterials; m++)
                {
                    if (unusedStairTextures.Contains(m))
                    {
                        continue;//skip, unused
                    }
                    BuildrTexture bTexture = data.textures[m];
                    stairMaterials.Add(bTexture.usedMaterial);
                }

                int numberOfStairMeshes = stairwellMesh.meshCount;
                for (int i = 0; i < numberOfStairMeshes; i++)
                {
                    string meshName = "model stairs";
                    if (numberOfVolumes > 0)
                    {
                        meshName += " volume " + (v + 1);
                    }
                    if (numberOfStairMeshes > 1)
                    {
                        meshName += " mesh " + (i + 1);
                    }
                    GameObject newMeshHolder = new GameObject(meshName);
                    newMeshHolder.transform.parent        = transform;
                    newMeshHolder.transform.localPosition = volume.stairBaseVector[i];
                    meshFilt      = newMeshHolder.AddComponent <MeshFilter>();
                    meshRend      = newMeshHolder.AddComponent <MeshRenderer>();
                    meshFilt.mesh = stairwellMesh[i].mesh;
                    interiorMeshHolders.Add(newMeshHolder);
                    meshRend.sharedMaterials = stairMaterials.ToArray();
                }
                interiorMeshes.Add(stairwellMesh);
            }
        }
    }
Example #10
0
    private static void LeanTo(BuildrVolume volume, BuildrRoofDesign design)
    {
        BuildrPlan area = data.plan;
        int numberOfFloors = volume.numberOfFloors;
        float floorHeight = data.floorHeight;
        Vector3 volumeFloorHeight = Vector3.up * (numberOfFloors * floorHeight);
        Vector3 ridgeVector = Vector3.up * design.height;

        int[] pointIndexes = new int[4];
        switch (design.direction)
        {
            case 0:
                pointIndexes = new int[4] { 0, 1, 2, 3 };
                break;
            case 1:
                pointIndexes = new int[4] { 1, 2, 3, 0 };
                break;
            case 2:
                pointIndexes = new int[4] { 2, 3, 0, 1 };
                break;
            case 3:
                pointIndexes = new int[4] { 3, 0, 1, 2 };
                break;
        }
        Vector3[] points = new Vector3[6];
        points[0] = area.points[volume.points[pointIndexes[0]]].vector3 + volumeFloorHeight;
        points[1] = area.points[volume.points[pointIndexes[1]]].vector3 + volumeFloorHeight;
        points[2] = area.points[volume.points[pointIndexes[2]]].vector3 + volumeFloorHeight;
        points[3] = area.points[volume.points[pointIndexes[3]]].vector3 + volumeFloorHeight;
        points[4] = area.points[volume.points[pointIndexes[2]]].vector3 + volumeFloorHeight + ridgeVector;
        points[5] = area.points[volume.points[pointIndexes[3]]].vector3 + volumeFloorHeight + ridgeVector;

        //top
        int subMeshTop = design.GetTexture(BuildrRoofDesign.textureNames.tiles);
        bool flippedTop = design.IsFlipped(BuildrRoofDesign.textureNames.tiles);
        AddPlane(design, points[0], points[1], points[5], points[4], subMeshTop, flippedTop);

        //window
        int subMeshWindow = design.GetTexture(BuildrRoofDesign.textureNames.window);
        bool flippedWindow = design.IsFlipped(BuildrRoofDesign.textureNames.window);
        AddPlane(design, points[2], points[3], points[4], points[5], subMeshWindow, flippedWindow);

        //sides
        Vector3[] vertsA = new Vector3[3] { points[1], points[2], points[4] };
        Vector3[] vertsB = new Vector3[3] { points[0], points[3], points[5] };
        float uvWdith = Vector3.Distance(points[0], points[3]);
        float uvHeight = design.height;
        int subMesh = design.GetTexture(BuildrRoofDesign.textureNames.wall);
        BuildrTexture texture = textures[subMesh];

        if (texture.tiled)
        {
            uvWdith *= (1.0f / texture.textureUnitSize.x);
            uvHeight *= (1.0f / texture.textureUnitSize.y);
            if (texture.patterned)
            {
                Vector2 uvunits = texture.tileUnitUV;
                uvWdith = Mathf.Ceil(uvWdith / uvunits.x) * uvunits.x;
                uvHeight = Mathf.Ceil(uvHeight / uvunits.y) * uvunits.y;
            }
        }
        else
        {
            uvWdith = texture.tiledX;
            uvHeight = texture.tiledY;
        }

        Vector2[] uvs = new Vector2[3] { new Vector2(0, 0), new Vector2(uvWdith, 0), new Vector2(uvWdith, uvHeight) };
        if (!design.IsFlipped(BuildrRoofDesign.textureNames.wall))
            uvs = new Vector2[3] { new Vector2(uvWdith, 0), new Vector2(0, 0), new Vector2(uvHeight, uvWdith / 2) };

        int[] triA = new int[3] { 1, 0, 2 };
        int[] triB = new int[3] { 0, 1, 2 };

        AddData(vertsA, uvs, triA, subMesh);
        AddData(vertsB, uvs, triB, subMesh);
    }
Example #11
0
    private static void BuildTextures()
    {
        List <TexturePaintObject> buildSourceTextures = new List <TexturePaintObject>();

        foreach (BuildrTexture btexture in data.textures)//Gather the source textures, resized into Color32 arrays
        {
            TexturePaintObject texturePaintObject = new TexturePaintObject();
            texturePaintObject.pixels = ((Texture2D)btexture.texture).GetPixels32();
            texturePaintObject.width  = btexture.texture.width;
            texturePaintObject.height = btexture.texture.height;
            texturePaintObject.tiles  = new Vector2(btexture.tiledX, btexture.tiledY);
            if (btexture.tiled)
            {
                int resizedTextureWidth  = Mathf.RoundToInt(btexture.textureUnitSize.x * PIXELS_PER_METER * packedScale);
                int resizedTextureHeight = Mathf.RoundToInt(btexture.textureUnitSize.y * PIXELS_PER_METER * packedScale);
                texturePaintObject.pixels = TextureScale.NearestNeighbourSample(texturePaintObject.pixels, texturePaintObject.width, texturePaintObject.height, resizedTextureWidth, resizedTextureHeight);
                texturePaintObject.width  = resizedTextureWidth;
                texturePaintObject.height = resizedTextureHeight;
            }
            else
            {
                texturePaintObject.tiled = false;
            }
            buildSourceTextures.Add(texturePaintObject);
        }
        LogTimer("Gather Source into Arrays");
        TexturePaintObject[] sourceTextures = buildSourceTextures.ToArray();
        textures = data.textures.ToArray();
        BuildrFacadeDesign facadeDesign = data.facades[0];
        BuildrPlan         plan         = data.plan;

        int numberOfVolumes = data.plan.numberOfVolumes;
        int facadeNumber    = 0;

        for (int s = 0; s < numberOfVolumes; s++)
        {
            BuildrVolume volume = plan.volumes[s];
            int          numberOfVolumePoints = volume.points.Count;

            for (int f = 0; f < numberOfVolumePoints; f++)
            {
                if (!volume.renderFacade[f])
                {
                    continue;
                }
                int     indexA, indexB;
                Vector3 p0, p1;
                indexA = f;
                indexB = (f < numberOfVolumePoints - 1) ? f + 1 : 0;
                p0     = plan.points[volume.points[indexA]].vector3;
                p1     = plan.points[volume.points[indexB]].vector3;
                Rect packedPosition = packedTexturePositions[facadeNumber];

                float facadeWidth    = Vector3.Distance(p0, p1);
                int   floorBase      = plan.GetFacadeFloorHeight(s, volume.points[indexA], volume.points[indexB]);
                int   numberOfFloors = volume.numberOfFloors - floorBase;
                if (numberOfFloors < 1)
                {
                    //no facade - adjacent facade is taller and covers this one
                    continue;
                }
                float floorHeight = data.floorHeight;

                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 bayBase          = Vector2.zero;
                float   currentFloorBase = 0;
                for (int r = 0; r < rows; r++)
                {
                    currentFloorBase = floorHeight * r;
                    int modFloor = (r % floorPatternSize);

                    facadeDesign = data.facades[styleUnits[facadePatternReference[modFloor]].styleID];

                    bool isBlankWall = !facadeDesign.hasWindows;
                    if (facadeDesign.type == BuildrFacadeDesign.types.patterned)
                    {
                        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[] bays;
                        int         numberOfBayDesigns = 0;
                        if (facadeDesign.type == BuildrFacadeDesign.types.patterned)
                        {
                            numberOfBayDesigns = facadeDesign.bayPattern.Count;
                            bays = new BuildrBay[numberOfBayDesigns];
                            for (int i = 0; i < numberOfBayDesigns; i++)
                            {
                                bays[i] = data.bays[facadeDesign.bayPattern[i]];
                            }
                        }
                        else
                        {
                            bays = 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 = bays[patternModIndex].openingWidth + bays[patternModIndex].minimumBayWidth;
                            if (patternSize + patternAddition < facadeWidth)
                            {
                                patternSize += patternAddition;
                                numberOfBays++;
                            }
                            else
                            {
                                break;
                            }
                            it--;
                            if (it < 0)
                            {
                                break;
                            }
                        }
                        float perBayAdditionalSpacing = (facadeWidth - patternSize) / numberOfBays;

                        float windowXBase = 0;
                        for (int c = 0; c < numberOfBays; c++)
                        {
                            BuildrBay bayStyle;
                            if (facadeDesign.type == BuildrFacadeDesign.types.patterned)
                            {
                                int numberOfBayStyles = facadeDesign.bayPattern.Count;
                                bayStyle = bays[c % numberOfBayStyles];
                            }
                            else
                            {
                                bayStyle = facadeDesign.simpleBay;
                            }
                            float actualWindowSpacing = bayStyle.minimumBayWidth + perBayAdditionalSpacing;
                            float leftSpace           = actualWindowSpacing * bayStyle.openingWidthRatio;
                            float rightSpace          = actualWindowSpacing - leftSpace;
                            float openingSpace        = bayStyle.openingWidth;

                            Vector3 bayDimensions;
                            int     subMesh;
                            bool    flipped;

                            if (!bayStyle.isOpening)
                            {
                                subMesh   = bayStyle.GetTexture(BuildrBay.TextureNames.WallTexture);
                                flipped   = bayStyle.IsFlipped(BuildrBay.TextureNames.WallTexture);
                                bayBase.x = windowXBase;
                                bayBase.y = currentFloorBase;
                                float bayWidth  = (openingSpace + actualWindowSpacing);
                                float bayHeight = floorHeight;
                                bayDimensions = new Vector2(bayWidth, bayHeight);
                                DrawFacadeTexture(sourceTextures, bayBase, bayDimensions, subMesh, flipped, packedPosition);

                                windowXBase += bayWidth; //move base vertor to next bay
                                continue;                //bay filled - move onto next bay
                            }

                            float rowBottomHeight = ((floorHeight - bayStyle.openingHeight) * bayStyle.openingHeightRatio);
                            float rowTopHeight    = (floorHeight - rowBottomHeight - bayStyle.openingHeight);

                            //Window
                            subMesh       = bayStyle.GetTexture(BuildrBay.TextureNames.OpeningBackTexture);
                            flipped       = bayStyle.IsFlipped(BuildrBay.TextureNames.OpeningBackTexture);
                            bayBase.x     = windowXBase + leftSpace;
                            bayBase.y     = currentFloorBase + rowBottomHeight;
                            bayDimensions = new Vector2(bayStyle.openingWidth, bayStyle.openingHeight);
                            DrawFacadeTexture(sourceTextures, bayBase, bayDimensions, subMesh, flipped, packedPosition);

                            //Column Left
                            if (leftSpace > 0)
                            {
                                subMesh       = bayStyle.GetTexture(BuildrBay.TextureNames.ColumnTexture);
                                flipped       = bayStyle.IsFlipped(BuildrBay.TextureNames.ColumnTexture);
                                bayBase.x     = windowXBase;
                                bayBase.y     = currentFloorBase + rowBottomHeight;
                                bayDimensions = new Vector2(leftSpace, bayStyle.openingHeight);
                                DrawFacadeTexture(sourceTextures, bayBase, bayDimensions, subMesh, flipped, packedPosition);
                            }

                            //Column Right
                            if (rightSpace > 0)
                            {
                                subMesh       = bayStyle.GetTexture(BuildrBay.TextureNames.ColumnTexture);
                                flipped       = bayStyle.IsFlipped(BuildrBay.TextureNames.ColumnTexture);
                                bayBase.x     = windowXBase + leftSpace + openingSpace;
                                bayBase.y     = currentFloorBase + rowBottomHeight;
                                bayDimensions = new Vector2(rightSpace, bayStyle.openingHeight);
                                DrawFacadeTexture(sourceTextures, bayBase, bayDimensions, subMesh, flipped, packedPosition);
                            }

                            //Row Bottom
                            if (rowBottomHeight > 0)
                            {
                                subMesh       = bayStyle.GetTexture(BuildrBay.TextureNames.RowTexture);
                                flipped       = bayStyle.IsFlipped(BuildrBay.TextureNames.RowTexture);
                                bayBase.x     = windowXBase + leftSpace;
                                bayBase.y     = currentFloorBase;
                                bayDimensions = new Vector2(openingSpace, rowBottomHeight);
                                DrawFacadeTexture(sourceTextures, bayBase, bayDimensions, subMesh, flipped, packedPosition);
                            }

                            //Row Top
                            if (rowTopHeight > 0)
                            {
                                subMesh       = bayStyle.GetTexture(BuildrBay.TextureNames.RowTexture);
                                flipped       = bayStyle.IsFlipped(BuildrBay.TextureNames.RowTexture);
                                bayBase.x     = windowXBase + leftSpace;
                                bayBase.y     = currentFloorBase + rowBottomHeight + bayStyle.openingHeight;
                                bayDimensions = new Vector2(openingSpace, rowTopHeight);
                                DrawFacadeTexture(sourceTextures, bayBase, bayDimensions, subMesh, flipped, packedPosition);
                            }

                            //Cross Left
                            if (leftSpace > 0)
                            {
                                //Cross Left Bottom
                                subMesh       = bayStyle.GetTexture(BuildrBay.TextureNames.CrossTexture);
                                flipped       = bayStyle.IsFlipped(BuildrBay.TextureNames.CrossTexture);
                                bayBase.x     = windowXBase;
                                bayBase.y     = currentFloorBase;
                                bayDimensions = new Vector2(leftSpace, rowBottomHeight);
                                DrawFacadeTexture(sourceTextures, bayBase, bayDimensions, subMesh, flipped, packedPosition);

                                //Cross Left Top
                                subMesh       = bayStyle.GetTexture(BuildrBay.TextureNames.CrossTexture);
                                flipped       = bayStyle.IsFlipped(BuildrBay.TextureNames.CrossTexture);
                                bayBase.x     = windowXBase;
                                bayBase.y     = currentFloorBase + rowBottomHeight + bayStyle.openingHeight;
                                bayDimensions = new Vector2(leftSpace, rowTopHeight);
                                DrawFacadeTexture(sourceTextures, bayBase, bayDimensions, subMesh, flipped, packedPosition);
                            }

                            //Cross Right
                            if (rightSpace > 0)
                            {
                                //Cross Left Bottom
                                subMesh       = bayStyle.GetTexture(BuildrBay.TextureNames.CrossTexture);
                                flipped       = bayStyle.IsFlipped(BuildrBay.TextureNames.CrossTexture);
                                bayBase.x     = windowXBase + leftSpace + openingSpace;
                                bayBase.y     = currentFloorBase;
                                bayDimensions = new Vector2(rightSpace, rowBottomHeight);
                                DrawFacadeTexture(sourceTextures, bayBase, bayDimensions, subMesh, flipped, packedPosition);

                                //Cross Left Top
                                subMesh       = bayStyle.GetTexture(BuildrBay.TextureNames.CrossTexture);
                                flipped       = bayStyle.IsFlipped(BuildrBay.TextureNames.CrossTexture);
                                bayBase.x     = windowXBase + leftSpace + openingSpace;
                                bayBase.y     = currentFloorBase + rowBottomHeight + bayStyle.openingHeight;
                                bayDimensions = new Vector2(rightSpace, rowTopHeight);
                                DrawFacadeTexture(sourceTextures, bayBase, bayDimensions, subMesh, flipped, packedPosition);
                            }

                            windowXBase += leftSpace + openingSpace + rightSpace;//move base vertor to next bay
                        }
                    }
                    else
                    {
                        // windowless wall
                        int  subMesh = facadeDesign.simpleBay.GetTexture(BuildrBay.TextureNames.WallTexture);
                        bool flipped = facadeDesign.simpleBay.IsFlipped(BuildrBay.TextureNames.WallTexture);
                        bayBase.x = 0;
                        bayBase.y = currentFloorBase;
                        Vector2 dimensions = new Vector2(facadeWidth, floorHeight);
                        DrawFacadeTexture(sourceTextures, bayBase, dimensions, subMesh, flipped, packedPosition);
                    }
                }
                facadeNumber++;
            }
        }
        LogTimer("generate facade textures");

        //add roof textures
        int numberOfroofTextures = roofTextures.Count;
        int scaledPadding        = Mathf.FloorToInt(ATLAS_PADDING * packedScale);

        for (int i = 0; i < numberOfroofTextures; i++)
        {
            Rect          roofTexturePosition = packedTexturePositions[i + facadeNumber];
            BuildrTexture bTexture            = roofTextures[i];
            int           roofTextureWidth    = bTexture.texture.width;
            int           roofTextureHeight   = bTexture.texture.height;
            int           targetTextureWidth  = Mathf.RoundToInt(roofTexturePosition.width);
            int           targetTextureHeight = Mathf.RoundToInt(roofTexturePosition.height);
            if (bTexture.maxUVTile == Vector2.zero)
            {
                LogTimer("BuildTextures: Skip texture " + bTexture.name + " as it appears it's not used");
                continue;
            }
            int sourceTextureWidth  = Mathf.RoundToInt(targetTextureWidth / (bTexture.tiled ? bTexture.maxUVTile.x : bTexture.tiledX));
            int sourceTextureHeight = Mathf.RoundToInt(targetTextureHeight / (bTexture.tiled ? bTexture.maxUVTile.y : bTexture.tiledY));
            int sourceTextureSize   = sourceTextureWidth * sourceTextureHeight;
            if (sourceTextureSize == 0)
            {
                //Debug.Log(sourceTextureWidth+" "+sourceTextureHeight+" "+bTexture.tiledX+" "+bTexture.maxUVTile+" "+bTexture.tiledX+","+bTexture.tiledY);
                continue;
            }
            Color32[] roofColourArray = TextureScale.NearestNeighbourSample(((Texture2D)bTexture.texture).GetPixels32(), roofTextureWidth, roofTextureHeight, sourceTextureWidth, sourceTextureHeight);
            //Color32[] roofColourArray = bTexture.texture.GetPixels32();

            for (int x = 0; x < targetTextureWidth; x++)
            {
                for (int y = 0; y < targetTextureHeight; y++)
                {
                    int drawX       = Mathf.FloorToInt(x + roofTexturePosition.x);
                    int drawY       = Mathf.FloorToInt(y + roofTexturePosition.y);
                    int colourIndex = drawX + drawY * textureWidth;

                    int sx          = x % sourceTextureWidth;
                    int sy          = y % sourceTextureHeight;
                    int sourceIndex = sx + sy * sourceTextureWidth;
                    if (sourceIndex >= sourceTextureSize)
                    {
                        Debug.Log("Source Index too big " + sx + " " + sy + " " + sourceTextureWidth + " " + sourceTextureSize + " " + bTexture.maxUVTile + " " + bTexture.name);
                    }
                    Color32 sourceColour = roofColourArray[sourceIndex];
                    if (colourIndex >= textureSize)
                    {
                        Debug.Log("Output Index Too big " + drawX + " " + drawY + " " + colourIndex + " " + textureSize + " " + roofTexturePosition);
                    }
                    colourArray[colourIndex] = sourceColour;

                    //Padding
                    if (x == 0)
                    {
                        for (int p = 0; p < scaledPadding; p++)
                        {
                            colourArray[colourIndex - p] = sourceColour;
                        }
                    }
                    if (x == targetTextureWidth - 1)
                    {
                        for (int p = 0; p < scaledPadding; p++)
                        {
                            colourArray[colourIndex + p] = sourceColour;
                        }
                    }

                    if (y == 0)
                    {
                        for (int p = 0; p < scaledPadding; p++)
                        {
                            colourArray[colourIndex - (p * textureWidth)] = sourceColour;
                        }
                    }

                    if (y == targetTextureHeight - 1)
                    {
                        for (int p = 0; p < scaledPadding; p++)
                        {
                            colourArray[colourIndex + (p * textureWidth)] = sourceColour;
                        }
                    }
                }
            }
        }
        LogTimer("generate roof textures");
    }
Example #12
0
    private static void Dormers(BuildrVolume volume, BuildrRoofDesign design)
    {
        BuildrPlan area = data.plan;
        int numberOfVolumePoints = volume.points.Count;
        int numberOfFloors = volume.numberOfFloors;
        float floorHeight = data.floorHeight;
        Vector3 volumeFloorHeight = Vector3.up * (numberOfFloors * floorHeight);

        for (int l = 0; l < numberOfVolumePoints; l++)
        {
            int indexA, indexB, indexA0, indexB0;
            Vector3 p0, p1, p00, p10;
            indexA = l;
            indexB = (l < numberOfVolumePoints - 1) ? l + 1 : 0;
            indexA0 = (l > 0) ? l - 1 : numberOfVolumePoints - 1;
            indexB0 = (l < numberOfVolumePoints - 2) ? l + 2 : l + 2 - numberOfVolumePoints;

            p0 = area.points[volume.points[indexA]].vector3;
            p1 = area.points[volume.points[indexB]].vector3;
            p00 = area.points[volume.points[indexA0]].vector3;
            p10 = area.points[volume.points[indexB0]].vector3;

            Vector3 facadeDirection = (p1 - p0).normalized;
            Vector3 facadeDirectionLeft = (p0 - p00).normalized;
            Vector3 facadeDirectionRight = (p10 - p1).normalized;
            Vector3 facadeNormal = Vector3.Cross(p1 - p0, Vector3.up).normalized;
            Vector3 facadeNormalLeft = Vector3.Cross(facadeDirectionLeft, Vector3.up);
            Vector3 facadeNormalRight = Vector3.Cross(facadeDirectionRight, Vector3.up);
            Vector3 leftDir = (facadeNormal + facadeNormalLeft).normalized;
            Vector3 rightDir = (facadeNormal + facadeNormalRight).normalized;

            float windowBottom = (design.height - design.dormerHeight) * design.dormerHeightRatio;

            float baseDepth = design.floorDepth;
            float cornerLeftRad = Vector3.Angle(facadeDirection, -facadeDirectionLeft) * Mathf.Deg2Rad / 2;
            float cornerRightRad = Vector3.Angle(-facadeDirection, facadeDirectionRight) * Mathf.Deg2Rad / 2;
            float cornerDepthLeft = baseDepth / Mathf.Sin(cornerLeftRad);
            float cornerDepthRight = baseDepth / Mathf.Sin(cornerRightRad);
            float topDepth = design.depth;
            float cornerTopDepthLeft = topDepth / Mathf.Sin(cornerLeftRad);
            float cornerTopDepthRight = topDepth / Mathf.Sin(cornerRightRad);

            float dormerDepth = design.depth * (design.dormerHeight / design.height);
            float windowBottomRat = Mathf.Lerp(0, 1 - design.dormerHeight / design.height, design.dormerHeightRatio);

            p0 += volumeFloorHeight + leftDir * cornerDepthLeft;
            p1 += volumeFloorHeight + rightDir * cornerDepthRight;

            float leftStartTopRad = Vector3.Angle(facadeDirectionLeft, facadeDirection) * Mathf.Deg2Rad * 0.5f;
            float leftStartMargin = cornerTopDepthLeft * Mathf.Sin(leftStartTopRad);

            float rightStartTopRad = Vector3.Angle(facadeDirection, facadeDirectionRight) * Mathf.Deg2Rad * 0.5f;
            float rightStartMargin = cornerTopDepthRight * Mathf.Sin(rightStartTopRad);

            Vector3 dormerStartPosition = leftDir * (windowBottomRat * cornerTopDepthLeft) + facadeDirection * (leftStartMargin);
            Vector3 dormerEndPosition = rightDir * (windowBottomRat * cornerTopDepthRight) - facadeDirection * (rightStartMargin + design.dormerWidth);
            float dormerPositionWidth = Vector3.Distance((p0 + dormerStartPosition), (p1 + dormerEndPosition));
            int numberOfWindows = Mathf.FloorToInt((dormerPositionWidth) / (design.dormerWidth + design.minimumDormerSpacing));
            float actualWindowSpacing = (dormerPositionWidth - (numberOfWindows * design.dormerWidth)) / (numberOfWindows + 1);
            numberOfWindows++;//add the final window

            Vector3 dormerWidthVector = facadeDirection * design.dormerWidth;
            Vector3 dormerHeightVectorA = Vector3.up * (design.dormerHeight - design.dormerRoofHeight);
            Vector3 dormerHeightVectorB = Vector3.up * design.dormerHeight;
            Vector3 dormerDepthVector = facadeNormal * dormerDepth;
            Vector3 dormerSpace = facadeDirection * (actualWindowSpacing + design.dormerWidth);
            Vector3 dormerSpacer = facadeDirection * (actualWindowSpacing);
            Vector3 dormerYPosition = Vector3.up * windowBottom;

            Vector3 w0, w1, w2, w3, w4, w5, w6, w7, w8, w9;
            for (int i = 0; i < numberOfWindows; i++)
            {
                w0 = p0 + dormerSpace * (i) + dormerStartPosition + dormerYPosition + dormerSpacer * 0.5f;
                w1 = w0 + dormerWidthVector;
                w2 = w0 + dormerHeightVectorA;
                w3 = w1 + dormerHeightVectorA;
                w4 = w0 + dormerWidthVector / 2 + dormerHeightVectorB;

                w5 = w0 + dormerDepthVector;
                w6 = w1 + dormerDepthVector;
                w7 = w2 + dormerDepthVector;
                w8 = w3 + dormerDepthVector;
                w9 = w4 + dormerDepthVector;

                int subMeshwindow = design.GetTexture(BuildrRoofDesign.textureNames.window);
                int subMeshwall = design.GetTexture(BuildrRoofDesign.textureNames.wall);
                int subMeshtiles = design.GetTexture(BuildrRoofDesign.textureNames.tiles);
                bool flippedwall = design.IsFlipped(BuildrRoofDesign.textureNames.wall);
                bool flippedtiles = design.IsFlipped(BuildrRoofDesign.textureNames.tiles);

                AddPlane(design, w1, w6, w3, w8, subMeshwall, flippedwall);//side
                AddPlane(design, w5, w0, w7, w2, subMeshwall, flippedwall);//side
                AddPlane(design, w3, w8, w4, w9, subMeshtiles, flippedtiles);//roof
                AddPlane(design, w7, w2, w9, w4, subMeshtiles, flippedtiles);//roof

                Vector3[] verts = new Vector3[5] { w0, w1, w2, w3, w4 };
                float roofBottom = (design.dormerHeight - design.dormerRoofHeight) / design.dormerHeight;
                Vector2[] uvs = new Vector2[5]{
					new Vector2(0,0),
					new Vector2(1,0),
					new Vector2(0,roofBottom),
					new Vector2(1,roofBottom),
					new Vector2(0.5f,1),
				};
                int[] tris = new int[9] { 1, 0, 2, 1, 2, 3, 2, 4, 3 };
                mesh.AddData(verts, uvs, tris, subMeshwindow);
            }
        }
    }
Example #13
0
    private static void Gabled(BuildrVolume volume, BuildrRoofDesign design)
    {
        BuildrPlan area = data.plan;
        int numberOfFloors = volume.numberOfFloors;
        float floorHeight = data.floorHeight;
        Vector3 volumeFloorHeight = Vector3.up * (numberOfFloors * floorHeight);
        Vector3 ridgeVector = Vector3.up * design.height;

        Vector3[] basePoints = new Vector3[4];
        if (design.direction == 0)
        {
            basePoints[0] = area.points[volume.points[0]].vector3 + volumeFloorHeight;
            basePoints[1] = area.points[volume.points[1]].vector3 + volumeFloorHeight;
            basePoints[2] = area.points[volume.points[2]].vector3 + volumeFloorHeight;
            basePoints[3] = area.points[volume.points[3]].vector3 + volumeFloorHeight;
        }
        else
        {
            basePoints[0] = area.points[volume.points[1]].vector3 + volumeFloorHeight;
            basePoints[1] = area.points[volume.points[2]].vector3 + volumeFloorHeight;
            basePoints[2] = area.points[volume.points[3]].vector3 + volumeFloorHeight;
            basePoints[3] = area.points[volume.points[0]].vector3 + volumeFloorHeight;
        }
        Vector3 centrePoint = Vector3.zero;
        for (int l = 0; l < 4; l++)
            centrePoint += area.points[volume.points[l]].vector3;
        centrePoint = (centrePoint / 4) + volumeFloorHeight + ridgeVector;

        Vector3 r0 = Vector3.Lerp(basePoints[0], basePoints[1], 0.5f) + ridgeVector;
        Vector3 r1 = Vector3.Lerp(basePoints[2], basePoints[3], 0.5f) + ridgeVector;

        int subMesh = design.GetTexture(BuildrRoofDesign.textureNames.tiles);
        bool flipped = design.IsFlipped(BuildrRoofDesign.textureNames.tiles);
        AddPlane(design, basePoints[0], r0, basePoints[3], r1, subMesh, flipped);//top
        AddPlane(design, basePoints[2], r1, basePoints[1], r0, subMesh, flipped);//top

        Vector3[] vertsA = new Vector3[3] { basePoints[0], basePoints[1], r0 };
        Vector3[] vertsB = new Vector3[3] { basePoints[2], basePoints[3], r1 };
        float uvWdithA = Vector3.Distance(basePoints[0], basePoints[1]);
        float uvWdithB = Vector3.Distance(basePoints[2], basePoints[3]);
        float uvHeight = design.height;
        subMesh = design.GetTexture(BuildrRoofDesign.textureNames.wall);
        BuildrTexture texture = textures[subMesh];

        if (texture.tiled)
        {
            uvWdithA *= (1.0f / texture.textureUnitSize.x);
            uvWdithB *= (1.0f / texture.textureUnitSize.x);
            uvHeight *= (1.0f / texture.textureUnitSize.y);
            if (texture.patterned)
            {
                Vector2 uvunits = texture.tileUnitUV;
                uvWdithA = Mathf.Ceil(uvWdithA / uvunits.x) * uvunits.x;
                uvWdithB = Mathf.Ceil(uvWdithB / uvunits.x) * uvunits.x;
                uvHeight = Mathf.Ceil(uvHeight / uvunits.y) * uvunits.y;
            }
        }
        else
        {
            uvWdithA = texture.tiledX;
            uvWdithB = texture.tiledX;
            uvHeight = texture.tiledY;
        }
        Vector2[] uvsA = new Vector2[3] { new Vector2(-uvWdithA / 2, 0), new Vector2(uvWdithA / 2, 0), new Vector2(0, uvHeight) };
        Vector2[] uvsB = new Vector2[3] { new Vector2(-uvWdithB / 2, 0), new Vector2(uvWdithB / 2, 0), new Vector2(0, uvHeight) };
        int[] tri = new int[3] { 1, 0, 2 };
        AddData(vertsA, uvsA, tri, subMesh);
        AddData(vertsB, uvsB, tri, subMesh);

    }
Example #14
0
    private static void Steeple(BuildrVolume volume, BuildrRoofDesign design)
    {
        BuildrPlan area = data.plan;
        int numberOfFloors = volume.numberOfFloors;
        float floorHeight = data.floorHeight;
        Vector3 volumeFloorHeight = Vector3.up * (numberOfFloors * floorHeight);
        Vector3 ridgeVector = Vector3.up * design.height;

        int numberOfVolumePoints = volume.points.Count;
        Vector3[] basePoints = new Vector3[numberOfVolumePoints];
        Vector3 centrePoint = Vector3.zero;
        for (int l = 0; l < numberOfVolumePoints; l++)
        {
            basePoints[l] = area.points[volume.points[l]].vector3 + volumeFloorHeight;
            centrePoint += area.points[volume.points[l]].vector3;
        }
        centrePoint = (centrePoint / numberOfVolumePoints) + volumeFloorHeight + ridgeVector;
        for (int l = 0; l < numberOfVolumePoints; l++)
        {
            int pointIndexA = l;
            int pointIndexB = (l < numberOfVolumePoints - 1) ? l + 1 : 0;
            Vector3[] verts = new Vector3[3] { basePoints[pointIndexA], basePoints[pointIndexB], centrePoint };
            float uvWdith = Vector3.Distance(basePoints[pointIndexA], basePoints[pointIndexB]);
            float uvHeight = design.height;
            int subMesh = design.GetTexture(BuildrRoofDesign.textureNames.tiles);
            BuildrTexture texture = textures[subMesh];

            if (texture.tiled)
            {
                uvWdith *= (1.0f / texture.textureUnitSize.x);
                uvHeight *= (1.0f / texture.textureUnitSize.y);
                if (texture.patterned)
                {
                    Vector2 uvunits = texture.tileUnitUV;
                    uvWdith = Mathf.Ceil(uvWdith / uvunits.x) * uvunits.x;
                    uvHeight = Mathf.Ceil(uvHeight / uvunits.y) * uvunits.y;
                }
            }
            else
            {
                uvWdith = texture.tiledX;
                uvHeight = texture.tiledY;
            }
            Vector2[] uvs = new Vector2[3] { new Vector2(-uvWdith / 2, 0), new Vector2(uvWdith / 2, 0), new Vector2(0, uvHeight) };
            int[] tri = new int[3] { 1, 0, 2 };
            AddData(verts, uvs, tri, subMesh);
        }
    }
Example #15
0
    private static void LeanTo(BuildrVolume volume, BuildrRoofDesign design)
    {
        BuildrPlan area = data.plan;
        int numberOfFloors = volume.numberOfFloors;
        float floorHeight = data.floorHeight;
        Vector3 volumeFloorHeight = Vector3.up * (numberOfFloors * floorHeight);
        Vector3 ridgeVector = Vector3.up * design.height;

        int[] pointIndexes = new int[4];
        switch (design.direction)
        {
            case 0:
                pointIndexes = new int[4] { 0, 1, 2, 3 };
                break;
            case 1:
                pointIndexes = new int[4] { 1, 2, 3, 0 };
                break;
            case 2:
                pointIndexes = new int[4] { 2, 3, 0, 1 };
                break;
            case 3:
                pointIndexes = new int[4] { 3, 0, 1, 2 };
                break;
        }
        Vector3[] points = new Vector3[6];
        points[0] = area.points[volume.points[pointIndexes[0]]].vector3 + volumeFloorHeight;
        points[1] = area.points[volume.points[pointIndexes[1]]].vector3 + volumeFloorHeight;
        points[2] = area.points[volume.points[pointIndexes[2]]].vector3 + volumeFloorHeight;
        points[3] = area.points[volume.points[pointIndexes[3]]].vector3 + volumeFloorHeight;
        points[4] = area.points[volume.points[pointIndexes[2]]].vector3 + volumeFloorHeight + ridgeVector;
        points[5] = area.points[volume.points[pointIndexes[3]]].vector3 + volumeFloorHeight + ridgeVector;

        //top
        int subMeshTop = design.GetTexture(BuildrRoofDesign.textureNames.tiles);
        bool flippedTop = design.IsFlipped(BuildrRoofDesign.textureNames.tiles);
        AddPlane(design, points[0], points[1], points[5], points[4], subMeshTop, flippedTop);

        //window
        int subMeshWindow = design.GetTexture(BuildrRoofDesign.textureNames.window);
        bool flippedWindow = design.IsFlipped(BuildrRoofDesign.textureNames.window);
        AddPlane(design, points[2], points[3], points[4], points[5], subMeshWindow, flippedWindow);

        //sides
        Vector3[] vertsA = new Vector3[3] { points[1], points[2], points[4] };
        Vector3[] vertsB = new Vector3[3] { points[0], points[3], points[5] };
        float uvWdith = Vector3.Distance(points[0], points[3]);
        float uvHeight = design.height;
        int subMesh = design.GetTexture(BuildrRoofDesign.textureNames.wall);
        BuildrTexture texture = textures[subMesh];

        if (texture.tiled)
        {
            uvWdith *= (1.0f / texture.textureUnitSize.x);
            uvHeight *= (1.0f / texture.textureUnitSize.y);
            if (texture.patterned)
            {
                Vector2 uvunits = texture.tileUnitUV;
                uvWdith = Mathf.Ceil(uvWdith / uvunits.x) * uvunits.x;
                uvHeight = Mathf.Ceil(uvHeight / uvunits.y) * uvunits.y;
            }
        }
        else
        {
            uvWdith = texture.tiledX;
            uvHeight = texture.tiledY;
        }

        Vector2[] uvs = new Vector2[3] { new Vector2(0, 0), new Vector2(uvWdith, 0), new Vector2(uvWdith, uvHeight) };
        if (!design.IsFlipped(BuildrRoofDesign.textureNames.wall))
            uvs = new Vector2[3] { new Vector2(uvWdith, 0), new Vector2(0, 0), new Vector2(uvHeight, uvWdith / 2) };

        int[] triA = new int[3] { 1, 0, 2 };
        int[] triB = new int[3] { 0, 1, 2 };

        AddData(vertsA, uvs, triA, subMesh);
        AddData(vertsB, uvs, triB, subMesh);
    }
Example #16
0
    private static void Hipped(BuildrVolume volume, BuildrRoofDesign design)
    {
        BuildrPlan area = data.plan;
        int numberOfFloors = volume.numberOfFloors;
        float baseHeight = data.floorHeight * numberOfFloors;
        float roofHeight = design.height;
        int numberOfVolumePoints = volume.points.Count;
        int subMesh = design.GetTexture(BuildrRoofDesign.textureNames.tiles);

        Vector2[] volumePoints = new Vector2[numberOfVolumePoints];
        for(int i = 0; i < numberOfVolumePoints; i++)
        {
            volumePoints[i] = area.points[volume.points[i]].vector2;
        }

        Vector2[][] meshData = StraightSkeleton.Calculate(volumePoints);
        Vector2[] triData = meshData[0];
        List<Vector2> interiorPoints = new List<Vector2>(meshData[1]);
        int numberOfVerts = triData.Length;
        Vector3[] verts = new Vector3[numberOfVerts];
        Vector2[] uvs = new Vector2[numberOfVerts];
        int[] tris = new int[numberOfVerts];
        for(int i = 0; i < triData.Length; i+=3)
        {
            Vector2 pa = triData[i];
            Vector2 pb = triData[i+1];
            Vector2 pc = triData[i+2];

            float ah = baseHeight + (interiorPoints.Contains(pa) ? roofHeight : 0);
            float bh = baseHeight + (interiorPoints.Contains(pb) ? roofHeight : 0);
            float ch = baseHeight + (interiorPoints.Contains(pc) ? roofHeight : 0);

            Vector3 v0 = new Vector3(pa.x, ah, pa.y);
            Vector3 v1 = new Vector3(pb.x, bh, pb.y);
            Vector3 v2 = new Vector3(pc.x, ch, pc.y);

            verts[i] = v0;
            verts[i+1] = v1;
            verts[i+2] = v2;

            Vector3 roofBaseDir = (interiorPoints.Contains(pc)) ? v1 - v0 : v2 - v1;
            Vector3 roofBaseNormal = Vector3.Cross(roofBaseDir, Vector3.up);
            Vector2[] uvsMansard = BuildrProjectUVs.Project(new Vector3[3] { v0, v1, v2 }, Vector2.zero, roofBaseNormal);

            uvs[i] = uvsMansard[0];
            uvs[i + 1] = uvsMansard[1];
            uvs[i + 2] = uvsMansard[2];

            tris[i] = i;
            tris[i + 1] = i+2;
            tris[i + 2] = i+1;
        }

        AddData(verts,uvs,tris,subMesh);

        /*Vector3 ridgeVector = Vector3.up * design.height;

        Vector3[] basePoints = new Vector3[4];
        if (design.direction == 0)
        {
            basePoints[0] = area.points[volume.points[0]].vector3 + volumeFloorHeight;
            basePoints[1] = area.points[volume.points[1]].vector3 + volumeFloorHeight;
            basePoints[2] = area.points[volume.points[2]].vector3 + volumeFloorHeight;
            basePoints[3] = area.points[volume.points[3]].vector3 + volumeFloorHeight;
        }
        else
        {
            basePoints[0] = area.points[volume.points[1]].vector3 + volumeFloorHeight;
            basePoints[1] = area.points[volume.points[2]].vector3 + volumeFloorHeight;
            basePoints[2] = area.points[volume.points[3]].vector3 + volumeFloorHeight;
            basePoints[3] = area.points[volume.points[0]].vector3 + volumeFloorHeight;
        }
        Vector3 centrePoint = Vector3.zero;
        for (int l = 0; l < 4; l++)
            centrePoint += area.points[volume.points[l]].vector3;
        centrePoint = (centrePoint / 4) + volumeFloorHeight + ridgeVector;

        Vector3 r0 = Vector3.Lerp(basePoints[0], basePoints[1], 0.5f) + ridgeVector;
        Vector3 r1 = Vector3.Lerp(basePoints[2], basePoints[3], 0.5f) + ridgeVector;
        Vector3 ridgeDirection = (r1 - r0);
        float roofLength = Vector3.Distance(r0, r1);
        float ridgeLengthA = Vector3.Distance(basePoints[0], basePoints[1]);
        if (ridgeLengthA > roofLength)
            ridgeLengthA = roofLength;
        float ridgeLengthB = Vector3.Distance(basePoints[2], basePoints[3]);
        if (ridgeLengthB > roofLength)
            ridgeLengthB = roofLength;
        r0 += ridgeDirection.normalized * ridgeLengthA / 2;
        r1 += -ridgeDirection.normalized * ridgeLengthB / 2;

        int subMesh = design.GetTexture(BuildrRoofDesign.textureNames.tiles);
        bool flipped = design.IsFlipped(BuildrRoofDesign.textureNames.tiles);
        AddPlane(design, basePoints[0], r0, basePoints[3], r1, subMesh, flipped);//top
        AddPlane(design, basePoints[2], r1, basePoints[1], r0, subMesh, flipped);//top

        Vector3[] vertsA = new Vector3[3] { basePoints[0], basePoints[1], r0 };
        Vector3[] vertsB = new Vector3[3] { basePoints[2], basePoints[3], r1 };
        float uvWdithA = Vector3.Distance(basePoints[0], basePoints[1]);
        float uvWdithB = Vector3.Distance(basePoints[2], basePoints[3]);
        float uvHeight = design.height;
        BuildrTexture texture = textures[subMesh];

        if (texture.tiled)
        {
            uvWdithA *= (1.0f / texture.textureUnitSize.x);
            uvWdithB *= (1.0f / texture.textureUnitSize.x);
            uvHeight *= (1.0f / texture.textureUnitSize.y);
            if (texture.patterned)
            {
                Vector2 uvunits = texture.tileUnitUV;
                uvWdithA = Mathf.Ceil(uvWdithA / uvunits.x) * uvunits.x;
                uvWdithB = Mathf.Ceil(uvWdithB / uvunits.x) * uvunits.x;
                uvHeight = Mathf.Ceil(uvHeight / uvunits.y) * uvunits.y;
            }
        }
        else
        {
            uvWdithA = texture.tiledX;
            uvWdithB = texture.tiledX;
            uvHeight = texture.tiledY;
        }
        Vector2[] uvsA = new Vector2[3] { new Vector2(-uvWdithA / 2, 0), new Vector2(uvWdithA / 2, 0), new Vector2(0, uvHeight) };
        Vector2[] uvsB = new Vector2[3] { new Vector2(-uvWdithB / 2, 0), new Vector2(uvWdithB / 2, 0), new Vector2(0, uvHeight) };
        int[] tri = new int[3] { 1, 0, 2 };
        AddData(vertsA, uvsA, tri, subMesh);
        AddData(vertsB, uvsB, tri, subMesh);*/
    }
Example #17
0
    private static void Sawtooth(BuildrVolume volume, BuildrRoofDesign design)
    {
        BuildrPlan area = data.plan;
        int numberOfFloors = volume.numberOfFloors;
        float floorHeight = data.floorHeight;
        Vector3 volumeFloorHeight = Vector3.up * (numberOfFloors * floorHeight);
        Vector3 ridgeVector = Vector3.up * design.height;

        int[] pointIndexes = new int[4];
        switch (design.direction)
        {
            case 0:
                pointIndexes = new int[4] { 0, 1, 2, 3 };
                break;
            case 1:
                pointIndexes = new int[4] { 1, 2, 3, 0 };
                break;
            case 2:
                pointIndexes = new int[4] { 2, 3, 0, 1 };
                break;
            case 3:
                pointIndexes = new int[4] { 3, 0, 1, 2 };
                break;
        }
        Vector3[] basepoints = new Vector3[4];
        Vector3[] points = new Vector3[6];

        for (int i = 0; i < design.sawtoothTeeth; i++)
        {

            Vector3 toothBaseMovementA = (area.points[volume.points[pointIndexes[3]]].vector3 - area.points[volume.points[pointIndexes[0]]].vector3).normalized;
            float roofDepthA = Vector3.Distance(area.points[volume.points[pointIndexes[3]]].vector3, area.points[volume.points[pointIndexes[0]]].vector3);
            float toothDepthA = roofDepthA / design.sawtoothTeeth;
            Vector3 toothVectorA = toothBaseMovementA * toothDepthA;

            Vector3 toothBaseMovementB = (area.points[volume.points[pointIndexes[2]]].vector3 - area.points[volume.points[pointIndexes[1]]].vector3).normalized;
            float roofDepthB = Vector3.Distance(area.points[volume.points[pointIndexes[2]]].vector3, area.points[volume.points[pointIndexes[1]]].vector3);
            float toothDepthB = roofDepthB / design.sawtoothTeeth;
            Vector3 toothVectorB = toothBaseMovementB * toothDepthB;

            basepoints[0] = area.points[volume.points[pointIndexes[0]]].vector3 + toothVectorA * i;
            basepoints[1] = area.points[volume.points[pointIndexes[1]]].vector3 + toothVectorB * i;
            basepoints[2] = basepoints[1] + toothVectorB;
            basepoints[3] = basepoints[0] + toothVectorA;

            points[0] = basepoints[0] + volumeFloorHeight;
            points[1] = basepoints[1] + volumeFloorHeight;
            points[2] = basepoints[2] + volumeFloorHeight;
            points[3] = basepoints[3] + volumeFloorHeight;
            points[4] = basepoints[2] + volumeFloorHeight + ridgeVector;
            points[5] = basepoints[3] + volumeFloorHeight + ridgeVector;

            //top
            int subMeshTop = design.GetTexture(BuildrRoofDesign.textureNames.tiles);
            bool flippedTop = design.IsFlipped(BuildrRoofDesign.textureNames.tiles);
            AddPlane(design, points[0], points[1], points[5], points[4], subMeshTop, flippedTop);

            //window
            int subMeshWindow = design.GetTexture(BuildrRoofDesign.textureNames.window);
            bool flippedWindow = design.IsFlipped(BuildrRoofDesign.textureNames.window);
            AddPlane(design, points[2], points[3], points[4], points[5], subMeshWindow, flippedWindow);

            //sides
            Vector3[] vertsA = new Vector3[3] { points[1], points[2], points[4] };
            Vector3[] vertsB = new Vector3[3] { points[0], points[3], points[5] };
            float uvWdith = Vector3.Distance(points[0], points[3]);
            float uvHeight = design.height;
            int subMesh = design.GetTexture(BuildrRoofDesign.textureNames.wall);
            BuildrTexture texture = textures[subMesh];

            if (texture.tiled)
            {
                uvWdith *= (1.0f / texture.textureUnitSize.x);
                uvHeight *= (1.0f / texture.textureUnitSize.y);
                if (texture.patterned)
                {
                    Vector2 uvunits = texture.tileUnitUV;
                    uvWdith = Mathf.Ceil(uvWdith / uvunits.x) * uvunits.x;
                    uvHeight = Mathf.Ceil(uvHeight / uvunits.y) * uvunits.y;
                }
            }
            else
            {
                uvWdith = texture.tiledX;
                uvHeight = texture.tiledY;
            }

            Vector2[] uvs = new Vector2[3] { new Vector2(0, 0), new Vector2(uvWdith, 0), new Vector2(uvWdith, uvHeight) };
            int[] triA = new int[3] { 1, 0, 2 };
            int[] triB = new int[3] { 0, 1, 2 };
            AddData(vertsA, uvs, triA, subMesh);
            AddData(vertsB, uvs, triB, subMesh);

        }
    }
Example #18
0
 public void RemoveVolume(BuildrVolume volume)
 {
     volumes.Remove(volume);
     DestroyImmediate(volume);
     CleanUpVolumes();
 }
Example #19
0
    public static void Build(DynamicMeshGenericMultiMaterialMesh _mesh, BuildrData _data)
    {
        data = _data;
        mesh = _mesh;
        BuildrPlan plan = data.plan;

        int facadeIndex     = 0;
        int numberOfVolumes = data.plan.numberOfVolumes;

        for (int s = 0; s < numberOfVolumes; s++)
        {
            BuildrVolume volume = plan.volumes[s];
            int          numberOfVolumePoints = volume.points.Count;
            Vector3[]    newEndVerts          = new Vector3[numberOfVolumePoints];
            Vector2[]    newEndUVs            = new Vector2[numberOfVolumePoints];
            Vector3      volumeHeight         = Vector3.up * (volume.numberOfFloors * data.floorHeight);
            for (int i = 0; i < numberOfVolumePoints; i++)
            {
                newEndVerts[i] = plan.points[volume.points[i]].vector3 + volumeHeight;
                newEndUVs[i]   = Vector2.zero;
            }

            List <int> tris = new List <int>(data.plan.GetTrianglesBySectorBase(s));
            mesh.AddData(newEndVerts, newEndUVs, tris.ToArray(), 0);
        }
        //Build ROOF

        //Build facades
        for (int v = 0; v < numberOfVolumes; v++)
        {
            BuildrVolume volume = plan.volumes[v];
            int          numberOfVolumePoints = volume.points.Count;

            for (int f = 0; f < numberOfVolumePoints; f++)
            {
                if (!volume.renderFacade[f])
                {
                    continue;
                }

                int     indexA = f;
                int     indexB = (f < numberOfVolumePoints - 1) ? f + 1 : 0;
                Vector3 p0     = plan.points[volume.points[indexA]].vector3;
                Vector3 p1     = plan.points[volume.points[indexB]].vector3;

                int floorBase      = plan.GetFacadeFloorHeight(v, volume.points[indexA], volume.points[indexB]);
                int numberOfFloors = volume.numberOfFloors - floorBase;
                if (numberOfFloors < 1)
                {
                    //no facade - adjacent facade is taller and covers this one
                    continue;
                }
                float floorHeight = data.floorHeight;

                Vector3 floorHeightStart = Vector3.up * (floorBase * floorHeight);
                Vector3 wallHeight       = Vector3.up * (volume.numberOfFloors * floorHeight) - floorHeightStart;
                float   facadeWidth      = Vector3.Distance(p0, p1);


                p0 += floorHeightStart;
                p1 += floorHeightStart;

                Vector3 w0 = p0;
                Vector3 w1 = p1;
                Vector3 w2 = w0 + wallHeight;
                Vector3 w3 = w1 + wallHeight;

                Vector2 uvMin = new Vector2(0, 0);
                Vector2 uvMax = new Vector2(facadeWidth, floorHeight);

                mesh.AddPlane(w0, w1, w2, w3, uvMin, uvMax, 0);
                facadeIndex++;
            }
        }

        data = null;
        mesh = null;
    }
Example #20
0
    private static void Gabled(BuildrVolume volume, BuildrRoofDesign design)
    {
        BuildrPlan area = data.plan;
        int numberOfFloors = volume.numberOfFloors;
        float floorHeight = data.floorHeight;
        Vector3 volumeFloorHeight = Vector3.up * (numberOfFloors * floorHeight);
        Vector3 ridgeVector = Vector3.up * design.height;

        Vector3[] basePoints = new Vector3[4];
        if (design.direction == 0)
        {
            basePoints[0] = area.points[volume.points[0]].vector3 + volumeFloorHeight;
            basePoints[1] = area.points[volume.points[1]].vector3 + volumeFloorHeight;
            basePoints[2] = area.points[volume.points[2]].vector3 + volumeFloorHeight;
            basePoints[3] = area.points[volume.points[3]].vector3 + volumeFloorHeight;
        }
        else
        {
            basePoints[0] = area.points[volume.points[1]].vector3 + volumeFloorHeight;
            basePoints[1] = area.points[volume.points[2]].vector3 + volumeFloorHeight;
            basePoints[2] = area.points[volume.points[3]].vector3 + volumeFloorHeight;
            basePoints[3] = area.points[volume.points[0]].vector3 + volumeFloorHeight;
        }
        Vector3 centrePoint = Vector3.zero;
        for (int l = 0; l < 4; l++)
            centrePoint += area.points[volume.points[l]].vector3;
        centrePoint = (centrePoint / 4) + volumeFloorHeight + ridgeVector;

        Vector3 r0 = Vector3.Lerp(basePoints[0], basePoints[1], 0.5f) + ridgeVector;
        Vector3 r1 = Vector3.Lerp(basePoints[2], basePoints[3], 0.5f) + ridgeVector;

        int subMesh = design.GetTexture(BuildrRoofDesign.textureNames.tiles);
        bool flipped = design.IsFlipped(BuildrRoofDesign.textureNames.tiles);
        AddPlane(design, basePoints[0], r0, basePoints[3], r1, subMesh, flipped);//top
        AddPlane(design, basePoints[2], r1, basePoints[1], r0, subMesh, flipped);//top

        Vector3[] vertsA = new Vector3[3] { basePoints[0], basePoints[1], r0 };
        Vector3[] vertsB = new Vector3[3] { basePoints[2], basePoints[3], r1 };
        float uvWdithA = Vector3.Distance(basePoints[0], basePoints[1]);
        float uvWdithB = Vector3.Distance(basePoints[2], basePoints[3]);
        float uvHeight = design.height;
        subMesh = design.GetTexture(BuildrRoofDesign.textureNames.wall);
        BuildrTexture texture = textures[subMesh];

        if (texture.tiled)
        {
            uvWdithA *= (1.0f / texture.textureUnitSize.x);
            uvWdithB *= (1.0f / texture.textureUnitSize.x);
            uvHeight *= (1.0f / texture.textureUnitSize.y);
            if (texture.patterned)
            {
                Vector2 uvunits = texture.tileUnitUV;
                uvWdithA = Mathf.Ceil(uvWdithA / uvunits.x) * uvunits.x;
                uvWdithB = Mathf.Ceil(uvWdithB / uvunits.x) * uvunits.x;
                uvHeight = Mathf.Ceil(uvHeight / uvunits.y) * uvunits.y;
            }
        }
        else
        {
            uvWdithA = texture.tiledX;
            uvWdithB = texture.tiledX;
            uvHeight = texture.tiledY;
        }
        Vector2[] uvsA = new Vector2[3] { new Vector2(-uvWdithA / 2, 0), new Vector2(uvWdithA / 2, 0), new Vector2(0, uvHeight) };
        Vector2[] uvsB = new Vector2[3] { new Vector2(-uvWdithB / 2, 0), new Vector2(uvWdithB / 2, 0), new Vector2(0, uvHeight) };
        int[] tri = new int[3] { 1, 0, 2 };
        AddData(vertsA, uvsA, tri, subMesh);
        AddData(vertsB, uvsB, tri, subMesh);

    }
Example #21
0
    private static void Parapet(BuildrVolume volume, BuildrRoofDesign design)
    {
        BuildrPlan area = data.plan;
        int volumeIndex = area.volumes.IndexOf(volume);
        int numberOfVolumePoints = volume.points.Count;
        int numberOfFloors = volume.numberOfFloors;
        float floorHeight = data.floorHeight;
        Vector3 volumeFloorHeight = Vector3.up * (numberOfFloors * floorHeight);

        for (int l = 0; l < numberOfVolumePoints; l++)
        {

            int indexA, indexB, indexA0, indexB0;
            Vector3 p0, p1, p00, p10;
            indexA = l;
            indexB = (l < numberOfVolumePoints - 1) ? l + 1 : 0;
            indexA0 = (l > 0) ? l - 1 : numberOfVolumePoints - 1;
            indexB0 = (l < numberOfVolumePoints - 2) ? l + 2 : l + 2 - numberOfVolumePoints;

            int adjacentFloorHeight = area.GetFacadeFloorHeight(volumeIndex, volume.points[indexA], volume.points[indexB]);
            bool leftParapet = area.GetFacadeFloorHeight(volumeIndex, volume.points[indexA0], volume.points[indexA]) < numberOfFloors;
            bool rightParapet = area.GetFacadeFloorHeight(volumeIndex, volume.points[indexB], volume.points[indexB0]) < numberOfFloors;

            if (adjacentFloorHeight >= numberOfFloors)
                continue;//do not draw a roof edge

            p0 = area.points[volume.points[indexA]].vector3;
            p1 = area.points[volume.points[indexB]].vector3;
            p00 = area.points[volume.points[indexA0]].vector3;
            p10 = area.points[volume.points[indexB0]].vector3;

            float facadeWidth = Vector3.Distance(p0, p1);
            Vector3 facadeDirection = (p1 - p0).normalized;
            Vector3 facadeDirectionLeft = (p0 - p00).normalized;
            Vector3 facadeDirectionRight = (p10 - p1).normalized;
            Vector3 facadeNormal = Vector3.Cross(facadeDirection, Vector3.up);
            Vector3 facadeNormalLeft = Vector3.Cross(facadeDirectionLeft, Vector3.up);
            Vector3 facadeNormalRight = Vector3.Cross(facadeDirectionRight, Vector3.up);

            float parapetHeight = design.parapetHeight;
            float parapetFrontDepth = design.parapetFrontDepth;
            float parapetBackDepth = design.parapetBackDepth;

            Vector3 w0, w1, w2, w3, w4, w5, w6, w7;
            Vector3 pr = facadeDirection * facadeWidth;
            Vector3 pu = Vector3.up * parapetHeight;

            Vector3 pbdl, pbdr, pfdl, pfdr;
            if (leftParapet)
            {
                pbdl = -(facadeNormal + facadeNormalLeft).normalized * parapetFrontDepth;
                pfdl = (facadeNormal + facadeNormalLeft).normalized * parapetBackDepth;
            }
            else
            {
                pbdl = facadeDirectionLeft * parapetFrontDepth;
                pfdl = -facadeDirectionLeft * parapetBackDepth;
            }
            if (rightParapet)
            {
                pbdr = -(facadeNormal + facadeNormalRight).normalized * parapetFrontDepth;
                pfdr = (facadeNormal + facadeNormalRight).normalized * parapetBackDepth;
            }
            else
            {
                pbdr = -facadeDirectionRight * parapetFrontDepth;
                pfdr = facadeDirectionRight * parapetBackDepth;
            }

            p0 += volumeFloorHeight;
            p1 += volumeFloorHeight;

            w2 = p0 + pbdl;//front left
            w3 = p0 + pr + pbdr;//front right
            w0 = p0 + pfdl;//back left
            w1 = p0 + pr + pfdr;//back right
            w6 = p0 + pbdl + pu;//front left top
            w7 = p0 + pr + pbdr + pu;//front right top
            w4 = p0 + pfdl + pu;//back left top
            w5 = p0 + pr + pfdr + pu;//back right top

            int subMesh = design.GetTexture(BuildrRoofDesign.textureNames.parapet);
            bool flipped = design.IsFlipped(BuildrRoofDesign.textureNames.parapet);
            AddPlane(design, w1, w0, w5, w4, subMesh, flipped);//front
            AddPlaneComplex(design, w6, w7, w4, w5, subMesh, flipped, facadeNormal);//top
            AddPlane(design, w2, w3, w6, w7, subMesh, flipped);//back

            if (parapetFrontDepth > 0)
                AddPlaneComplex(design, w3, w2, w1, w0, subMesh, flipped, facadeNormal);//bottom

            if (!leftParapet)
                AddPlane(design, w0, w2, w4, w6, subMesh, flipped);//left cap

            if (!rightParapet)
                AddPlane(design, w3, w1, w7, w5, subMesh, flipped);//left cap
        }
    }
Example #22
0
    private static void Dormers(BuildrVolume volume, BuildrRoofDesign design)
    {
        BuildrPlan area = data.plan;
        int numberOfVolumePoints = volume.points.Count;
        int numberOfFloors = volume.numberOfFloors;
        float floorHeight = data.floorHeight;
        Vector3 volumeFloorHeight = Vector3.up * (numberOfFloors * floorHeight);

        for (int l = 0; l < numberOfVolumePoints; l++)
        {
            int indexA, indexB, indexA0, indexB0;
            Vector3 p0, p1, p00, p10;
            indexA = l;
            indexB = (l < numberOfVolumePoints - 1) ? l + 1 : 0;
            indexA0 = (l > 0) ? l - 1 : numberOfVolumePoints - 1;
            indexB0 = (l < numberOfVolumePoints - 2) ? l + 2 : l + 2 - numberOfVolumePoints;

            p0 = area.points[volume.points[indexA]].vector3;
            p1 = area.points[volume.points[indexB]].vector3;
            p00 = area.points[volume.points[indexA0]].vector3;
            p10 = area.points[volume.points[indexB0]].vector3;

            Vector3 facadeDirection = (p1 - p0).normalized;
            Vector3 facadeDirectionLeft = (p0 - p00).normalized;
            Vector3 facadeDirectionRight = (p10 - p1).normalized;
            Vector3 facadeNormal = Vector3.Cross(p1 - p0, Vector3.up).normalized;
            Vector3 facadeNormalLeft = Vector3.Cross(facadeDirectionLeft, Vector3.up);
            Vector3 facadeNormalRight = Vector3.Cross(facadeDirectionRight, Vector3.up);
            Vector3 leftDir = (facadeNormal + facadeNormalLeft).normalized;
            Vector3 rightDir = (facadeNormal + facadeNormalRight).normalized;

            float windowBottom = (design.height - design.dormerHeight) * design.dormerHeightRatio;

            float baseDepth = design.floorDepth;
            float cornerLeftRad = Vector3.Angle(facadeDirection, -facadeDirectionLeft) * Mathf.Deg2Rad / 2;
            float cornerRightRad = Vector3.Angle(-facadeDirection, facadeDirectionRight) * Mathf.Deg2Rad / 2;
            float cornerDepthLeft = baseDepth / Mathf.Sin(cornerLeftRad);
            float cornerDepthRight = baseDepth / Mathf.Sin(cornerRightRad);
            float topDepth = design.depth;
            float cornerTopDepthLeft = topDepth / Mathf.Sin(cornerLeftRad);
            float cornerTopDepthRight = topDepth / Mathf.Sin(cornerRightRad);

            float dormerDepth = design.depth * (design.dormerHeight / design.height);
            float windowBottomRat = Mathf.Lerp(0, 1 - design.dormerHeight / design.height, design.dormerHeightRatio);

            p0 += volumeFloorHeight + leftDir * cornerDepthLeft;
            p1 += volumeFloorHeight + rightDir * cornerDepthRight;

            float leftStartTopRad = Vector3.Angle(facadeDirectionLeft, facadeDirection) * Mathf.Deg2Rad * 0.5f;
            float leftStartMargin = cornerTopDepthLeft * Mathf.Sin(leftStartTopRad);

            float rightStartTopRad = Vector3.Angle(facadeDirection, facadeDirectionRight) * Mathf.Deg2Rad * 0.5f;
            float rightStartMargin = cornerTopDepthRight * Mathf.Sin(rightStartTopRad);

            Vector3 dormerStartPosition = leftDir * (windowBottomRat * cornerTopDepthLeft) + facadeDirection * (leftStartMargin);
            Vector3 dormerEndPosition = rightDir * (windowBottomRat * cornerTopDepthRight) - facadeDirection * (rightStartMargin + design.dormerWidth);
            float dormerPositionWidth = Vector3.Distance((p0 + dormerStartPosition), (p1 + dormerEndPosition));
            int numberOfWindows = Mathf.FloorToInt((dormerPositionWidth) / (design.dormerWidth + design.minimumDormerSpacing));
            float actualWindowSpacing = (dormerPositionWidth - (numberOfWindows * design.dormerWidth)) / (numberOfWindows + 1);
            numberOfWindows++;//add the final window

            Vector3 dormerWidthVector = facadeDirection * design.dormerWidth;
            Vector3 dormerHeightVectorA = Vector3.up * (design.dormerHeight - design.dormerRoofHeight);
            Vector3 dormerHeightVectorB = Vector3.up * design.dormerHeight;
            Vector3 dormerDepthVector = facadeNormal * dormerDepth;
            Vector3 dormerSpace = facadeDirection * (actualWindowSpacing + design.dormerWidth);
            Vector3 dormerSpacer = facadeDirection * (actualWindowSpacing);
            Vector3 dormerYPosition = Vector3.up * windowBottom;

            Vector3 w0, w1, w2, w3, w4, w5, w6, w7, w8, w9;
            for (int i = 0; i < numberOfWindows; i++)
            {
                w0 = p0 + dormerSpace * (i) + dormerStartPosition + dormerYPosition + dormerSpacer * 0.5f;
                w1 = w0 + dormerWidthVector;
                w2 = w0 + dormerHeightVectorA;
                w3 = w1 + dormerHeightVectorA;
                w4 = w0 + dormerWidthVector / 2 + dormerHeightVectorB;

                w5 = w0 + dormerDepthVector;
                w6 = w1 + dormerDepthVector;
                w7 = w2 + dormerDepthVector;
                w8 = w3 + dormerDepthVector;
                w9 = w4 + dormerDepthVector;

                int subMeshwindow = design.GetTexture(BuildrRoofDesign.textureNames.window);
                int subMeshwall = design.GetTexture(BuildrRoofDesign.textureNames.wall);
                int subMeshtiles = design.GetTexture(BuildrRoofDesign.textureNames.tiles);
                bool flippedwall = design.IsFlipped(BuildrRoofDesign.textureNames.wall);
                bool flippedtiles = design.IsFlipped(BuildrRoofDesign.textureNames.tiles);

                AddPlane(design, w1, w6, w3, w8, subMeshwall, flippedwall);//side
                AddPlane(design, w5, w0, w7, w2, subMeshwall, flippedwall);//side
                AddPlane(design, w3, w8, w4, w9, subMeshtiles, flippedtiles);//roof
                AddPlane(design, w7, w2, w9, w4, subMeshtiles, flippedtiles);//roof

                Vector3[] verts = new Vector3[5] { w0, w1, w2, w3, w4 };
                float roofBottom = (design.dormerHeight - design.dormerRoofHeight) / design.dormerHeight;
                Vector2[] uvs = new Vector2[5]{
					new Vector2(0,0),
					new Vector2(1,0),
					new Vector2(0,roofBottom),
					new Vector2(1,roofBottom),
					new Vector2(0.5f,1),
				};
                int[] tris = new int[9] { 1, 0, 2, 1, 2, 3, 2, 4, 3 };
                mesh.AddData(verts, uvs, tris, subMeshwindow);
            }
        }
    }
Example #23
0
    public void MergeVolumes(int volumeIndexA, int volumeIndexB)
    {
        BuildrVolume volumeA     = volumes[volumeIndexA];
        BuildrVolume volumeB     = volumes[volumeIndexB];
        int          volumeASize = volumeA.Count;
        int          volumeBSize = volumeB.Count;
        List <int>   keepPoints  = new List <int>();

        string outpt = "";

        foreach (int p in volumeA.points)
        {
            outpt += "," + p;
        }
        //Debug.Log(outpt);
        outpt = "";
        foreach (int p in volumeB.points)
        {
            outpt += "," + p;
        }
        //Debug.Log(outpt);

        //find the start of volume A - where the connection to volume B ends.
        bool insideConnections = false;
        int  volumeAStart      = 0;

        for (int pa = 0; pa < volumeASize; pa++)
        {
            int paa      = volumeA.points[pa];
            int pab      = volumeA.points[(pa + 1) % volumeASize];
            int linkedVA = GetConnectingVolumeIndex(volumeIndexA, paa, pab);
            if (insideConnections)
            {
                if (linkedVA != volumeIndexB)               //if we leave the connection - mark the start of the non connected points
                {
                    volumeAStart = pa;
                    break;
                }
            }
            else
            {
                if (linkedVA == volumeIndexB)               //we have entered connected points
                {
                    insideConnections = true;
                }
            }
        }

        for (int pa = 0; pa < volumeASize; pa++)
        {
            int pas = (pa + volumeAStart) % volumeASize;

            int paa      = volumeA.points[pas];
            int pab      = volumeA.points[(pas + 1) % volumeASize];
            int linkedVA = GetConnectingVolumeIndex(volumeIndexA, paa, pab);
            if (linkedVA != volumeIndexB)           //if we leave the connection - mark the start of the non connected points
            {
                keepPoints.Add(paa);
            }
            else
            {
                keepPoints.Add(paa);                //add last point
                break;
            }
        }
        outpt = "";
        foreach (int p in keepPoints)
        {
            outpt += "," + p;
        }
        //Debug.Log(outpt);

        int volumeBStartIndex = volumeB.IndexOf(keepPoints[keepPoints.Count - 1]);

        //Debug.Log("volumeBStartIndex "+volumeBStartIndex);
        for (int pb = 1; pb < volumeBSize; pb++)   //start at one as we already have the first point logged from volume a
        {
            int pbs      = (pb + volumeBStartIndex) % volumeBSize;
            int pba      = volumeB.points[pbs];
            int pbb      = volumeB.points[(pbs + 1) % volumeBSize];
            int linkedVB = GetConnectingVolumeIndex(volumeIndexB, pba, pbb);
            //Debug.Log(pbs+" "+pba+" "+pbb+" "+linkedVB);
            if (linkedVB != volumeIndexA)           //if we leave the connection - mark the start of the non connected points
            {
                keepPoints.Add(pba);
            }
            else
            {
                break;
            }
        }
        //keepPoints.RemoveAt(keepPoints.Count-1);//remove last one - it is the start of volume a


        outpt = "";
        foreach (int p in keepPoints)
        {
            outpt += "," + p;
        }
        //Debug.Log(outpt);

        //remove all the linked points
        for (int rp = 0; rp < volumeASize; rp++)
        {
            int point = volumeA.points[rp];
            if (!keepPoints.Contains(point))
            {
                int keepPointLength = keepPoints.Count;
                for (int ap = 0; ap < keepPointLength; ap++)
                {
                    int keepPoint = keepPoints[ap];
                    if (keepPoint > point)
                    {
                        keepPoints[ap]--;
                    }
                }
                Debug.Log(point);
                RemovePoint(point);
                volumeASize--;
                rp--;
            }
        }

        //transfer all the styles across to the one volume
        foreach (int kp in keepPoints)
        {
            BuildrVolumeStylesUnit[] VBStyles = volumeB.styles.GetContents();
            if (!volumeA.Contains(kp))
            {
                foreach (BuildrVolumeStylesUnit style in VBStyles)
                {
                    if (style.facadeID == kp)
                    {
                        volumeA.styles.AddStyle(style.styleID, style.facadeID, style.floors);
                    }
                }
            }
        }

        //reassign the list of points
        volumeA.points = new List <int>(keepPoints);

        //remove old volume
        RemoveVolume(volumeB);
        outpt = "";
        foreach (int p in volumeA.points)
        {
            outpt += "," + p;
        }
        //Debug.Log(outpt);
    }
Example #24
0
    public static void SceneGUI(BuildrEditMode editMode, BuildrData data, bool shouldSnap, float handleSize)
    {
        if (editMode.fullMesh == null)
        {
            return;
        }

        Rect HUDRect = new Rect(0, 0, 300, 300);

        Handles.BeginGUI();
        GUILayout.BeginArea(HUDRect);

        EditorGUILayout.LabelField("Buildr");
        EditorGUILayout.LabelField("Vertices: " + editMode.fullMesh.vertexCount);
        EditorGUILayout.LabelField("Triangles " + editMode.fullMesh.triangleCount / 3);

        GUILayout.EndArea();
        Handles.EndGUI();

        bool isLegal = !(data.plan.illegalPoints.Length > 0);

        if (isLegal)
        {
            isLegal = editMode.transform.localScale == Vector3.one;
        }

        if (isLegal)
        {
            return;
        }

        int numberOfFacades  = data.facades.Count;
        int numberOfRoofs    = data.roofs.Count;
        int numberOfTextures = data.textures.Count;

        if (numberOfFacades == 0 || numberOfRoofs == 0 || numberOfTextures == 0)
        {
            return;
        }

        Vector3 position = editMode.transform.position;

        BuildrPlan area            = data.plan;
        int        numberOfVolumes = area.numberOfVolumes;

        int facadeCounter = 0;

        for (int s = 0; s < numberOfVolumes; s++)
        {
            BuildrVolume volume      = data.plan.volumes[s];
            int          volumeSize  = volume.Count;
            Vector3      floorCentre = Vector3.zero;
            Handles.color = Color.red;

            for (int p = 0; p < volumeSize; p++)
            {
                int     point    = volume.points[p];
                Vector3 pointPos = area.points[point].vector3;
                floorCentre += pointPos;

                List <Vector3> verts        = new List <Vector3>();
                int            indexB       = (p < volumeSize - 1) ? p + 1 : 0;
                Vector3        volumeHeight = Vector3.up * (volume.numberOfFloors * data.floorHeight);
                verts.Add(pointPos + position);
                verts.Add(area.points[volume.points[indexB]].vector3 + position);
                verts.Add(verts[1] + volumeHeight);
                verts.Add(verts[0] + volumeHeight);
                Handles.DrawSolidRectangleWithOutline(verts.ToArray(), new Color(1, 0, 0, 0.2f), Color.red);
                Handles.DrawLine(verts[2], verts[3]);
                facadeCounter++;
            }
        }
    }
Example #25
0
    public static void SceneGUI(BuildrEditMode editMode, BuildrData data, bool shouldSnap, float handleSize)
    {
        if (data.details.Count == 0)
        {
            return;
        }
        Undo.RecordObject(data, "Detail Modified");

        int numberOfFacades  = data.facades.Count;
        int numberOfRoofs    = data.roofs.Count;
        int numberOfTextures = data.textures.Count;

        if (numberOfFacades == 0 || numberOfRoofs == 0 || numberOfTextures == 0)
        {
            return;
        }

        Vector3 position = editMode.transform.position;

        BuildrPlan   plan            = data.plan;
        int          numberOfVolumes = plan.numberOfVolumes;
        BuildrDetail bDetail         = data.details[selectedDetail];
        float        volumeHeight    = 0;
        Vector3      baseLeft        = Vector3.zero;
        Vector3      baseRight       = Vector3.zero;
        int          faceIndex       = bDetail.face;

        int facadeCounter = 0;

        for (int v = 0; v < numberOfVolumes; v++)
        {
            BuildrVolume volume      = data.plan.volumes[v];
            int          volumeSize  = volume.Count;
            Vector3      floorCentre = Vector3.zero;
            Handles.color = Color.white;

            for (int p = 0; p < volumeSize; p++)
            {
                int     point  = volume.points[p];
                int     indexB = volume.points[(p + 1) % volumeSize];
                Vector3 fb0    = plan.points[point].vector3;
                Vector3 fb1    = plan.points[indexB].vector3;
                if (bDetail.face == facadeCounter && bDetail.type == BuildrDetail.Types.Facade)
                {
                    baseLeft  = fb0;
                    baseRight = fb1;
                }
                floorCentre += baseLeft;

                List <Vector3> verts = new List <Vector3>();
                volumeHeight = (volume.numberOfFloors * data.floorHeight);
                Vector3 volumeHeightVector = Vector3.up * volumeHeight;
                verts.Add(fb0 + position);
                verts.Add(fb1 + position);
                verts.Add(verts[1] + volumeHeightVector);
                verts.Add(verts[0] + volumeHeightVector);
                if (bDetail.face == facadeCounter && bDetail.type == BuildrDetail.Types.Facade)
                {
                    //display something to highlight this facade
                    Handles.DrawSolidRectangleWithOutline(verts.ToArray(), Color.clear, BuildrColours.MAGENTA);
                }
                Handles.color = BuildrColours.CYAN;
                if (v == bDetail.face && bDetail.type == BuildrDetail.Types.Roof)
                {
                    Handles.DrawLine(verts[2], verts[3]);
                }
                if (editMode.showFacadeMarkers)
                {
                    Handles.color = Color.white;
                    Vector3  camDirection     = Camera.current.transform.forward;
                    Vector3  facadeDirection  = Vector3.Cross((verts[0] - verts[1]), Vector3.up);
                    GUIStyle facadeLabelStyle = new GUIStyle();
                    facadeLabelStyle.normal.textColor = Color.white;
                    facadeLabelStyle.alignment        = TextAnchor.MiddleCenter;
                    facadeLabelStyle.fixedWidth       = 75.0f;
                    if (Vector3.Dot(camDirection, facadeDirection) < 0)//only display label when facade is facing camera
                    {
                        Vector3 centerPos = (verts[0] + verts[1]) * 0.5f;
                        Vector3 labelPos  = centerPos + facadeDirection.normalized;
                        Handles.Label(labelPos, "facade " + facadeCounter, facadeLabelStyle);
                        Handles.DrawLine(centerPos, labelPos);
                    }
                }
                facadeCounter++;
            }
        }

        Vector3    handlePosition = bDetail.worldPosition + position;// new Vector3(basePos.x, volumeHeight * bDetail.faceUv.y, basePos.z);
        Vector3    baseDir        = (baseRight - baseLeft).normalized;
        Vector3    baseCross      = Vector3.Cross(Vector3.up, baseDir);
        Quaternion currentRot     = Quaternion.Euler(bDetail.userRotation);
        Quaternion faceRotation   = (bDetail.type == BuildrDetail.Types.Facade) ? Quaternion.LookRotation(baseCross) : Quaternion.identity;

        switch (Tools.current)
        {
        case Tool.Move:
            Vector3 dirX, dirY, dirZ;
            if (bDetail.type == BuildrDetail.Types.Facade)
            {
                dirX = baseDir;
                dirY = baseCross;
                dirZ = Vector3.up;
            }
            else
            {
                dirX = Vector3.right;
                dirY = Vector3.up;
                dirZ = Vector3.forward;
            }
            Vector3 newSliderPos;
            Handles.color = BuildrColours.RED;
            newSliderPos  = Handles.Slider(handlePosition, dirX, handleSize * 0.666f, Handles.ArrowCap, 0.0f);
            Handles.color = BuildrColours.BLUE;
            newSliderPos  = Handles.Slider(newSliderPos, dirZ, handleSize * 0.666f, Handles.ArrowCap, 0.0f);
            Handles.color = BuildrColours.GREEN;
            newSliderPos  = Handles.Slider(newSliderPos, dirY, handleSize * 0.666f, Handles.ArrowCap, 0.0f);
            Vector3 sliderDiff = newSliderPos - handlePosition;

            if (sliderDiff != Vector3.zero)
            {
                float newXUV = 0, newYUV = 0, newHeight = bDetail.faceHeight;
                if (bDetail.type == BuildrDetail.Types.Facade)
                {
                    float facadeWidth = Vector3.Distance(baseLeft, baseRight);
                    float sliderDiffX = Mathf.Sqrt(sliderDiff.x * sliderDiff.x + sliderDiff.z * sliderDiff.z) * Mathf.Sign(Vector3.Dot(baseDir, sliderDiff));
                    newXUV = sliderDiffX / facadeWidth + bDetail.faceUv.x;
                    newYUV = sliderDiff.y / volumeHeight + bDetail.faceUv.y;
                }
                else
                {
                    BuildrVolume volume = plan.volumes[faceIndex];
                    int          numberOfVolumePoints = volume.points.Count;
                    Vector3      minPoint             = plan.points[volume.points[0]].vector3;
                    Vector3      maxPoint             = plan.points[volume.points[0]].vector3;
                    for (int p = 1; p < numberOfVolumePoints; p++)
                    {
                        Vector3 fp0 = plan.points[volume.points[p]].vector3;
                        if (fp0.x < minPoint.x)
                        {
                            minPoint.x = fp0.x;
                        }
                        if (fp0.z < minPoint.z)
                        {
                            minPoint.z = fp0.z;
                        }
                        if (fp0.x > maxPoint.x)
                        {
                            maxPoint.x = fp0.x;
                        }
                        if (fp0.z > maxPoint.z)
                        {
                            maxPoint.z = fp0.z;
                        }
                    }
                    float roofWidth = maxPoint.x - minPoint.x;
                    float roofDepth = maxPoint.z - minPoint.z;
                    newXUV     = sliderDiff.x / roofWidth + bDetail.faceUv.x;
                    newYUV     = sliderDiff.z / roofDepth + bDetail.faceUv.y;
                    newHeight += sliderDiff.y;
                }
                bDetail.faceUv     = new Vector2(newXUV, newYUV);
                bDetail.faceHeight = newHeight;
            }
            break;

        case Tool.Rotate:
            currentRot           = Handles.RotationHandle(currentRot, handlePosition);
            bDetail.userRotation = currentRot.eulerAngles;
            break;

        case Tool.Scale:
            bDetail.scale = Handles.ScaleHandle(bDetail.scale, handlePosition, currentRot * faceRotation, handleSize * 0.666f);

            break;
        }

        //draw mesh bounds
        if (bDetail.mesh != null)
        {
            Bounds     meshBounds = bDetail.mesh.bounds;
            Quaternion rotation   = bDetail.worldRotation;
            Vector3    p0         = rotation * (new Vector3(meshBounds.min.x, meshBounds.min.y, meshBounds.min.z)) + bDetail.worldPosition;
            Vector3    p1         = rotation * (new Vector3(meshBounds.max.x, meshBounds.min.y, meshBounds.min.z)) + bDetail.worldPosition;
            Vector3    p2         = rotation * (new Vector3(meshBounds.min.x, meshBounds.min.y, meshBounds.max.z)) + bDetail.worldPosition;
            Vector3    p3         = rotation * (new Vector3(meshBounds.max.x, meshBounds.min.y, meshBounds.max.z)) + bDetail.worldPosition;
            Vector3    p4         = rotation * (new Vector3(meshBounds.min.x, meshBounds.max.y, meshBounds.min.z)) + bDetail.worldPosition;
            Vector3    p5         = rotation * (new Vector3(meshBounds.max.x, meshBounds.max.y, meshBounds.min.z)) + bDetail.worldPosition;
            Vector3    p6         = rotation * (new Vector3(meshBounds.min.x, meshBounds.max.y, meshBounds.max.z)) + bDetail.worldPosition;
            Vector3    p7         = rotation * (new Vector3(meshBounds.max.x, meshBounds.max.y, meshBounds.max.z)) + bDetail.worldPosition;

            Handles.color = BuildrColours.BLUE;
            Handles.DrawLine(p0, p1);
            Handles.DrawLine(p0, p2);
            Handles.DrawLine(p1, p3);
            Handles.DrawLine(p2, p3);
            Handles.DrawLine(p0, p4);
            Handles.DrawLine(p1, p5);
            Handles.DrawLine(p2, p6);
            Handles.DrawLine(p3, p7);
            Handles.DrawLine(p4, p5);
            Handles.DrawLine(p4, p6);
            Handles.DrawLine(p5, p7);
            Handles.DrawLine(p6, p7);

            if (clickPlace)
            {
                Vector3 planeBase   = Vector3.zero;
                Vector3 planeNormal = Vector3.up;
                Vector3 planeSize   = Vector3.zero;
                if (bDetail.type == BuildrDetail.Types.Facade)
                {
                    //find facade
                    int  facadeCount = 0;
                    bool facadeFound = false;
                    for (int s = 0; s < numberOfVolumes; s++)
                    {
                        BuildrVolume volume = plan.volumes[s];
                        int          numberOfVolumePoints = volume.points.Count;
                        for (int p = 0; p < numberOfVolumePoints; p++)
                        {
                            if (facadeCount == faceIndex)
                            {
                                int     indexA = p;
                                int     indexB = (p + 1) % numberOfVolumePoints;
                                Vector3 fp0    = plan.points[volume.points[indexA]].vector3;
                                Vector3 fp1    = plan.points[volume.points[indexB]].vector3;
                                planeBase   = fp0;
                                planeNormal = Vector3.Cross(Vector3.up, fp1 - fp0).normalized;
                                planeSize.x = Vector3.Distance(fp0, fp1);
                                planeSize.y = volume.numberOfFloors * data.floorHeight;
                                facadeFound = true;
                                break;
                            }
                            facadeCount++;
                        }
                        if (facadeFound)
                        {
                            break;
                        }
                    }
                }
                else
                {
                    BuildrVolume volume = plan.volumes[faceIndex];
                    int          numberOfVolumePoints = volume.points.Count;
                    Vector3      minPoint             = plan.points[volume.points[0]].vector3;
                    Vector3      maxPoint             = plan.points[volume.points[0]].vector3;
                    for (int p = 1; p < numberOfVolumePoints; p++)
                    {
                        Vector3 fp0 = plan.points[volume.points[p]].vector3;
                        if (fp0.x < minPoint.x)
                        {
                            minPoint.x = fp0.x;
                        }
                        if (fp0.z < minPoint.z)
                        {
                            minPoint.z = fp0.z;
                        }
                        if (fp0.x > maxPoint.x)
                        {
                            maxPoint.x = fp0.x;
                        }
                        if (fp0.z > maxPoint.z)
                        {
                            maxPoint.z = fp0.z;
                        }
                    }
                    planeSize.x = maxPoint.x - minPoint.x;
                    planeSize.z = maxPoint.z - minPoint.z;
                    planeBase   = minPoint;
                    planeBase.y = (data.floorHeight * volume.numberOfFloors);
                }
                float distance;
                Plane buildingPlane = new Plane(planeNormal, planeBase);
                Ray   ray           = Camera.current.ScreenPointToRay(new Vector3(Event.current.mousePosition.x, Screen.height - Event.current.mousePosition.y - 30, 0));
                if (buildingPlane.Raycast(ray, out distance))
                {
                    Vector3    mousePlanePoint    = ray.GetPoint(distance);
                    Quaternion mouseLookDirection = Quaternion.LookRotation(buildingPlane.normal);

                    if (Handles.Button(mousePlanePoint, mouseLookDirection, handleSize * 0.1f, handleSize * 0.1f, Handles.CircleCap))
                    {
                        float xUv, yUv;
                        if (bDetail.type == BuildrDetail.Types.Facade)
                        {
                            Vector3 facadeBaseMousePoint = new Vector3(mousePlanePoint.x, 0, mousePlanePoint.z);
                            xUv = Vector3.Distance(planeBase, facadeBaseMousePoint) / planeSize.x;
                            yUv = (mousePlanePoint.y - planeBase.y) / planeSize.y;
                        }
                        else
                        {
                            xUv = (mousePlanePoint.x - planeBase.x) / planeSize.x;
                            yUv = (mousePlanePoint.z - planeBase.z) / planeSize.z;
                        }
                        bDetail.faceUv = new Vector2(xUv, yUv);
                        clickPlace     = false;
                        GUI.changed    = true;
                    }
                }
            }
        }


        if (GUI.changed)
        {
            EditorUtility.SetDirty(editMode);
            EditorUtility.SetDirty(data);
            editMode.UpdateRender();
        }
    }
Example #26
0
    private static void Mansard(BuildrVolume volume, BuildrRoofDesign design)
    {
        BuildrPlan area = data.plan;
        int numberOfVolumePoints = volume.points.Count;
        int numberOfFloors = volume.numberOfFloors;
        float floorHeight = data.floorHeight;
        Vector3 volumeFloorHeight = Vector3.up * (numberOfFloors * floorHeight);

        //add top base of the flat roof
        Vector3[] topVerts = new Vector3[numberOfVolumePoints];
        Vector2[] topUVs = new Vector2[numberOfVolumePoints];
        int topTextureID = design.GetTexture(BuildrRoofDesign.textureNames.floorB);
        BuildrTexture texture = textures[topTextureID];

        for (int l = 0; l < numberOfVolumePoints; l++)
        {
            int indexA, indexB, indexA0, indexB0;
            Vector3 p0, p1, p00, p10;
            indexA = l;
            indexB = (l < numberOfVolumePoints - 1) ? l + 1 : 0;
            indexA0 = (l > 0) ? l - 1 : numberOfVolumePoints - 1;
            indexB0 = (l < numberOfVolumePoints - 2) ? l + 2 : l + 2 - numberOfVolumePoints;

            p0 = area.points[volume.points[indexA]].vector3;
            p1 = area.points[volume.points[indexB]].vector3;
            p00 = area.points[volume.points[indexA0]].vector3;
            p10 = area.points[volume.points[indexB0]].vector3;

            float facadeWidth = Vector3.Distance(p0, p1);
            Vector3 facadeDirection = (p1 - p0).normalized;
            Vector3 facadeDirectionLeft = (p0 - p00).normalized;
            Vector3 facadeDirectionRight = (p10 - p1).normalized;
            Vector3 facadeNormal = Vector3.Cross(facadeDirection, Vector3.up);
            Vector3 facadeNormalLeft = Vector3.Cross(facadeDirectionLeft, Vector3.up);
            Vector3 facadeNormalRight = Vector3.Cross(facadeDirectionRight, Vector3.up);

            float roofHeight = design.height;
            float baseDepth = design.floorDepth;
            float cornerLeftRad = Vector3.Angle(facadeDirection, -facadeDirectionLeft) * Mathf.Deg2Rad / 2;
            float cornerRightRad = Vector3.Angle(-facadeDirection, facadeDirectionRight) * Mathf.Deg2Rad / 2;
            float cornerDepthLeft = baseDepth / Mathf.Sin(cornerLeftRad);
            float cornerDepthRight = baseDepth / Mathf.Sin(cornerRightRad);
            float topDepth = design.depth;
            float cornerTopDepthLeft = topDepth / Mathf.Sin(cornerLeftRad);
            float cornerTopDepthRight = topDepth / Mathf.Sin(cornerRightRad);

            Vector3 pr = facadeDirection * facadeWidth;

            Vector3 leftDir = (facadeNormal + facadeNormalLeft).normalized;
            Vector3 rightDir = (facadeNormal + facadeNormalRight).normalized;

            p0 += volumeFloorHeight;
            p1 += volumeFloorHeight;

            Vector3 w0, w1, w2, w3, w4, w5;
            w0 = p0;
            w1 = p0 + pr;
            w2 = w0 + leftDir * cornerDepthLeft;
            w3 = w1 + rightDir * cornerDepthRight;
            w4 = w2 + leftDir * cornerTopDepthLeft + Vector3.up * roofHeight;
            w5 = w3 + rightDir * cornerTopDepthRight + Vector3.up * roofHeight;

            Vector3[] verts = new Vector3[6] { w0, w1, w2, w3, w4, w5 };
//            List<Vector2> uvs = new List<Vector2>();

            Vector2[] uvsFloor = BuildrProjectUVs.Project(new Vector3[4] { w0, w1, w2, w3 }, Vector2.zero, facadeNormal);
            if(baseDepth == 0)
                uvsFloor[3].x = facadeWidth;
            Vector2[] uvsMansard = BuildrProjectUVs.Project(new Vector3[3] { w2, w4, w5 }, uvsFloor[2], facadeNormal);

            Vector3[] vertsA = new Vector3[4] { verts[0], verts[1], verts[2], verts[3] };
            Vector2[] uvsA = new Vector2[4] { uvsFloor[0], uvsFloor[1], uvsFloor[2], uvsFloor[3] };
            int[] trisA = new int[6] { 1, 0, 2, 1, 2, 3 };
            int subMeshA = design.GetTexture(BuildrRoofDesign.textureNames.floor);
            mesh.AddData(vertsA, uvsA, trisA, subMeshA);

            Vector3[] vertsB = new Vector3[4] { verts[2], verts[3], verts[4], verts[5] };
            Vector2[] uvsB = new Vector2[4] { uvsFloor[2], uvsFloor[3], uvsMansard[1], uvsMansard[2] };
            int[] trisB = new int[6] { 0, 2, 1, 1, 2, 3 };
            int subMeshB = design.GetTexture(BuildrRoofDesign.textureNames.tiles);
            mesh.AddData(vertsB, uvsB, trisB, subMeshB);

            //modify point for the top geometry
            Vector2z point = area.points[volume.points[l]];
            topVerts[l] = point.vector3 + volumeFloorHeight + Vector3.up * roofHeight + leftDir * (cornerDepthLeft + cornerTopDepthLeft);
            topUVs[l] = new Vector2(topVerts[l].x / texture.textureUnitSize.x, topVerts[l].z / texture.textureUnitSize.y);
        }

        Vector2z[] topVertV2z = new Vector2z[topVerts.Length];
        for (int i = 0; i < topVerts.Length; i++)
            topVertV2z[i] = new Vector2z(topVerts[i]);
        int[] topTris = EarClipper.Triangulate(topVertV2z);
        AddData(topVerts, topUVs, topTris, topTextureID);//top
    }
Example #27
0
    public static void Build(DynamicMeshGenericMultiMaterialMesh _mesh, BuildrData _data)
    {
        //        timestart = Time.realtimeSinceStartup;
        data     = _data;
        mesh     = _mesh;
        textures = data.textures.ToArray();
        BuildrPlan plan = data.plan;

//        int facadeIndex = 0;
        numberOfFacades = 0;
        int numberOfVolumes = data.plan.numberOfVolumes;

        //define rectangles that represent the facades
        packedTexturePositions.Clear();
        for (int v = 0; v < numberOfVolumes; v++)
        {
            BuildrVolume volume = plan.volumes[v];
            int          numberOfVolumePoints = volume.points.Count;

            for (int f = 0; f < numberOfVolumePoints; f++)
            {
                if (!volume.renderFacade[f])
                {
                    continue;
                }
                int      indexA = f;
                int      indexB = (f < numberOfVolumePoints - 1) ? f + 1 : 0;
                Vector2z p0     = plan.points[volume.points[indexA]];
                Vector2z p1     = plan.points[volume.points[indexB]];

                float facadeWidth = Vector2z.Distance(p0, p1) * PIXELS_PER_METER;
                int   floorBase   = plan.GetFacadeFloorHeight(v, volume.points[indexA], volume.points[indexB]);

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

                float floorHeight  = data.floorHeight;
                float facadeHeight = (volume.numberOfFloors - floorBase) * floorHeight * PIXELS_PER_METER;
                if (facadeHeight < 0)
                {
                    facadeWidth  = 0;
                    facadeHeight = 0;
                }

                Rect newFacadeRect = new Rect(0, 0, facadeWidth, facadeHeight);
                packedTexturePositions.Add(newFacadeRect);

                numberOfFacades++;
            }
        }

        //Build ROOF
        DynamicMeshGenericMultiMaterialMesh dynMeshRoof = new DynamicMeshGenericMultiMaterialMesh();

        dynMeshRoof.name         = "Roof Mesh";
        dynMeshRoof.subMeshCount = textures.Length;
        BuildrRoof.Build(dynMeshRoof, data, true);
        dynMeshRoof.CheckMaxTextureUVs(data);

        roofTextures.Clear();
        roofTextureIndex.Clear();
        foreach (BuildrRoofDesign roofDesign in data.roofs)
        {
            foreach (int textureIndex in roofDesign.textureValues)
            {
                if (!roofTextureIndex.Contains(textureIndex))
                {
                    BuildrTexture bTexture = data.textures[textureIndex];
                    Vector2       largestSubmeshPlaneSize = new Vector2(1, 1);
                    Vector2       minWorldUvSize          = dynMeshRoof.MinWorldUvSize(textureIndex);
                    Vector2       maxWorldUvSize          = dynMeshRoof.MaxWorldUvSize(textureIndex);
                    largestSubmeshPlaneSize.x = maxWorldUvSize.x - minWorldUvSize.x;
                    largestSubmeshPlaneSize.y = maxWorldUvSize.y - minWorldUvSize.y;
                    int  roofTextureWidth    = Mathf.RoundToInt(largestSubmeshPlaneSize.x * PIXELS_PER_METER);
                    int  roofTextureHeight   = Mathf.RoundToInt(largestSubmeshPlaneSize.y * PIXELS_PER_METER);
                    Rect newRoofTexutureRect = new Rect(0, 0, roofTextureWidth, roofTextureHeight);
                    packedTexturePositions.Add(newRoofTexutureRect);
                    roofTextures.Add(bTexture);
                    roofTextureIndex.Add(textureIndex);
                }
            }
        }

        //run a custom packer to define their postions
        textureWidth = RectanglePack.Pack(packedTexturePositions, ATLAS_PADDING);

        //determine the resize scale and apply that to the rects
        packedScale = 1;
        int numberOfRects = packedTexturePositions.Count;

        if (textureWidth > MAXIMUM_TEXTURESIZE)
        {
            packedScale = MAXIMUM_TEXTURESIZE / (float)textureWidth;
            for (int i = 0; i < numberOfRects; i++)
            {
                Rect thisRect = packedTexturePositions[i];
                thisRect.x               *= packedScale;
                thisRect.y               *= packedScale;
                thisRect.width           *= packedScale;
                thisRect.height          *= packedScale;
                packedTexturePositions[i] = thisRect;
                //Debug.Log("Rects "+roofTextures[i-+packedTexturePositions[i]);
            }
            textureWidth = Mathf.RoundToInt(packedScale * textureWidth);
        }
        else
        {
            textureWidth = (int)Mathf.Pow(2, (Mathf.FloorToInt(Mathf.Log(textureWidth - 1, 2)) + 1));//find the next power of two
        }

        textureSize = textureWidth * textureWidth;
        colourArray = new Color32[textureSize];
        //TestRectColours();//this test paints all the facades with rainbow colours - real pretty
        BuildTextures();

        Texture2D packedTexture = new Texture2D(textureWidth, textureWidth, TextureFormat.ARGB32, true);

        packedTexture.filterMode = FilterMode.Bilinear;
        packedTexture.SetPixels32(colourArray);
        packedTexture.Apply(true, false);

        if (data.OneDrawCallTexture != null)
        {
            Object.DestroyImmediate(data.OneDrawCallTexture);
        }
        data.OneDrawCallTexture      = packedTexture;
        data.OneDrawCallTexture.name = "One Draw Call Texture";

        int         numberOfRoofTextures   = roofTextures.Count - 1;
        List <Rect> facadeTexturePositions = new List <Rect>(packedTexturePositions);

        Debug.Log(numberOfRoofTextures);
        facadeTexturePositions.RemoveRange(packedTexturePositions.Count - numberOfRoofTextures, numberOfRoofTextures);

        BuildrBuilding.Build(mesh, data, facadeTexturePositions.ToArray());

        data     = null;
        mesh     = null;
        textures = null;


        System.GC.Collect();
    }
Example #28
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));
            }
        }
    }
Example #29
0
    private static void Barrel(BuildrVolume volume, BuildrRoofDesign design)
    {
        BuildrPlan area = data.plan;
        int numberOfFloors = volume.numberOfFloors;
        float floorHeight = data.floorHeight;
        Vector3 volumeFloorHeight = Vector3.up * (numberOfFloors * floorHeight);

        Vector3[] points = new Vector3[4];
        //Vector3 ridgeVector;
        if (design.direction == 0)
        {
            points[0] = area.points[volume.points[0]].vector3 + volumeFloorHeight;
            points[1] = area.points[volume.points[3]].vector3 + volumeFloorHeight;
            points[2] = area.points[volume.points[1]].vector3 + volumeFloorHeight;
            points[3] = area.points[volume.points[2]].vector3 + volumeFloorHeight;
        }
        else
        {
            points[0] = area.points[volume.points[1]].vector3 + volumeFloorHeight;
            points[1] = area.points[volume.points[0]].vector3 + volumeFloorHeight;
            points[2] = area.points[volume.points[2]].vector3 + volumeFloorHeight;
            points[3] = area.points[volume.points[3]].vector3 + volumeFloorHeight;
        }

        int barrelSegments = design.barrelSegments + 1;
        Vector3[] bPoints = new Vector3[barrelSegments * 2];
        for (int i = 0; i < barrelSegments; i++)
        {
            float lerp = (float)i / (float)(barrelSegments - 1);
            Vector3 height = Mathf.Sin(lerp * Mathf.PI) * design.height * Vector3.up;
            float cosLerp = 1 - (Mathf.Cos((lerp) * Mathf.PI) + 1) / 2;
            bPoints[i] = Vector3.Lerp(points[0], points[1], cosLerp) + height;
            bPoints[i + barrelSegments] = Vector3.Lerp(points[2], points[3], cosLerp) + height;
        }

        int topIterations = barrelSegments - 1;
        int subMesh = design.GetTexture(BuildrRoofDesign.textureNames.tiles);
        bool flipped = design.IsFlipped(BuildrRoofDesign.textureNames.tiles);
        for (int t = 0; t < topIterations; t++)
            AddPlane(design, bPoints[t + 1], bPoints[t], bPoints[t + barrelSegments + 1], bPoints[t + barrelSegments], subMesh, flipped);//top

        Vector3 centerA = Vector3.Lerp(points[0], points[1], 0.5f);
        Vector3 centerB = Vector3.Lerp(points[2], points[3], 0.5f);
        for (int e = 0; e < topIterations; e++)
        {
            float lerpA = ((float)(e) / (float)(topIterations)) * Mathf.PI;
            float lerpB = ((float)(e + 1) / (float)(topIterations)) * Mathf.PI;
            Vector2[] uvs = new Vector2[3]{
				new Vector2(0.5f,0),
				new Vector2(1-(Mathf.Cos(lerpA)+1)/2,Mathf.Sin(lerpA)),
				new Vector2(1-(Mathf.Cos(lerpB)+1)/2,Mathf.Sin(lerpB))
			};

            Vector3[] verts = new Vector3[3] { centerA, bPoints[e], bPoints[e + 1] };
            int[] tri = new int[3] { 0, 2, 1 };
            AddData(verts, uvs, tri, design.GetTexture(BuildrRoofDesign.textureNames.window));

            verts = new Vector3[3] { centerB, bPoints[e + barrelSegments], bPoints[e + 1 + barrelSegments] };
            tri = new int[3] { 0, 1, 2 };
            AddData(verts, uvs, tri, design.GetTexture(BuildrRoofDesign.textureNames.window));
        }
    }
Example #30
0
    private static void BuildSimple(DynamicMeshGenericMultiMaterialMesh _mesh, BuildrData _data)
    {
        BuildrData data = _data;
        DynamicMeshGenericMultiMaterialMesh mesh = _mesh;
        BuildrPlan plan = data.plan;

        int facadeIndex     = 0;
        int numberOfVolumes = data.plan.numberOfVolumes;

        //Build Floor
        if (data.drawUnderside)
        {
            for (int s = 0; s < numberOfVolumes; s++)
            {
                BuildrVolume volume = plan.volumes[s];
                int          numberOfVolumePoints = volume.points.Count;
                Vector3[]    newEndVerts          = new Vector3[numberOfVolumePoints];
                Vector2[]    newEndUVs            = new Vector2[numberOfVolumePoints];
                for (int i = 0; i < numberOfVolumePoints; i++)
                {
                    newEndVerts[i] = plan.points[volume.points[i]].vector3;
                    newEndUVs[i]   = Vector2.zero;
                }

                List <int> tris = new List <int>(data.plan.GetTrianglesBySectorBase(s));
                tris.Reverse();
                mesh.AddData(newEndVerts, newEndUVs, tris.ToArray(), 0);
            }
        }

        //Build ROOF
        DynamicMeshGenericMultiMaterialMesh dynMeshRoof = new DynamicMeshGenericMultiMaterialMesh();

        dynMeshRoof.subMeshCount = data.textures.Count;
        BuildrRoof.Build(dynMeshRoof, data, true);
        mesh.AddData(dynMeshRoof.vertices, dynMeshRoof.uv, dynMeshRoof.triangles, 0);

        Vector3 foundationVector = Vector3.down * data.foundationHeight;

        //Build facades
        for (int s = 0; s < numberOfVolumes; s++)
        {
            BuildrVolume volume = plan.volumes[s];
            int          numberOfVolumePoints = volume.points.Count;

            for (int l = 0; l < numberOfVolumePoints; l++)
            {
                int     indexA = l;
                int     indexB = (l < numberOfVolumePoints - 1) ? l + 1 : 0;
                Vector3 p0     = plan.points[volume.points[indexA]].vector3;
                Vector3 p1     = plan.points[volume.points[indexB]].vector3;

                int floorBase      = plan.GetFacadeFloorHeight(s, volume.points[indexA], volume.points[indexB]);
                int numberOfFloors = volume.numberOfFloors - floorBase;
                if (numberOfFloors < 1)
                {
                    //no facade - adjacent facade is taller and covers this one
                    continue;
                }
                float floorHeight = data.floorHeight;

                Vector3 floorHeightStart = Vector3.up * (floorBase * floorHeight);
                Vector3 wallHeight       = Vector3.up * (volume.numberOfFloors * floorHeight) - floorHeightStart;

                p0 += floorHeightStart;
                p1 += floorHeightStart;

                Vector3 w0 = p0;
                Vector3 w1 = p1;
                Vector3 w2 = w0 + wallHeight;
                Vector3 w3 = w1 + wallHeight;

                if (floorBase == 0)
                {
                    w0 += foundationVector;
                    w1 += foundationVector;
                }

                mesh.AddPlane(w0, w1, w2, w3, Vector2.zero, Vector2.zero, 0);
                facadeIndex++;
            }
        }

        data = null;
        mesh = null;
    }
Example #31
0
    private static void Sawtooth(BuildrVolume volume, BuildrRoofDesign design)
    {
        BuildrPlan area = data.plan;
        int numberOfFloors = volume.numberOfFloors;
        float floorHeight = data.floorHeight;
        Vector3 volumeFloorHeight = Vector3.up * (numberOfFloors * floorHeight);
        Vector3 ridgeVector = Vector3.up * design.height;

        int[] pointIndexes = new int[4];
        switch (design.direction)
        {
            case 0:
                pointIndexes = new int[4] { 0, 1, 2, 3 };
                break;
            case 1:
                pointIndexes = new int[4] { 1, 2, 3, 0 };
                break;
            case 2:
                pointIndexes = new int[4] { 2, 3, 0, 1 };
                break;
            case 3:
                pointIndexes = new int[4] { 3, 0, 1, 2 };
                break;
        }
        Vector3[] basepoints = new Vector3[4];
        Vector3[] points = new Vector3[6];

        for (int i = 0; i < design.sawtoothTeeth; i++)
        {

            Vector3 toothBaseMovementA = (area.points[volume.points[pointIndexes[3]]].vector3 - area.points[volume.points[pointIndexes[0]]].vector3).normalized;
            float roofDepthA = Vector3.Distance(area.points[volume.points[pointIndexes[3]]].vector3, area.points[volume.points[pointIndexes[0]]].vector3);
            float toothDepthA = roofDepthA / design.sawtoothTeeth;
            Vector3 toothVectorA = toothBaseMovementA * toothDepthA;

            Vector3 toothBaseMovementB = (area.points[volume.points[pointIndexes[2]]].vector3 - area.points[volume.points[pointIndexes[1]]].vector3).normalized;
            float roofDepthB = Vector3.Distance(area.points[volume.points[pointIndexes[2]]].vector3, area.points[volume.points[pointIndexes[1]]].vector3);
            float toothDepthB = roofDepthB / design.sawtoothTeeth;
            Vector3 toothVectorB = toothBaseMovementB * toothDepthB;

            basepoints[0] = area.points[volume.points[pointIndexes[0]]].vector3 + toothVectorA * i;
            basepoints[1] = area.points[volume.points[pointIndexes[1]]].vector3 + toothVectorB * i;
            basepoints[2] = basepoints[1] + toothVectorB;
            basepoints[3] = basepoints[0] + toothVectorA;

            points[0] = basepoints[0] + volumeFloorHeight;
            points[1] = basepoints[1] + volumeFloorHeight;
            points[2] = basepoints[2] + volumeFloorHeight;
            points[3] = basepoints[3] + volumeFloorHeight;
            points[4] = basepoints[2] + volumeFloorHeight + ridgeVector;
            points[5] = basepoints[3] + volumeFloorHeight + ridgeVector;

            //top
            int subMeshTop = design.GetTexture(BuildrRoofDesign.textureNames.tiles);
            bool flippedTop = design.IsFlipped(BuildrRoofDesign.textureNames.tiles);
            AddPlane(design, points[0], points[1], points[5], points[4], subMeshTop, flippedTop);

            //window
            int subMeshWindow = design.GetTexture(BuildrRoofDesign.textureNames.window);
            bool flippedWindow = design.IsFlipped(BuildrRoofDesign.textureNames.window);
            AddPlane(design, points[2], points[3], points[4], points[5], subMeshWindow, flippedWindow);

            //sides
            Vector3[] vertsA = new Vector3[3] { points[1], points[2], points[4] };
            Vector3[] vertsB = new Vector3[3] { points[0], points[3], points[5] };
            float uvWdith = Vector3.Distance(points[0], points[3]);
            float uvHeight = design.height;
            int subMesh = design.GetTexture(BuildrRoofDesign.textureNames.wall);
            BuildrTexture texture = textures[subMesh];

            if (texture.tiled)
            {
                uvWdith *= (1.0f / texture.textureUnitSize.x);
                uvHeight *= (1.0f / texture.textureUnitSize.y);
                if (texture.patterned)
                {
                    Vector2 uvunits = texture.tileUnitUV;
                    uvWdith = Mathf.Ceil(uvWdith / uvunits.x) * uvunits.x;
                    uvHeight = Mathf.Ceil(uvHeight / uvunits.y) * uvunits.y;
                }
            }
            else
            {
                uvWdith = texture.tiledX;
                uvHeight = texture.tiledY;
            }

            Vector2[] uvs = new Vector2[3] { new Vector2(0, 0), new Vector2(uvWdith, 0), new Vector2(uvWdith, uvHeight) };
            int[] triA = new int[3] { 1, 0, 2 };
            int[] triB = new int[3] { 0, 1, 2 };
            AddData(vertsA, uvs, triA, subMesh);
            AddData(vertsB, uvs, triB, subMesh);

        }
    }
Example #32
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();
            }
        }
    }
Example #33
0
    private static void Hipped(BuildrVolume volume, BuildrRoofDesign design)
    {
        BuildrPlan area = data.plan;
        int numberOfFloors = volume.numberOfFloors;
        float baseHeight = data.floorHeight * numberOfFloors;
        float roofHeight = design.height;
        int numberOfVolumePoints = volume.points.Count;
        int subMesh = design.GetTexture(BuildrRoofDesign.textureNames.tiles);

        Vector2[] volumePoints = new Vector2[numberOfVolumePoints];
        for(int i = 0; i < numberOfVolumePoints; i++)
        {
            volumePoints[i] = area.points[volume.points[i]].vector2;
        }

        Vector2[][] meshData = StraightSkeleton.Calculate(volumePoints);
        Vector2[] triData = meshData[0];
        List<Vector2> interiorPoints = new List<Vector2>(meshData[1]);
        int numberOfVerts = triData.Length;
        Vector3[] verts = new Vector3[numberOfVerts];
        Vector2[] uvs = new Vector2[numberOfVerts];
        int[] tris = new int[numberOfVerts];
        for(int i = 0; i < triData.Length; i+=3)
        {
            Vector2 pa = triData[i];
            Vector2 pb = triData[i+1];
            Vector2 pc = triData[i+2];

            float ah = baseHeight + (interiorPoints.Contains(pa) ? roofHeight : 0);
            float bh = baseHeight + (interiorPoints.Contains(pb) ? roofHeight : 0);
            float ch = baseHeight + (interiorPoints.Contains(pc) ? roofHeight : 0);

            Vector3 v0 = new Vector3(pa.x, ah, pa.y);
            Vector3 v1 = new Vector3(pb.x, bh, pb.y);
            Vector3 v2 = new Vector3(pc.x, ch, pc.y);

            verts[i] = v0;
            verts[i+1] = v1;
            verts[i+2] = v2;

            Vector3 roofBaseDir = (interiorPoints.Contains(pc)) ? v1 - v0 : v2 - v1;
            Vector3 roofBaseNormal = Vector3.Cross(roofBaseDir, Vector3.up);
            Vector2[] uvsMansard = BuildrProjectUVs.Project(new Vector3[3] { v0, v1, v2 }, Vector2.zero, roofBaseNormal);

            uvs[i] = uvsMansard[0];
            uvs[i + 1] = uvsMansard[1];
            uvs[i + 2] = uvsMansard[2];

            tris[i] = i;
            tris[i + 1] = i+2;
            tris[i + 2] = i+1;
        }

        AddData(verts,uvs,tris,subMesh);

        /*Vector3 ridgeVector = Vector3.up * design.height;

        Vector3[] basePoints = new Vector3[4];
        if (design.direction == 0)
        {
            basePoints[0] = area.points[volume.points[0]].vector3 + volumeFloorHeight;
            basePoints[1] = area.points[volume.points[1]].vector3 + volumeFloorHeight;
            basePoints[2] = area.points[volume.points[2]].vector3 + volumeFloorHeight;
            basePoints[3] = area.points[volume.points[3]].vector3 + volumeFloorHeight;
        }
        else
        {
            basePoints[0] = area.points[volume.points[1]].vector3 + volumeFloorHeight;
            basePoints[1] = area.points[volume.points[2]].vector3 + volumeFloorHeight;
            basePoints[2] = area.points[volume.points[3]].vector3 + volumeFloorHeight;
            basePoints[3] = area.points[volume.points[0]].vector3 + volumeFloorHeight;
        }
        Vector3 centrePoint = Vector3.zero;
        for (int l = 0; l < 4; l++)
            centrePoint += area.points[volume.points[l]].vector3;
        centrePoint = (centrePoint / 4) + volumeFloorHeight + ridgeVector;

        Vector3 r0 = Vector3.Lerp(basePoints[0], basePoints[1], 0.5f) + ridgeVector;
        Vector3 r1 = Vector3.Lerp(basePoints[2], basePoints[3], 0.5f) + ridgeVector;
        Vector3 ridgeDirection = (r1 - r0);
        float roofLength = Vector3.Distance(r0, r1);
        float ridgeLengthA = Vector3.Distance(basePoints[0], basePoints[1]);
        if (ridgeLengthA > roofLength)
            ridgeLengthA = roofLength;
        float ridgeLengthB = Vector3.Distance(basePoints[2], basePoints[3]);
        if (ridgeLengthB > roofLength)
            ridgeLengthB = roofLength;
        r0 += ridgeDirection.normalized * ridgeLengthA / 2;
        r1 += -ridgeDirection.normalized * ridgeLengthB / 2;

        int subMesh = design.GetTexture(BuildrRoofDesign.textureNames.tiles);
        bool flipped = design.IsFlipped(BuildrRoofDesign.textureNames.tiles);
        AddPlane(design, basePoints[0], r0, basePoints[3], r1, subMesh, flipped);//top
        AddPlane(design, basePoints[2], r1, basePoints[1], r0, subMesh, flipped);//top

        Vector3[] vertsA = new Vector3[3] { basePoints[0], basePoints[1], r0 };
        Vector3[] vertsB = new Vector3[3] { basePoints[2], basePoints[3], r1 };
        float uvWdithA = Vector3.Distance(basePoints[0], basePoints[1]);
        float uvWdithB = Vector3.Distance(basePoints[2], basePoints[3]);
        float uvHeight = design.height;
        BuildrTexture texture = textures[subMesh];

        if (texture.tiled)
        {
            uvWdithA *= (1.0f / texture.textureUnitSize.x);
            uvWdithB *= (1.0f / texture.textureUnitSize.x);
            uvHeight *= (1.0f / texture.textureUnitSize.y);
            if (texture.patterned)
            {
                Vector2 uvunits = texture.tileUnitUV;
                uvWdithA = Mathf.Ceil(uvWdithA / uvunits.x) * uvunits.x;
                uvWdithB = Mathf.Ceil(uvWdithB / uvunits.x) * uvunits.x;
                uvHeight = Mathf.Ceil(uvHeight / uvunits.y) * uvunits.y;
            }
        }
        else
        {
            uvWdithA = texture.tiledX;
            uvWdithB = texture.tiledX;
            uvHeight = texture.tiledY;
        }
        Vector2[] uvsA = new Vector2[3] { new Vector2(-uvWdithA / 2, 0), new Vector2(uvWdithA / 2, 0), new Vector2(0, uvHeight) };
        Vector2[] uvsB = new Vector2[3] { new Vector2(-uvWdithB / 2, 0), new Vector2(uvWdithB / 2, 0), new Vector2(0, uvHeight) };
        int[] tri = new int[3] { 1, 0, 2 };
        AddData(vertsA, uvsA, tri, subMesh);
        AddData(vertsB, uvsB, tri, subMesh);*/
    }
Example #34
0
    public static void InspectorGUI(BuildrEditMode editMode, BuildrData _data)
    {
        data = _data;
        Undo.RecordObject(data, "Building Modified");
        BuildrPlan plan = data.plan;
        int        numberOfFacadeFaces   = 0;
        int        numberOfVolumes       = plan.numberOfVolumes;
        int        numberOfFacadeDesigns = data.facades.Count;

        if (numberOfVolumes == 0)
        {
            EditorGUILayout.HelpBox("There are no defined volumes, go to Floorplan and define one", MessageType.Error);
            return;
        }

        int numberOfFacades  = data.facades.Count;
        int numberOfRoofs    = data.roofs.Count;
        int numberOfTextures = data.textures.Count;

        bool legalBuilding = true;

        if (numberOfFacades == 0)
        {
            EditorGUILayout.HelpBox("There are no facade designs to render building, go to Facades to define a default one", MessageType.Error);
            legalBuilding = false;
        }
        if (numberOfRoofs == 0)
        {
            EditorGUILayout.HelpBox("There are no roof designs to render building, go to Facades to define a default one", MessageType.Error);
            legalBuilding = false;
        }
        if (numberOfTextures == 0)
        {
            EditorGUILayout.HelpBox("There are no textures to render building, go to Textures to define a default one", MessageType.Error);
            legalBuilding = false;
        }

        if (!legalBuilding)
        {
            return;
        }

        //Building Name
        EditorGUILayout.Space();
        EditorGUILayout.Space();
        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Name", GUILayout.Width(200));
        data.name = EditorGUILayout.TextField(data.name, GUILayout.Width(200));
        EditorGUILayout.EndHorizontal();

        //Floor Height
        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Floor height", GUILayout.Width(200));
        data.floorHeight = EditorGUILayout.FloatField(data.floorHeight, GUILayout.Width(50));
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Number of Floors", GUILayout.Width(200));
        int[]    volumeSeletionsList       = new int[numberOfVolumes];
        string[] volumeSeletionsStringList = new string[numberOfVolumes];
        for (int s = 0; s < numberOfVolumes; s++)
        {
            volumeSeletionsStringList[s] = ("volume " + s);
            volumeSeletionsList[s]       = (s);
        }

        selectedFloorNumberVolume = EditorGUILayout.IntPopup(selectedFloorNumberVolume, volumeSeletionsStringList, volumeSeletionsList, GUILayout.Width(100));
        int numberOfFloors = EditorGUILayout.IntField(data.plan.volumes[selectedFloorNumberVolume].numberOfFloors);

        if (GUILayout.Button("^"))
        {
            numberOfFloors++;
        }
        if (GUILayout.Button("v"))
        {
            numberOfFloors--;
        }
        data.plan.volumes[selectedFloorNumberVolume].numberOfFloors = Mathf.Max(numberOfFloors, 1);
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Show Facade Markers", GUILayout.Width(200));
        editMode.showFacadeMarkers = EditorGUILayout.Toggle(editMode.showFacadeMarkers, GUILayout.Width(200));
        EditorGUILayout.EndHorizontal();
        EditorGUILayout.Space();

        GUIStyle titlesyle = new GUIStyle(GUI.skin.label);

        titlesyle.fixedHeight      = 60;
        titlesyle.fixedWidth       = 400;
        titlesyle.alignment        = TextAnchor.UpperCenter;
        titlesyle.fontStyle        = FontStyle.Bold;
        titlesyle.normal.textColor = Color.white;

        EditorGUILayout.LabelField("Facade Design", titlesyle);
        Texture2D facadeTexture = new Texture2D(1, 1);

        facadeTexture.SetPixel(0, 0, BuildrColours.MAGENTA);
        facadeTexture.Apply();
        Rect sqrPos = new Rect(0, 0, 0, 0);

        if (Event.current.type == EventType.Repaint)
        {
            sqrPos = GUILayoutUtility.GetLastRect();
        }
        GUI.DrawTexture(sqrPos, facadeTexture);
        EditorGUI.LabelField(sqrPos, "Facade Design", titlesyle);

        //create/display the facade selector
        List <int>    facadeSeletionsList       = new List <int>();
        List <int>    facadeRenderList          = new List <int>();
        List <string> facadeSeletionsStringList = new List <string>();

        for (int s = 0; s < numberOfVolumes; s++)
        {
            int numberOfPoints = plan.volumes[s].Count;
            numberOfFacadeFaces += numberOfPoints;
            for (int p = 0; p < numberOfPoints; p++)
            {
                int index = facadeSeletionsList.Count;
                facadeSeletionsStringList.Add("facade " + index);
                facadeSeletionsList.Add(index);
                facadeRenderList.Add(p);
            }
        }
        int[]    facadeSelections      = facadeSeletionsList.ToArray();
        string[] facadeSelectionString = facadeSeletionsStringList.ToArray();

        selectedFacade = EditorGUILayout.IntPopup("Selected Facade", selectedFacade, facadeSelectionString, facadeSelections, GUILayout.Width(400));

        //grab the selected facade
        int facadeCount         = 0;
        int selectedVolumePoint = 0;

        for (int s = 0; s < numberOfVolumes; s++)
        {
            int numberOfPoints = plan.volumes[s].Count;
            for (int p = 0; p < numberOfPoints; p++)
            {
                if (selectedFacade == facadeCount)
                {
                    selectedVolume      = s;
                    selectedVolumePoint = p;
                    selectedPoint       = plan.volumes[s].points[p];
                }
                facadeCount++;
            }
        }

        BuildrVolume volume = plan.volumes[selectedVolume];

        BuildrVolumeStylesUnit[] styles = volume.styles.GetContents();

        bool renderFacade = volume.renderFacade[selectedVolumePoint];

        volume.renderFacade[selectedVolumePoint] = EditorGUILayout.Toggle("Render Facade", renderFacade);

        //ensure the selected style isn't out of bounds
        int numberOfStyles = styles.Length;

        if (selectedStyle >= numberOfStyles)
        {
            selectedStyle = 0;
        }

        //compose a list of style ids from the volume style library
        List <int> entryNum = new List <int>();

        for (int s = 0; s < numberOfStyles; s++)
        {
            if (selectedPoint == styles[s].facadeID)
            {
                entryNum.Add(s);
            }
        }

        int numberOfFacadeStyles = entryNum.Count;

        if (GUILayout.Button("Add style to facade", GUILayout.Width(400)))
        {
            volume.styles.AddStyle(0, selectedPoint, 1);
        }

        GUILayout.BeginHorizontal("box");
        GUILayout.BeginHorizontal("box");
        EditorGUILayout.LabelField("Style", GUILayout.Width(160));
        GUILayout.EndHorizontal();
        GUILayout.BeginHorizontal("box");
        GUILayout.Label("Floors", GUILayout.Width(78));
        GUILayout.EndHorizontal();
        GUILayout.BeginHorizontal("box");
        GUILayout.Label("Position", GUILayout.Width(54));
        GUILayout.EndHorizontal();
        GUILayout.BeginHorizontal("box");
        GUILayout.Label(" ", GUILayout.Width(55));
        GUILayout.EndHorizontal();
        GUILayout.EndHorizontal();

        for (int s = 0; s < numberOfFacadeStyles; s++)
        {
            int index = entryNum[s];
            BuildrVolumeStylesUnit styleUnit = styles[index];

            GUILayout.BeginHorizontal("box");
            GUILayout.BeginHorizontal("box");
            string[] facadeNames = new string[numberOfFacadeDesigns];
            for (int f = 0; f < numberOfFacadeDesigns; f++)
            {
                facadeNames[f] = data.facades[f].name;
            }
            int selectedFacadeDesign = EditorGUILayout.Popup(styleUnit.styleID, facadeNames, GUILayout.Width(160));
            if (selectedFacadeDesign != styleUnit.styleID)
            {
                volume.styles.ModifyStyle(index, selectedFacadeDesign);
            }
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal("box");
            int currentFloors = styleUnit.floors;

            currentFloors = EditorGUILayout.IntField(currentFloors, GUILayout.Width(20));
            if (GUILayout.Button("+", GUILayout.Width(25)))
            {
                currentFloors++;
            }
            EditorGUI.BeginDisabledGroup(currentFloors < 2);
            if (GUILayout.Button("-", GUILayout.Width(25)))
            {
                currentFloors--;
            }
            EditorGUI.EndDisabledGroup();
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal("box");
            EditorGUI.BeginDisabledGroup((s < 1));
            {
                if (GUILayout.Button("^", GUILayout.Width(25)))
                {
                    volume.styles.MoveEntry(entryNum[s], entryNum[s - 1] + 1);
                    GUI.changed = true;
                }
            }
            EditorGUI.EndDisabledGroup();
            EditorGUI.BeginDisabledGroup((s > numberOfFacadeStyles - 2));
            {
                if (GUILayout.Button("v", GUILayout.Width(25)))
                {
                    volume.styles.MoveEntry(entryNum[s], entryNum[s + 1] + 1);
                    GUI.changed = true;
                }
            }
            EditorGUI.EndDisabledGroup();
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal("box");
            if (GUILayout.Button("remove", GUILayout.Width(55)))
            {
                volume.styles.RemoveStyle(index);
            }
            GUILayout.EndHorizontal();
            GUILayout.EndHorizontal();

            if (currentFloors != styleUnit.floors)
            {
                volume.styles.ModifyFloors(index, currentFloors);
                GUI.changed = true;
            }
        }
        EditorGUILayout.Space();

        titlesyle                  = new GUIStyle(GUI.skin.label);
        titlesyle.fixedHeight      = 60;
        titlesyle.fixedWidth       = 400;
        titlesyle.alignment        = TextAnchor.UpperCenter;
        titlesyle.fontStyle        = FontStyle.Bold;
        titlesyle.normal.textColor = Color.black;

        EditorGUILayout.LabelField("Roof Design", titlesyle);
        facadeTexture = new Texture2D(1, 1);
        facadeTexture.SetPixel(0, 0, BuildrColours.CYAN);
        facadeTexture.Apply();
        sqrPos = new Rect(0, 0, 0, 0);
        if (Event.current.type == EventType.Repaint)
        {
            sqrPos = GUILayoutUtility.GetLastRect();
        }
        GUI.DrawTexture(sqrPos, facadeTexture);
        EditorGUI.LabelField(sqrPos, "Roof Design", titlesyle);



        //create/display the roof selector
        volumeSeletionsList       = new int[numberOfVolumes];
        volumeSeletionsStringList = new string[numberOfVolumes];
        for (int s = 0; s < numberOfVolumes; s++)
        {
            volumeSeletionsStringList[s] = ("volume " + s);
            volumeSeletionsList[s]       = (s);
        }

        selectedRoofVolume = EditorGUILayout.IntPopup("Selected Volume", selectedRoofVolume, volumeSeletionsStringList, volumeSeletionsList, GUILayout.Width(400));

        string[] roofNames = new string[numberOfRoofs];
        int[]    roofList  = new int[numberOfRoofs];
        for (int r = 0; r < numberOfRoofs; r++)
        {
            roofList[r]  = r;
            roofNames[r] = data.roofs[r].name;
        }

        volume = data.plan.volumes[selectedRoofVolume];
        volume.roofDesignID = EditorGUILayout.IntPopup("Selected Roof Design", volume.roofDesignID, roofNames, roofList, GUILayout.Width(400));
    }
Example #35
0
    private static void Parapet(BuildrVolume volume, BuildrRoofDesign design)
    {
        BuildrPlan area = data.plan;
        int volumeIndex = area.volumes.IndexOf(volume);
        int numberOfVolumePoints = volume.points.Count;
        int numberOfFloors = volume.numberOfFloors;
        float floorHeight = data.floorHeight;
        Vector3 volumeFloorHeight = Vector3.up * (numberOfFloors * floorHeight);

        for (int l = 0; l < numberOfVolumePoints; l++)
        {

            int indexA, indexB, indexA0, indexB0;
            Vector3 p0, p1, p00, p10;
            indexA = l;
            indexB = (l < numberOfVolumePoints - 1) ? l + 1 : 0;
            indexA0 = (l > 0) ? l - 1 : numberOfVolumePoints - 1;
            indexB0 = (l < numberOfVolumePoints - 2) ? l + 2 : l + 2 - numberOfVolumePoints;

            int adjacentFloorHeight = area.GetFacadeFloorHeight(volumeIndex, volume.points[indexA], volume.points[indexB]);
            bool leftParapet = area.GetFacadeFloorHeight(volumeIndex, volume.points[indexA0], volume.points[indexA]) < numberOfFloors;
            bool rightParapet = area.GetFacadeFloorHeight(volumeIndex, volume.points[indexB], volume.points[indexB0]) < numberOfFloors;

            if (adjacentFloorHeight >= numberOfFloors)
                continue;//do not draw a roof edge

            p0 = area.points[volume.points[indexA]].vector3;
            p1 = area.points[volume.points[indexB]].vector3;
            p00 = area.points[volume.points[indexA0]].vector3;
            p10 = area.points[volume.points[indexB0]].vector3;

            float facadeWidth = Vector3.Distance(p0, p1);
            Vector3 facadeDirection = (p1 - p0).normalized;
            Vector3 facadeDirectionLeft = (p0 - p00).normalized;
            Vector3 facadeDirectionRight = (p10 - p1).normalized;
            Vector3 facadeNormal = Vector3.Cross(facadeDirection, Vector3.up);
            Vector3 facadeNormalLeft = Vector3.Cross(facadeDirectionLeft, Vector3.up);
            Vector3 facadeNormalRight = Vector3.Cross(facadeDirectionRight, Vector3.up);

            float parapetHeight = design.parapetHeight;
            float parapetFrontDepth = design.parapetFrontDepth;
            float parapetBackDepth = design.parapetBackDepth;

            Vector3 w0, w1, w2, w3, w4, w5, w6, w7;
            Vector3 pr = facadeDirection * facadeWidth;
            Vector3 pu = Vector3.up * parapetHeight;

            Vector3 pbdl, pbdr, pfdl, pfdr;
            if (leftParapet)
            {
                pbdl = -(facadeNormal + facadeNormalLeft).normalized * parapetFrontDepth;
                pfdl = (facadeNormal + facadeNormalLeft).normalized * parapetBackDepth;
            }
            else
            {
                pbdl = facadeDirectionLeft * parapetFrontDepth;
                pfdl = -facadeDirectionLeft * parapetBackDepth;
            }
            if (rightParapet)
            {
                pbdr = -(facadeNormal + facadeNormalRight).normalized * parapetFrontDepth;
                pfdr = (facadeNormal + facadeNormalRight).normalized * parapetBackDepth;
            }
            else
            {
                pbdr = -facadeDirectionRight * parapetFrontDepth;
                pfdr = facadeDirectionRight * parapetBackDepth;
            }

            p0 += volumeFloorHeight;
            p1 += volumeFloorHeight;

            w2 = p0 + pbdl;//front left
            w3 = p0 + pr + pbdr;//front right
            w0 = p0 + pfdl;//back left
            w1 = p0 + pr + pfdr;//back right
            w6 = p0 + pbdl + pu;//front left top
            w7 = p0 + pr + pbdr + pu;//front right top
            w4 = p0 + pfdl + pu;//back left top
            w5 = p0 + pr + pfdr + pu;//back right top

            int subMesh = design.GetTexture(BuildrRoofDesign.textureNames.parapet);
            bool flipped = design.IsFlipped(BuildrRoofDesign.textureNames.parapet);
            AddPlane(design, w1, w0, w5, w4, subMesh, flipped);//front
            AddPlaneComplex(design, w6, w7, w4, w5, subMesh, flipped, facadeNormal);//top
            AddPlane(design, w2, w3, w6, w7, subMesh, flipped);//back

            if (parapetFrontDepth > 0)
                AddPlaneComplex(design, w3, w2, w1, w0, subMesh, flipped, facadeNormal);//bottom

            if (!leftParapet)
                AddPlane(design, w0, w2, w4, w6, subMesh, flipped);//left cap

            if (!rightParapet)
                AddPlane(design, w3, w1, w7, w5, subMesh, flipped);//left cap
        }
    }
Example #36
0
    public static void SceneGUI(BuildrEditMode editMode, BuildrData _data, bool shouldSnap, float handleSize)
    {
        data = _data;
        Vector3 camDirection = Camera.current.transform.forward;
        Vector3 camPosition  = Camera.current.transform.position;

        int numberOfFacades  = data.facades.Count;
        int numberOfRoofs    = data.roofs.Count;
        int numberOfTextures = data.textures.Count;

        if (numberOfFacades == 0 || numberOfRoofs == 0 || numberOfTextures == 0)
        {
            return;
        }

        Vector3 position    = editMode.transform.position;
        float   floorHeight = data.floorHeight;

        BuildrPlan area            = data.plan;
        int        numberOfVolumes = area.numberOfVolumes;

        int facadeCounter = 0;

        for (int s = 0; s < numberOfVolumes; s++)
        {
            BuildrVolume volume      = data.plan.volumes[s];
            int          volumeSize  = volume.Count;
            Vector3      floorCentre = Vector3.zero;
            Handles.color = Color.white;

            for (int p = 0; p < volumeSize; p++)
            {
                int     point    = volume.points[p];
                Vector3 pointPos = area.points[point].vector3;
                floorCentre += pointPos;

                List <Vector3> verts        = new List <Vector3>();
                int            indexB       = (p < volumeSize - 1) ? p + 1 : 0;
                Vector3        volumeHeight = Vector3.up * (volume.numberOfFloors * data.floorHeight);
                verts.Add(pointPos + position);
                verts.Add(area.points[volume.points[indexB]].vector3 + position);
                verts.Add(verts[1] + volumeHeight);
                verts.Add(verts[0] + volumeHeight);
                if (s == selectedVolume && point == selectedPoint)
                {
                    //display something to highlight this facade
                    Handles.DrawSolidRectangleWithOutline(verts.ToArray(), Color.clear, BuildrColours.MAGENTA);
                }
                Handles.color = BuildrColours.CYAN;
                if (s == selectedRoofVolume)
                {
                    Handles.DrawLine(verts[2], verts[3]);
                }
                if (editMode.showFacadeMarkers)
                {
                    Handles.color = Color.white;
                    Vector3  facadeDirection  = Vector3.Cross((verts[0] - verts[1]), Vector3.up);
                    GUIStyle facadeLabelStyle = new GUIStyle();
                    facadeLabelStyle.normal.textColor = Color.white;
                    facadeLabelStyle.alignment        = TextAnchor.MiddleCenter;
                    facadeLabelStyle.fixedWidth       = 75.0f;
                    Vector3 centerPos     = (verts[0] + verts[1]) * 0.5f;
                    bool    camVisible    = Vector3.Dot(camDirection, centerPos - camPosition) > 0;
                    bool    facadeVisible = Vector3.Dot(camDirection, facadeDirection) < 0;
                    if (camVisible && facadeVisible)//only display label when facade is facing camera and is in camera view
                    {
                        Vector3 labelPos = centerPos + facadeDirection.normalized;
                        Handles.Label(labelPos, "facade " + facadeCounter, facadeLabelStyle);
                        Handles.DrawLine(centerPos, labelPos);
                    }
                }
                facadeCounter++;
            }
            floorCentre /= volumeSize;

            //Volume height/floor number slider
            Vector3 volumeHeightDir = Vector3.up * (volume.numberOfFloors * data.floorHeight);
            Vector3 volumePosition  = floorCentre + position + volumeHeightDir;
            if (Vector3.Dot(camDirection, volumePosition - camPosition) > 0)//only display label when facade is facing camera
            {
                Handles.Label(volumePosition + (Vector3.up * (handleSize * 0.1f)), "volume " + s);
                Handles.Label(volumePosition, "number of floors " + volume.numberOfFloors);
            }
            Handles.color = Color.green;
            volume.height = Handles.Slider(volumePosition, Vector3.up).y - position.y;
            if (volume.height < data.floorHeight)
            {
                volume.height = data.floorHeight;
            }

            volume.numberOfFloors = Mathf.RoundToInt(volume.height / floorHeight);
        }
    }
Example #37
0
    private static void FlatRoof(BuildrVolume volume, BuildrRoofDesign design)
    {
        BuildrPlan area = data.plan;
        int volumeIndex = area.volumes.IndexOf(volume);
        int numberOfVolumePoints = volume.points.Count;
        int numberOfFloors = volume.numberOfFloors;
        float floorHeight = data.floorHeight;
        Vector3 volumeFloorHeight = Vector3.up * (numberOfFloors * floorHeight);

        //add top base of the flat roof
        Vector3[] newEndVerts = new Vector3[numberOfVolumePoints];
        Vector2[] newEndUVs = new Vector2[numberOfVolumePoints];
        int[] tris = new List<int>(area.GetTrianglesBySectorBase(volumeIndex)).ToArray();
        int roofTextureID = design.GetTexture(BuildrRoofDesign.textureNames.floor);
        BuildrTexture texture = data.textures[roofTextureID];
        for (int i = 0; i < numberOfVolumePoints; i++)
        {
            Vector2z point = area.points[volume.points[i]];
            newEndVerts[i] = point.vector3 + volumeFloorHeight;
            newEndUVs[i] = new Vector2(point.vector2.x / texture.textureUnitSize.x, point.vector2.y / texture.textureUnitSize.y);
        }

        AddData(newEndVerts, newEndUVs, tris, design.GetTexture(BuildrRoofDesign.textureNames.floor));
    }
Example #38
0
    private static void GenerateFacades(BuildrData data)
    {
        BuildrGenerateConstraints constraints = data.generatorConstraints;
        RandomGen rgen = constraints.rgen;

        //generate bays
        //blank
        BuildrBay blankBay = new BuildrBay("Blank");

        blankBay.isOpening = false;
        data.bays.Add(blankBay);
        //door
        BuildrBay doorBay = new BuildrBay("Door");

        doorBay.openingHeight      = data.floorHeight * 0.9f;
        doorBay.openingHeightRatio = 0.0f;
        float doorWidth = (doorTexture.texture.width / (float)doorTexture.texture.height) * doorBay.openingHeight;

        doorBay.openingWidth = doorWidth;
        doorBay.openingDepth = rgen.OutputRange(0.0f, 0.3f);
        doorBay.SetTexture(BuildrBay.TextureNames.OpeningBackTexture, data.textures.IndexOf(doorTexture));
        data.bays.Add(doorBay);
        //ground window
        BuildrBay groundWindow = new BuildrBay("Ground Window");

        groundWindow.openingWidth       = rgen.OutputRange(constraints.openingMinimumWidth, constraints.openingMaximumWidth);
        groundWindow.openingHeight      = rgen.OutputRange(constraints.openingMinimumHeight, Mathf.Min(data.floorHeight, constraints.openingMinimumHeight));
        groundWindow.openingDepth       = rgen.OutputRange(constraints.openingMinimumDepth, constraints.openingMaximumDepth);
        groundWindow.openingHeightRatio = 0.8f;
        data.bays.Add(groundWindow);

//        BuildrTexture groundFloorWindowTexture = windowTexture.Duplicate("groundWindowTexture");
        groundFloorWindowTexture.tiled  = false;
        groundFloorWindowTexture.tiledX = Mathf.RoundToInt(groundWindow.openingWidth / groundWindow.openingHeight);
        int groundtextureIndex = data.textures.IndexOf(groundFloorWindowTexture);

//        data.textures.Add(groundFloorWindowTexture);
        groundWindow.SetTexture(BuildrBay.TextureNames.OpeningBackTexture, groundtextureIndex);
        //other windows
        BuildrBay windowBay = new BuildrBay("Window");

        data.bays.Add(windowBay);
        //util window
        BuildrBay utilBay = new BuildrBay("Utility Window");

        data.bays.Add(utilBay);

        //generate facades
        BuildrFacadeDesign basicFacadeDesign = new BuildrFacadeDesign("default");

        basicFacadeDesign.simpleBay.openingWidth  = rgen.OutputRange(constraints.openingMinimumWidth, constraints.openingMaximumWidth);
        basicFacadeDesign.simpleBay.openingHeight = rgen.OutputRange(constraints.openingMinimumHeight, Mathf.Min(data.floorHeight, constraints.openingMinimumHeight));
        basicFacadeDesign.simpleBay.openingDepth  = rgen.OutputRange(constraints.openingMinimumDepth, constraints.openingMaximumDepth);
//        float roughBaySize = basicFacadeDesign.simpleBay.openingHeight + basicFacadeDesign.simpleBay.openingWidth;
        basicFacadeDesign.simpleBay.minimumBayWidth = rgen.OutputRange(constraints.minimumBayMaximumWidth, constraints.minimumBayMaximumWidth);
        data.facades.Add(basicFacadeDesign);
        //ground floor with and without door
        BuildrFacadeDesign groundFloorDoor = new BuildrFacadeDesign("Ground Floor With Door");

        groundFloorDoor.type = BuildrFacadeDesign.types.patterned;
        int patternSize = rgen.OutputRange(1, 8);

        for (int i = 0; i < patternSize; i++)
        {
            groundFloorDoor.bayPattern.Add(rgen.output > 0.2f?2:0);
        }
        groundFloorDoor.bayPattern.Insert(rgen.OutputRange(0, patternSize), 1);//insert door into pattern
        data.facades.Add(groundFloorDoor);
        //couple of main facades
        //utility/back wall facade
        //maybe attic version

        BuildrPlan plan = data.plan;

        for (int v = 0; v < plan.numberOfVolumes; v++)
        {
            BuildrVolume volume         = plan.volumes[v];
            int          numberOfFloors = volume.numberOfFloors;
            volume.styles.Clear();
            for (int f = 0; f < volume.points.Count; f++)
            {
                int facadeIndex = volume.points[f];
                volume.styles.AddStyle(0, facadeIndex, numberOfFloors - 1);
                volume.styles.AddStyle(1, facadeIndex, 1);
            }
        }
    }
Example #39
0
    public static void Build(DynamicMeshGenericMultiMaterialMesh _mesh, BuildrData _data)
    {
//        timestart = Time.realtimeSinceStartup;
        data     = _data;
        mesh     = _mesh;
        textures = data.textures.ToArray();
        BuildrPlan plan = data.plan;

        int facadeIndex = 0;

        numberOfFacades = 0;
        int numberOfVolumes = data.plan.numberOfVolumes;

        LogTimer("Start");

        //define rectangles that represent the facades
        packedTexturePositions.Clear();
        for (int v = 0; v < numberOfVolumes; v++)
        {
            BuildrVolume volume = plan.volumes[v];
            int          numberOfVolumePoints = volume.points.Count;

            for (int f = 0; f < numberOfVolumePoints; f++)
            {
                if (!volume.renderFacade[f])
                {
                    continue;
                }
                int      indexA = f;
                int      indexB = (f < numberOfVolumePoints - 1) ? f + 1 : 0;
                Vector2z p0     = plan.points[volume.points[indexA]];
                Vector2z p1     = plan.points[volume.points[indexB]];

                float facadeWidth = Vector2z.Distance(p0, p1) * PIXELS_PER_METER;
                int   floorBase   = plan.GetFacadeFloorHeight(v, volume.points[indexA], volume.points[indexB]);

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

                float floorHeight  = data.floorHeight;
                float facadeHeight = (volume.numberOfFloors - floorBase) * floorHeight * PIXELS_PER_METER;
                if (facadeHeight < 0)
                {
                    facadeWidth  = 0;
                    facadeHeight = 0;
                }

                Rect newFacadeRect = new Rect(0, 0, facadeWidth, facadeHeight);
                packedTexturePositions.Add(newFacadeRect);

                numberOfFacades++;
            }
        }

        //Build ROOF
        DynamicMeshGenericMultiMaterialMesh dynMeshRoof = new DynamicMeshGenericMultiMaterialMesh();

        dynMeshRoof.name         = "Roof Mesh";
        dynMeshRoof.subMeshCount = textures.Length;
        BuildrRoof.Build(dynMeshRoof, data, true);
        dynMeshRoof.CheckMaxTextureUVs(data);
        LogTimer("Roof A");

        roofTextures.Clear();
        roofTextureIndex.Clear();
        foreach (BuildrRoofDesign roofDesign in data.roofs)
        {
            foreach (int textureIndex in roofDesign.textureValues)
            {
                if (!roofTextureIndex.Contains(textureIndex))
                {
                    BuildrTexture bTexture = data.textures[textureIndex];
                    Vector2       largestSubmeshPlaneSize = new Vector2(1, 1);
                    Vector2       minWorldUvSize          = dynMeshRoof.MinWorldUvSize(textureIndex);
                    Vector2       maxWorldUvSize          = dynMeshRoof.MaxWorldUvSize(textureIndex);
                    largestSubmeshPlaneSize.x = maxWorldUvSize.x - minWorldUvSize.x;
                    largestSubmeshPlaneSize.y = maxWorldUvSize.y - minWorldUvSize.y;
                    int  roofTextureWidth    = Mathf.RoundToInt(largestSubmeshPlaneSize.x * PIXELS_PER_METER);
                    int  roofTextureHeight   = Mathf.RoundToInt(largestSubmeshPlaneSize.y * PIXELS_PER_METER);
                    Rect newRoofTexutureRect = new Rect(0, 0, roofTextureWidth, roofTextureHeight);
                    packedTexturePositions.Add(newRoofTexutureRect);
                    roofTextures.Add(bTexture);
                    roofTextureIndex.Add(textureIndex);
                }
            }
        }

        //run a custom packer to define their postions
        textureWidth = RectanglePack.Pack(packedTexturePositions, ATLAS_PADDING);

        //determine the resize scale and apply that to the rects
        packedScale = 1;
        int numberOfRects = packedTexturePositions.Count;

        if (textureWidth > MAXIMUM_TEXTURESIZE)
        {
            packedScale = MAXIMUM_TEXTURESIZE / (float)textureWidth;
            for (int i = 0; i < numberOfRects; i++)
            {
                Rect thisRect = packedTexturePositions[i];
                thisRect.x               *= packedScale;
                thisRect.y               *= packedScale;
                thisRect.width           *= packedScale;
                thisRect.height          *= packedScale;
                packedTexturePositions[i] = thisRect;
                //Debug.Log("Rects "+roofTextures[i-+packedTexturePositions[i]);
            }
            textureWidth = Mathf.RoundToInt(packedScale * textureWidth);
        }
        else
        {
            textureWidth = (int)Mathf.Pow(2, (Mathf.FloorToInt(Mathf.Log(textureWidth - 1, 2)) + 1));//find the next power of two
        }
        //Debug.Log("Texture Width "+textureWidth);
        //TODO: maybe restrict the resize to a power of two?
        LogTimer("Packed Rect Generated");

        textureSize = textureWidth * textureWidth;
        colourArray = new Color32[textureSize];
        //TestRectColours();//this test paints all the facades with rainbow colours - real pretty
        BuildTextures();

        LogTimer("texture created");
        Texture2D packedTexture = new Texture2D(textureWidth, textureWidth, TextureFormat.ARGB32, true);

        packedTexture.filterMode = FilterMode.Bilinear;
        packedTexture.SetPixels32(colourArray);
        packedTexture.Apply(true, false);
        LogTimer("apply");

        if (data.LODTextureAtlas != null)
        {
            Object.DestroyImmediate(data.LODTextureAtlas);
        }
        data.LODTextureAtlas      = packedTexture;
        data.LODTextureAtlas.name = "Low Detail Texture";

        //build the model with new uvs

        if (data.drawUnderside)
        {
            for (int s = 0; s < numberOfVolumes; s++)
            {
                BuildrVolume volume = plan.volumes[s];
                int          numberOfVolumePoints = volume.points.Count;
                Vector3[]    newEndVerts          = new Vector3[numberOfVolumePoints];
                Vector2[]    newEndUVs            = new Vector2[numberOfVolumePoints];
                for (int i = 0; i < numberOfVolumePoints; i++)
                {
                    newEndVerts[i] = plan.points[volume.points[i]].vector3;
                    newEndUVs[i]   = Vector2.zero;
                }

                List <int> tris = new List <int>(data.plan.GetTrianglesBySectorBase(s));
                tris.Reverse();
                mesh.AddData(newEndVerts, newEndUVs, tris.ToArray(), 0);
            }
        }
        LogTimer("Floor");

        //Build facades
        for (int s = 0; s < numberOfVolumes; s++)
        {
            BuildrVolume volume = plan.volumes[s];
            int          numberOfVolumePoints = volume.points.Count;

            for (int f = 0; f < numberOfVolumePoints; f++)
            {
                if (!volume.renderFacade[f])
                {
                    continue;
                }
                int     indexA = f;
                int     indexB = (f < numberOfVolumePoints - 1) ? f + 1 : 0;
                Vector3 p0     = plan.points[volume.points[indexA]].vector3;
                Vector3 p1     = plan.points[volume.points[indexB]].vector3;

                int floorBase      = plan.GetFacadeFloorHeight(s, volume.points[indexA], volume.points[indexB]);
                int numberOfFloors = volume.numberOfFloors - floorBase;
                if (numberOfFloors < 1)
                {
                    //no facade - adjacent facade is taller and covers this one
                    continue;
                }
                float floorHeight = data.floorHeight;

                Vector3 floorHeightStart = Vector3.up * (floorBase * floorHeight);
                Vector3 wallHeight       = Vector3.up * (volume.numberOfFloors * floorHeight) - floorHeightStart;

                p0 += floorHeightStart;
                p1 += floorHeightStart;

                Vector3 w0 = p0;
                Vector3 w1 = p1;
                Vector3 w2 = w0 + wallHeight;
                Vector3 w3 = w1 + wallHeight;

                Rect facadeRect = packedTexturePositions[facadeIndex];

                float   imageSize = textureWidth;
                Vector2 uvMin     = new Vector2(facadeRect.xMin / imageSize, facadeRect.yMin / imageSize);
                Vector2 uvMax     = new Vector2(facadeRect.xMax / imageSize, facadeRect.yMax / imageSize);

                mesh.AddPlane(w0, w1, w2, w3, uvMin, uvMax, 0);
                facadeIndex++;
            }
        }
        LogTimer("Facades");

        //ROOF Textures
        int         roofRectBase  = numberOfFacades;
        List <Rect> newAtlasRects = new List <Rect>();

        for (int i = roofRectBase; i < packedTexturePositions.Count; i++)
        {
            Rect uvRect = new Rect();//generate a UV based rectangle off the packed one
            uvRect.x      = packedTexturePositions[i].x / textureWidth;
            uvRect.y      = packedTexturePositions[i].y / textureWidth;
            uvRect.width  = packedTexturePositions[i].width / textureWidth;
            uvRect.height = packedTexturePositions[i].height / textureWidth;
            newAtlasRects.Add(uvRect);
        }
        dynMeshRoof.Atlas(roofTextureIndex.ToArray(), newAtlasRects.ToArray(), data.textures.ToArray());
        //Add the atlased mesh data to the main model data at submesh 0
        mesh.AddData(dynMeshRoof.vertices, dynMeshRoof.uv, dynMeshRoof.triangles, 0);

        LogTimer("Roof B");

        data     = null;
        mesh     = null;
        textures = null;
        //atlasRects = null;

        LogTimer("Done");

        System.GC.Collect();
    }
Example #40
0
    public static void Build(DynamicMeshGenericMultiMaterialMesh _mesh, BuildrData _data, bool ignoreParapets)
    {
        data = _data;
        mesh = _mesh;
        textures = data.textures.ToArray();
        BuildrPlan plan = data.plan;

        int numberOfVolumes = data.plan.numberOfVolumes;
        for (int s = 0; s < numberOfVolumes; s++)
        {

            BuildrVolume volume = plan.volumes[s];
            BuildrRoofDesign design = data.roofs[volume.roofDesignID];

            BuildrRoofDesign.styles style = design.style;
            if (volume.points.Count != 4)
                if (design.style == BuildrRoofDesign.styles.leanto || design.style == BuildrRoofDesign.styles.sawtooth || design.style == BuildrRoofDesign.styles.barrel)
                    style = BuildrRoofDesign.styles.flat;//ignore style and just do a flat roof

            if (volume.points.Count != 4 && design.style == BuildrRoofDesign.styles.gabled)
                style = BuildrRoofDesign.styles.hipped;//ignore style and just do a hipped roof

            switch (style)
            {
                case BuildrRoofDesign.styles.flat:
                    FlatRoof(volume, design);
                    break;
                case BuildrRoofDesign.styles.mansard:
                    Mansard(volume, design);
                    if (design.hasDormers)
                        Dormers(volume, design);
                    break;
                case BuildrRoofDesign.styles.gabled:
                    Gabled(volume, design);
                    break;
                case BuildrRoofDesign.styles.hipped:
                    Hipped(volume, design);
                    break;
                case BuildrRoofDesign.styles.leanto:
                    LeanTo(volume, design);
                    break;
                case BuildrRoofDesign.styles.sawtooth:
                    Sawtooth(volume, design);
                    break;
                case BuildrRoofDesign.styles.barrel:
                    Barrel(volume, design);
                    break;
                case BuildrRoofDesign.styles.steepled:
                    Steeple(volume, design);
                    break;
            }

            if (design.parapet && !ignoreParapets)
                Parapet(volume, design);

        }

        data = null;
        mesh = null;
        textures = null;
    }