public void UpdateCollider()
    {
        if (data.generateCollider != BuildrData.ColliderGenerationModes.None)
        {
            if (data.floorHeight == 0)
                return;
            if (colliderMesh == null)
                colliderMesh = new DynamicMeshGenericMultiMaterialMesh();

            colliderMesh.Clear();
            colliderMesh.subMeshCount = 1;
            BuildrBuildingCollider.Build(colliderMesh, data);
            colliderMesh.Build(false);

            int numberOfStairMeshes = colliderMesh.meshCount;
            for (int i = 0; i < numberOfStairMeshes; i++)
            {
                string meshName = "collider";
                if (numberOfStairMeshes > 1) meshName += " mesh " + (i + 1);
                GameObject newMeshHolder = new GameObject(meshName);
                newMeshHolder.transform.parent = transform;
                meshFilt = newMeshHolder.AddComponent<MeshFilter>();
                meshRend = newMeshHolder.AddComponent<MeshRenderer>();
                meshFilt.mesh = colliderMesh[i].mesh;
                colliderHolders.Add(newMeshHolder);
            }
        }
    }
Beispiel #2
0
    private static void ExportCollider(BuildrData data)
    {
        DynamicMeshGenericMultiMaterialMesh COL_MESH = new DynamicMeshGenericMultiMaterialMesh();

        COL_MESH.subMeshCount = data.textures.Count;
        BuildrBuildingCollider.Build(COL_MESH, data);
//        COL_MESH.CollapseSubmeshes();
        COL_MESH.Build(false);

        ExportMaterial[] exportTextures = new ExportMaterial[1];
        ExportMaterial   newTexture     = new ExportMaterial();

        newTexture.name      = "blank";
        newTexture.filepath  = "";
        newTexture.generated = true;
        exportTextures[0]    = newTexture;

        int numberOfColliderMeshes = COL_MESH.meshCount;

        for (int i = 0; i < numberOfColliderMeshes; i++)
        {
            MeshUtility.Optimize(COL_MESH[i].mesh);
            string ColliderSuffixIndex = ((numberOfColliderMeshes > 1) ? "_" + i : "");
            string ColliderFileName    = data.exportFilename + COLLIDER_SUFFIX + ColliderSuffixIndex;
            string ColliderFolder      = ROOT_FOLDER + data.exportFilename + "/";
            Export(ColliderFileName, ColliderFolder, data, COL_MESH[i].mesh, exportTextures);
        }
    }
    /// <summary>
    /// generate an array of gameobjects that contain all the generated detail meshes - ready to display in a scene
    /// </summary>
    /// <param name="mesh"></param>
    /// <param name="data"></param>
    /// <returns></returns>
    public static GameObject[] Render(DynamicMeshGenericMultiMaterialMesh mesh, BuildrData data)
    {
        List<GameObject> detailGameobjects = new List<GameObject>();
        int numberOfDetails = data.details.Count;

        if (numberOfDetails == 0)
            return detailGameobjects.ToArray();

        BuildrDetailExportObject exportObject = Build(mesh, data);


        int numberOfMeshes = exportObject.detailMeshes.Length;
        if (numberOfMeshes == 0)
            return detailGameobjects.ToArray();

        if (detailMat == null)
            detailMat = new Material(Shader.Find("Diffuse"));
       
        detailMat.mainTexture = detailtexture;
        for (int i = 0; i < numberOfMeshes; i++)
        {
            GameObject details = new GameObject("details " + i);
            details.AddComponent<MeshFilter>().mesh = exportObject.detailMeshes[i];
            details.AddComponent<MeshRenderer>().sharedMaterial = detailMat;
            detailGameobjects.Add(details);
        }
        //        Debug.Log("BuildR Detail Pack Complete: " + (Time.realtimeSinceStartup - timestart) + " sec");
        return detailGameobjects.ToArray();
    }
Beispiel #4
0
    public void UpdateCollider()
    {
        if (data.generateCollider != BuildrData.ColliderGenerationModes.None)
        {
            if (data.floorHeight == 0)
            {
                return;
            }
            if (colliderMesh == null)
            {
                colliderMesh = new DynamicMeshGenericMultiMaterialMesh();
            }

            colliderMesh.Clear();
            colliderMesh.subMeshCount = 1;
            BuildrBuildingCollider.Build(colliderMesh, data);
            colliderMesh.Build(false);

            int numberOfStairMeshes = colliderMesh.meshCount;
            for (int i = 0; i < numberOfStairMeshes; i++)
            {
                string meshName = "collider";
                if (numberOfStairMeshes > 1)
                {
                    meshName += " mesh " + (i + 1);
                }
                GameObject newMeshHolder = new GameObject(meshName);
                newMeshHolder.transform.parent = transform;
                meshFilt      = newMeshHolder.AddComponent <MeshFilter>();
                meshRend      = newMeshHolder.AddComponent <MeshRenderer>();
                meshFilt.mesh = colliderMesh[i].mesh;
                colliderHolders.Add(newMeshHolder);
            }
        }
    }
    public static void Build(DynamicMeshGenericMultiMaterialMesh _mesh, BuildrData _data)
    {
        switch(_data.generateCollider)
        {
                case BuildrData.ColliderGenerationModes.None:
                return;
//                break;

                case BuildrData.ColliderGenerationModes.Simple:
                BuildSimple(_mesh,_data);
                break;

                case BuildrData.ColliderGenerationModes.Complex:
                BuildrBuilding.Build(_mesh,_data);
                BuildrRoof.Build(_mesh, _data);
                int numberOfVolumes = _data.plan.numberOfVolumes;
                for(int v = 0; v < numberOfVolumes; v++)
                {
                    BuildrInteriors.Build(_mesh,_data,v);
                    BuildrStairs.Build(_mesh,_data,v,BuildrStairs.StairModes.Flat,false);
                }
                _mesh.CollapseSubmeshes();
                break;
        }
    }
    public static void Build(DynamicMeshGenericMultiMaterialMesh _mesh, BuildrData _data)
    {
        switch (_data.generateCollider)
        {
        case BuildrData.ColliderGenerationModes.None:
            return;

//                break;

        case BuildrData.ColliderGenerationModes.Simple:
            BuildSimple(_mesh, _data);
            break;

        case BuildrData.ColliderGenerationModes.Complex:
            BuildrBuilding.Build(_mesh, _data);
            BuildrRoof.Build(_mesh, _data);
            int numberOfVolumes = _data.plan.numberOfVolumes;
            for (int v = 0; v < numberOfVolumes; v++)
            {
                BuildrInteriors.Build(_mesh, _data, v);
                BuildrStairs.Build(_mesh, _data, v, BuildrStairs.StairModes.Flat, false);
            }
            _mesh.CollapseSubmeshes();
            break;
        }
    }
Beispiel #7
0
 public static void Build(DynamicMeshGenericMultiMaterialMesh _mesh, BuildrData _data)
 {
     int numberOfFacades = _data.plan.numberOfFacades;
     Rect[] dummyUVConstraints = new Rect[numberOfFacades];
     for (int i = 0; i < numberOfFacades; i++)
         dummyUVConstraints[i] = new Rect(0,0,1,1);
     Build(_mesh, _data, dummyUVConstraints);
 }
Beispiel #8
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);
    }
Beispiel #9
0
    public void UpdateDetails()
    {
        int numberOfDetails = 0;

        if (details != null)
        {
            numberOfDetails = details.Length;
        }
        for (int i = 0; i < numberOfDetails; i++)
        {
            DestroyImmediate(details[i]);
        }

        if (data.plan == null)
        {
            return;
        }
        if (data.floorHeight == 0)
        {
            return;
        }
        if (data.details.Count == 0)
        {
            return;
        }
        if (detailMesh == null)
        {
            detailMesh = new DynamicMeshGenericMultiMaterialMesh();
        }

        if (renderMode != renderModes.full)
        {
            return;//once data is cleared - asses if we want to rerender the details
        }
        details         = BuildrBuildingDetails.Render(detailMesh, data);
        numberOfDetails = details.Length;

        for (int i = 0; i < numberOfDetails; i++)
        {
            details[i].transform.parent        = transform;
            details[i].transform.localPosition = Vector3.zero;
            details[i].transform.localRotation = Quaternion.identity;
        }
    }
Beispiel #10
0
    private static void ExportLowLOD(BuildrData data)
    {
        DynamicMeshGenericMultiMaterialMesh dynLODMesh = new DynamicMeshGenericMultiMaterialMesh();

        dynLODMesh.subMeshCount = data.textures.Count;
        BuildrBuildingLowDetail2.Build(dynLODMesh, data);
        dynLODMesh.CollapseSubmeshes();
        EditorUtility.DisplayCancelableProgressBar(PROGRESSBAR_TEXT, "", 0.80f);
        dynLODMesh.Build(data.includeTangents);
        Mesh LODMesh = dynLODMesh[0].mesh;//TODO: support many meshes

        MeshUtility.Optimize(LODMesh);
        EditorUtility.DisplayCancelableProgressBar(PROGRESSBAR_TEXT, "", 0.90f);

        string textureName     = data.exportFilename + ATLASED_SUFFIX + LOD_SUFFIX;
        string textureFileName = textureName + ".png";
        string newDirectory    = ROOT_FOLDER + data.exportFilename;

        File.WriteAllBytes(newDirectory + "/" + textureFileName, data.LODTextureAtlas.EncodeToPNG());
        ExportMaterial[] exportTextures = new ExportMaterial[1];
        ExportMaterial   newTexture     = new ExportMaterial();

        newTexture.name      = textureName;
        newTexture.filepath  = textureFileName;
        newTexture.generated = true;
        exportTextures[0]    = newTexture;
        string LODFileName = data.exportFilename + LOD_SUFFIX;
        string LODFolder   = ROOT_FOLDER + data.exportFilename + "/";

        Export(LODFileName, LODFolder, data, LODMesh, exportTextures);


        if (data.placeIntoScene)
        {
            AssetDatabase.Refresh();//ensure the database is up to date...
            string     filePath = LODFolder + LODFileName + FILE_EXTENTION;
            GameObject newModel = (GameObject)PrefabUtility.InstantiatePrefab(AssetDatabase.LoadMainAssetAtPath(filePath));
            newModel.transform.position = CURRENT_TRANSFORM.position;
            newModel.transform.rotation = CURRENT_TRANSFORM.rotation;
        }

        Texture2D.DestroyImmediate(data.textureAtlas);
        Texture2D.DestroyImmediate(data.LODTextureAtlas);
    }
Beispiel #11
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;
                BuildrInteriors.Build(interiorMesh, data, v);
                interiorMesh.Build(false);

                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);
                }
            }
        }
    }
Beispiel #12
0
    private static void ExportCollider(TrackBuildR data)
    {
        DynamicMeshGenericMultiMaterialMesh COL_MESH = new DynamicMeshGenericMultiMaterialMesh();

//        COL_MESH.subMeshCount = data.textures.Count;
//        BuildrBuildingCollider.Build(COL_MESH, data);
//        COL_MESH.CollapseSubmeshes();
        COL_MESH.Build(false);

        ExportMaterial[] exportTextures = new ExportMaterial[1];
        ExportMaterial   newTexture     = new ExportMaterial();

        newTexture.name      = "blank";
        newTexture.filepath  = "";
        newTexture.generated = true;
        exportTextures[0]    = newTexture;

        int numberOfColliderMeshes = COL_MESH.meshCount;

        for (int i = 0; i < numberOfColliderMeshes; i++)
        {
            MeshUtility.Optimize(COL_MESH[i].mesh);
            string ColliderSuffixIndex = ((numberOfColliderMeshes > 1) ? "_" + i : "");
            string ColliderFileName    = data.exportFilename + COLLIDER_SUFFIX + ColliderSuffixIndex;
            string ColliderFolder      = ROOT_FOLDER + data.exportFilename + "/";
            Export(ColliderFileName, ColliderFolder, data, COL_MESH[i].mesh, exportTextures);
        }

        //string newDirectory = rootFolder+track.exportFilename;
        //if(!CreateFolder(newDirectory))
        //	return;
//        ExportMaterial[] exportTextures = new ExportMaterial[1];
//        ExportMaterial newTexture = new ExportMaterial();
//        newTexture.customName = "";
//        newTexture.filepath = "";
//        newTexture.generated = true;
//        exportTextures[0] = newTexture;
//        Export(track.exportFilename + COLLIDER_SUFFIX, ROOT_FOLDER + track.exportFilename + "/", track, EXPORT_MESH, exportTextures);
//
//        COL_MESH = null;
//        EXPORT_MESH = null;
    }
Beispiel #13
0
    /// <summary>
    /// generate an array of gameobjects that contain all the generated detail meshes - ready to display in a scene
    /// </summary>
    /// <param name="mesh"></param>
    /// <param name="data"></param>
    /// <returns></returns>
    public static GameObject[] Render(DynamicMeshGenericMultiMaterialMesh mesh, BuildrData data)
    {
        List <GameObject> detailGameobjects = new List <GameObject>();
        int numberOfDetails = data.details.Count;

        if (numberOfDetails == 0)
        {
            return(detailGameobjects.ToArray());
        }

        BuildrDetailExportObject exportObject = Build(mesh, data);


        int numberOfMeshes = exportObject.detailMeshes.Length;

        if (numberOfMeshes == 0)
        {
            return(detailGameobjects.ToArray());
        }

        if (detailMat == null)
        {
            detailMat = new Material(Shader.Find("Diffuse"));
        }

        detailMat.mainTexture = detailtexture;
        for (int i = 0; i < numberOfMeshes; i++)
        {
            GameObject details = new GameObject("details " + i);
            details.AddComponent <MeshFilter>().mesh             = exportObject.detailMeshes[i];
            details.AddComponent <MeshRenderer>().sharedMaterial = detailMat;
            detailGameobjects.Add(details);
        }
        //        Debug.Log("BuildR Detail Pack Complete: " + (Time.realtimeSinceStartup - timestart) + " sec");
        return(detailGameobjects.ToArray());
    }
Beispiel #14
0
    //returns the number of meshes
    private static int ExportDetails(BuildrData data)
    {
        DynamicMeshGenericMultiMaterialMesh DET_MESH     = new DynamicMeshGenericMultiMaterialMesh();
        BuildrDetailExportObject            exportObject = BuildrBuildingDetails.Build(DET_MESH, data);

        int numberOfMeshes = exportObject.detailMeshes.Length;

        if (numberOfMeshes == 0)
        {
            return(0);
        }

        string textureName     = data.exportFilename + ATLASED_SUFFIX + DETAIL_SUFFIX;
        string textureFileName = textureName + ".png";
        string newDirectory    = ROOT_FOLDER + data.exportFilename;

        File.WriteAllBytes(newDirectory + "/" + textureFileName, exportObject.texture.EncodeToPNG());
        ExportMaterial[] exportTextures = new ExportMaterial[1];
        ExportMaterial   newTexture     = new ExportMaterial();

        newTexture.name      = textureName;
        newTexture.filepath  = textureFileName;
        newTexture.generated = true;
        exportTextures[0]    = newTexture;
        for (int i = 0; i < numberOfMeshes; i++)
        {
            string DetailSuffixIndex = ((numberOfMeshes > 1) ? "_" + i : "");
            string DetailFileName    = data.exportFilename + DETAIL_SUFFIX + DetailSuffixIndex;
            string DetailFolder      = ROOT_FOLDER + data.exportFilename + "/";
            Export(DetailFileName, DetailFolder, data, exportObject.detailMeshes[i], exportTextures);
        }

        Texture2D.DestroyImmediate(exportObject.texture);

        return(numberOfMeshes);
    }
    /// <summary>
    /// Generate the detail meshes and return the export object
    /// </summary>
    /// <param name="mesh"></param>
    /// <param name="data"></param>
    /// <returns></returns>
    public static BuildrDetailExportObject Build(DynamicMeshGenericMultiMaterialMesh mesh, BuildrData data)
    {
        BuildrDetailExportObject exportObject = new BuildrDetailExportObject();
        List<Texture2D> detailTextures = new List<Texture2D>();
        List<int> detailSubmeshesWithTextures = new List<int>();
        int numberOfDetails = data.details.Count;
        mesh.Clear();
        mesh.subMeshCount = numberOfDetails;

        for(int d = 0; d < numberOfDetails; d++)
        {
            BuildrDetail detail = data.details[d];
            if(detail.mesh == null)
                continue;
            int faceIndex = detail.face;
            Vector3 position = Vector3.zero;
            BuildrPlan plan = data.plan;
            int numberOfVolumes = plan.numberOfVolumes;
            Vector2 faceUv = detail.faceUv;
            Quaternion faceAngle = Quaternion.identity;
            //Place the detail mesh
            if (detail.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 p0 = plan.points[volume.points[indexA]].vector3;
                            Vector3 p1 = plan.points[volume.points[indexB]].vector3;
                            Vector3 basePosition = Vector3.Lerp(p0, p1, faceUv.x);
                            Vector3 detailHeight = Vector3.up * (volume.numberOfFloors * data.floorHeight * faceUv.y);
                            Vector3 facadeCross = Vector3.Cross(Vector3.up, p1 - p0).normalized;
                            Vector3 detailDepth = facadeCross * detail.faceHeight;
                            faceAngle = Quaternion.LookRotation(facadeCross);
                            position = basePosition + detailHeight + detailDepth;
                            facadeFound = true;
                            break;
                        }
                        facadeCount++;
                    }
                    if (facadeFound)
                        break;
                }
            }
            else//roof detail
            {
                BuildrVolume volume = plan.volumes[Mathf.Clamp(0,numberOfVolumes-1,faceIndex)];
                int numberOfVolumePoints = volume.points.Count;
                Vector3 minimumRoofPoint = plan.points[volume.points[0]].vector3;
                Vector3 maximumRoofPoint = minimumRoofPoint;
                for (int p = 1; p < numberOfVolumePoints; p++)
                {
                    Vector3 p0 = plan.points[volume.points[p]].vector3;
                    if (p0.x < minimumRoofPoint.x) minimumRoofPoint.x = p0.x;
                    if (p0.z < minimumRoofPoint.y) minimumRoofPoint.y = p0.z;
                    if (p0.x > maximumRoofPoint.x) maximumRoofPoint.x = p0.x;
                    if (p0.z > maximumRoofPoint.y) maximumRoofPoint.y = p0.z;
                }
                position.x = Mathf.Lerp(minimumRoofPoint.x, maximumRoofPoint.x, faceUv.x);
                position.z = Mathf.Lerp(minimumRoofPoint.y, maximumRoofPoint.y, faceUv.y);
                position.y = volume.numberOfFloors * data.floorHeight + detail.faceHeight;
            }

            Quaternion userRotation = Quaternion.Euler(detail.userRotation);
            int vertexCount = detail.mesh.vertexCount;
            Vector3[] verts = new Vector3[vertexCount];
            Quaternion rotate = faceAngle * userRotation;
            for (int i = 0; i < vertexCount; i++)
            {
                Vector3 sourceVertex = Vector3.Scale(detail.mesh.vertices[i], detail.scale);
                Vector3 outputVertex = (rotate) * sourceVertex + position;
                verts[i] = outputVertex;
            }
            mesh.AddData(verts, detail.mesh.uv, detail.mesh.triangles, d);
            detail.worldPosition = position;
            detail.worldRotation = rotate;

            if (detail.material.mainTexture != null)
            {
        #if UNITY_EDITOR
                string texturePath = AssetDatabase.GetAssetPath(detail.material.mainTexture);
                TextureImporter textureImporter = (TextureImporter)AssetImporter.GetAtPath(texturePath);

                if (!textureImporter.isReadable)
                {
                    Debug.LogWarning("The texture you have selected is not readable. Cannot render");
                    return exportObject;
                }

                detailTextures.Add((Texture2D)detail.material.mainTexture);
                detailSubmeshesWithTextures.Add(d);
        #endif
            }
        }

        if(detailtexture!=null)
            Object.DestroyImmediate(detailtexture);

        List<Mesh> outputMeshes = new List<Mesh>();
        if (detailSubmeshesWithTextures.Count > 0)
        {
            Rect[] textureRects = BuildrTexturePacker2.Pack(out detailtexture, detailTextures.ToArray(), 512);
            if(detailSubmeshesWithTextures.Count > 0) mesh.Atlas(detailSubmeshesWithTextures.ToArray(), textureRects);
            mesh.CollapseSubmeshes();
            mesh.Build();
            int numberOfMeshes = mesh.meshCount;
            for (int i = 0; i < numberOfMeshes; i++)
                outputMeshes.Add(mesh[i].mesh);
        }

        exportObject.detailMeshes = outputMeshes.ToArray();
        exportObject.texture = detailtexture;
        return exportObject;
        /*if (detailMat == null)
                detailMat = new Material(Shader.Find("Diffuse"));
            detailMat.mainTexture = detailtexture;
            List<Mesh> outputMeshes = new List<Mesh>();
            for (int i = 0; i < numberOfMeshes; i++)
            {
                outputMeshes.Add(mesh[i].mesh);
                GameObject details = new GameObject("details " + i);
                details.AddComponent<MeshFilter>().mesh = mesh[i].mesh;
                details.AddComponent<MeshRenderer>().sharedMaterial = detailMat;
                detailGameobjects.Add(details);
            }
        }
        //        Debug.Log("BuildR Detail Pack Complete: " + (Time.realtimeSinceStartup - timestart) + " sec");
        return detailGameobjects.ToArray();*/
    }
    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();
    }
    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);
            }
        }
    }
    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;
    }
    private static void ExportLowLOD(BuildrData data)
    {
        DynamicMeshGenericMultiMaterialMesh dynLODMesh = new DynamicMeshGenericMultiMaterialMesh();
        dynLODMesh.subMeshCount = data.textures.Count;
        BuildrBuildingLowDetail2.Build(dynLODMesh, data);
        dynLODMesh.CollapseSubmeshes();
        EditorUtility.DisplayCancelableProgressBar(PROGRESSBAR_TEXT, "", 0.80f);
        dynLODMesh.Build(data.includeTangents);
        Mesh LODMesh = dynLODMesh[0].mesh;//TODO: support many meshes
        MeshUtility.Optimize(LODMesh);
        EditorUtility.DisplayCancelableProgressBar(PROGRESSBAR_TEXT, "", 0.90f);

        string textureName = data.exportFilename + ATLASED_SUFFIX + LOD_SUFFIX;
        string textureFileName = textureName + ".png";
        string newDirectory = ROOT_FOLDER + data.exportFilename;

        File.WriteAllBytes(newDirectory + "/" + textureFileName, data.LODTextureAtlas.EncodeToPNG());
        ExportMaterial[] exportTextures = new ExportMaterial[1];
        ExportMaterial newTexture = new ExportMaterial();
        newTexture.name = textureName;
        newTexture.filepath = textureFileName;
        newTexture.generated = true;
        exportTextures[0] = newTexture;
        string LODFileName = data.exportFilename + LOD_SUFFIX;
        string LODFolder = ROOT_FOLDER + data.exportFilename + "/";
        Export(LODFileName, LODFolder, data, LODMesh, exportTextures);

        if (data.placeIntoScene)
        {
            AssetDatabase.Refresh();//ensure the database is up to date...
            string filePath = LODFolder + LODFileName + FILE_EXTENTION;
            GameObject newModel = (GameObject)PrefabUtility.InstantiatePrefab(AssetDatabase.LoadMainAssetAtPath(filePath));
            newModel.transform.position = CURRENT_TRANSFORM.position;
            newModel.transform.rotation = CURRENT_TRANSFORM.rotation;
        }

        Texture2D.DestroyImmediate(data.textureAtlas);
        Texture2D.DestroyImmediate(data.LODTextureAtlas);
    }
    private static void ExportCollider(BuildrData data)
    {
        DynamicMeshGenericMultiMaterialMesh COL_MESH = new DynamicMeshGenericMultiMaterialMesh();
        COL_MESH.subMeshCount = data.textures.Count;
        BuildrBuildingCollider.Build(COL_MESH, data);
        //        COL_MESH.CollapseSubmeshes();
        COL_MESH.Build(false);

        ExportMaterial[] exportTextures = new ExportMaterial[1];
        ExportMaterial newTexture = new ExportMaterial();
        newTexture.name = "blank";
        newTexture.filepath = "";
        newTexture.generated = true;
        exportTextures[0] = newTexture;

        int numberOfColliderMeshes = COL_MESH.meshCount;
        for (int i = 0; i < numberOfColliderMeshes; i++)
        {
            MeshUtility.Optimize(COL_MESH[i].mesh);
            string ColliderSuffixIndex = ((numberOfColliderMeshes > 1) ? "_" + i : "");
            string ColliderFileName = data.exportFilename + COLLIDER_SUFFIX + ColliderSuffixIndex;
            string ColliderFolder = ROOT_FOLDER + data.exportFilename + "/";
            Export(ColliderFileName, ColliderFolder, data, COL_MESH[i].mesh, exportTextures);
        }
    }
Beispiel #21
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;
    }
Beispiel #22
0
    private static void ExportModel(BuildrData data)
    {
        try
        {
            EditorUtility.DisplayCancelableProgressBar(PROGRESSBAR_TEXT, "", 0.0f);

            //check overwrites...
            string newDirectory = ROOT_FOLDER + data.exportFilename;
            if (!CreateFolder(newDirectory))
            {
                EditorUtility.ClearProgressBar();
                return;
            }

            EditorUtility.DisplayCancelableProgressBar(PROGRESSBAR_TEXT, "", 0.05f);
            if (data.fullmesh)
            {
                //export unpacked model
                DYN_MESH = new DynamicMeshGenericMultiMaterialMesh();
                DYN_MESH.subMeshCount = data.textures.Count;
                BuildrBuilding.Build(DYN_MESH, data);
                EditorUtility.DisplayCancelableProgressBar(PROGRESSBAR_TEXT, "", 0.30f);
                BuildrRoof.Build(DYN_MESH, data);
                EditorUtility.DisplayCancelableProgressBar(PROGRESSBAR_TEXT, "", 0.60f);
                DYN_MESH.Build(data.includeTangents);
                int meshCount = DYN_MESH.meshCount;


                List <int>            unusedTextures           = DYN_MESH.unusedSubmeshes;
                int                   numberOfUnpackedTextures = data.textures.Count;
                List <ExportMaterial> exportTextureList        = new List <ExportMaterial>();
                for (int t = 0; t < numberOfUnpackedTextures; t++)
                {
                    if (unusedTextures.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;
                    exportTextureList.Add(newTexture);
                }
                for (int i = 0; i < meshCount; i++)
                {
                    EXPORT_MESH = DYN_MESH[i].mesh;
                    MeshUtility.Optimize(EXPORT_MESH);
                    Export(data, EXPORT_MESH, exportTextureList.ToArray());
                    string filenameSuffix = (meshCount > 1)? i.ToString() : "";
                    string filename       = data.exportFilename + filenameSuffix;
                    Export(filename, ROOT_FOLDER + data.exportFilename + "/", data, EXPORT_MESH, exportTextureList.ToArray());
                }
            }

            //Export Collider
            if (data.generateCollider != BuildrData.ColliderGenerationModes.None)
            {
                ExportCollider(data);
            }

            int[] numberOfInteriorMeshes = new int[data.plan.numberOfVolumes];
            if (data.renderInteriors && data.fullmesh)
            {
                numberOfInteriorMeshes = ExportInteriors(data);
            }

            int[] numberOfStairwells = new int[data.plan.numberOfVolumes];
            if (data.renderInteriors && data.fullmesh)
            {
                numberOfStairwells = ExportStairwells(data);
            }

            int numberOfDetailMeshes = 0;
            if (data.fullmesh)
            {
                numberOfDetailMeshes = ExportDetails(data);
            }

            EditorUtility.DisplayCancelableProgressBar(PROGRESSBAR_TEXT, "", 0.70f);

            //Place exported version into scene
            if (data.fullmesh)
            {
                AssetDatabase.Refresh();//ensure the database is up to date...
                GameObject baseObject = new GameObject(data.exportFilename);
                if ((data.createPrefabOnExport || data.placeIntoScene))
                {
                    baseObject.transform.position = CURRENT_TRANSFORM.position;
                    baseObject.transform.rotation = CURRENT_TRANSFORM.rotation;

                    string     modelFilePath = ROOT_FOLDER + data.exportFilename + "/" + data.exportFilename + FILE_EXTENTION;
                    GameObject newModel      = (GameObject)PrefabUtility.InstantiatePrefab(AssetDatabase.LoadMainAssetAtPath(modelFilePath));
                    newModel.name                    = "model";
                    newModel.transform.parent        = baseObject.transform;
                    newModel.transform.localPosition = Vector3.zero;
                    newModel.transform.localRotation = Quaternion.identity;
                    if (data.generateCollider != BuildrData.ColliderGenerationModes.None)
                    {
                        GameObject colliderObject   = new GameObject("collider");
                        string     colliderFilePath = ROOT_FOLDER + data.exportFilename + "/" + data.exportFilename + COLLIDER_SUFFIX + FILE_EXTENTION;
                        colliderObject.AddComponent <MeshCollider>().sharedMesh = (Mesh)AssetDatabase.LoadAssetAtPath(colliderFilePath, typeof(Mesh));
                        colliderObject.transform.parent        = baseObject.transform;
                        colliderObject.transform.localPosition = Vector3.zero;
                        colliderObject.transform.localRotation = Quaternion.identity;
                    }

                    for (int i = 0; i < numberOfDetailMeshes; i++)
                    {
                        string     detailSuffixIndex = ((numberOfDetailMeshes > 1) ? "_" + i : "");
                        string     detailFileName    = data.exportFilename + DETAIL_SUFFIX + detailSuffixIndex;
                        string     detailFolder      = ROOT_FOLDER + data.exportFilename + "/";
                        string     detailFilepath    = detailFolder + detailFileName + FILE_EXTENTION;
                        GameObject detailObject      = (GameObject)PrefabUtility.InstantiatePrefab(AssetDatabase.LoadMainAssetAtPath(detailFilepath));
                        detailObject.name                    = "details";
                        detailObject.transform.parent        = baseObject.transform;
                        detailObject.transform.localPosition = Vector3.zero;
                        detailObject.transform.localRotation = Quaternion.identity;
                    }

                    int        numberOfVolumes = data.plan.numberOfVolumes;
                    GameObject interiorHolder  = new GameObject("interiors");
                    interiorHolder.transform.parent        = baseObject.transform;
                    interiorHolder.transform.localPosition = Vector3.zero;
                    interiorHolder.transform.localRotation = Quaternion.identity;
                    for (int v = 0; v < numberOfInteriorMeshes.Length; v++)
                    {
                        int numMeshes = numberOfInteriorMeshes[v];
                        for (int i = 0; i < numMeshes; i++)
                        {
                            string     VolumeSuffix      = ((numberOfVolumes > 1) ? "_" + v : "");
                            string     DetailSuffixIndex = ((numMeshes > 1) ? "_" + i : "");
                            string     DetailFileName    = data.exportFilename + INTERIOR_SUFFIX + VolumeSuffix + DetailSuffixIndex;
                            string     DetailFolder      = ROOT_FOLDER + data.exportFilename + "/";
                            string     filePath          = DetailFolder + DetailFileName + FILE_EXTENTION;
                            GameObject interiorObject    = (GameObject)PrefabUtility.InstantiatePrefab(AssetDatabase.LoadMainAssetAtPath(filePath));
                            interiorObject.name                    = INTERIOR_SUFFIX + VolumeSuffix + DetailSuffixIndex;
                            interiorObject.transform.parent        = interiorHolder.transform;
                            interiorObject.transform.localPosition = Vector3.zero;
                            interiorObject.transform.localRotation = Quaternion.identity;
                        }
                    }

                    for (int v = 0; v < numberOfStairwells.Length; v++)
                    {
                        int numMeshes = numberOfStairwells[v];
                        for (int i = 0; i < numMeshes; i++)
                        {
                            string     VolumeSuffix      = ((numberOfVolumes > 1) ? "_" + v : "");
                            string     DetailSuffixIndex = ((numMeshes > 1) ? "_" + i : "");
                            string     DetailFileName    = data.exportFilename + STAIR_SUFFIX + VolumeSuffix + DetailSuffixIndex;
                            string     DetailFolder      = ROOT_FOLDER + data.exportFilename + "/";
                            string     filePath          = DetailFolder + DetailFileName + FILE_EXTENTION;
                            GameObject interiorObject    = (GameObject)PrefabUtility.InstantiatePrefab(AssetDatabase.LoadMainAssetAtPath(filePath));
                            interiorObject.name                    = STAIR_SUFFIX + VolumeSuffix + DetailSuffixIndex;
                            interiorObject.transform.parent        = interiorHolder.transform;
                            interiorObject.transform.localPosition = data.plan.volumes[v].stairBaseVector[i];
                            interiorObject.transform.localRotation = Quaternion.identity;
                        }
                    }
                }

                if (data.createPrefabOnExport)
                {
                    string prefabPath = ROOT_FOLDER + data.exportFilename + "/" + data.exportFilename + ".prefab";
                    Object prefab     = AssetDatabase.LoadAssetAtPath(prefabPath, typeof(GameObject));
                    if (prefab == null)
                    {
                        prefab = PrefabUtility.CreateEmptyPrefab(prefabPath);
                    }
                    PrefabUtility.ReplacePrefab(baseObject, prefab, ReplacePrefabOptions.ConnectToPrefab);
                }

                if (!data.placeIntoScene)
                {
                    Object.DestroyImmediate(baseObject);
                }
            }

            if (data.exportLowLOD)
            {
                ExportLowLOD(data);
            }

            DYN_MESH    = null;
            EXPORT_MESH = null;

            EditorUtility.ClearProgressBar();
            EditorUtility.UnloadUnusedAssets();

            AssetDatabase.Refresh();
        }catch (System.Exception e)
        {
            Debug.LogError("BuildR Export Error: " + e);
            EditorUtility.ClearProgressBar();
        }
    }
Beispiel #23
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));
            }
        }
    }
Beispiel #24
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();
            }
        }
    }
    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;
    }
Beispiel #26
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);
            }
        }
    }
Beispiel #27
0
    private static void ExportModel(TrackBuildR track)
    {
        GameObject baseObject = new GameObject(track.exportFilename);

        baseObject.transform.position = CURRENT_TRANSFORM.position;
        baseObject.transform.rotation = CURRENT_TRANSFORM.rotation;
        EditorUtility.DisplayCancelableProgressBar(PROGRESSBAR_TEXT, "", 0.0f);
        track.ForceFullRecalculation();
        EditorUtility.DisplayCancelableProgressBar(PROGRESSBAR_TEXT, "", 0.1f);
        try
        {
            TrackBuildRTrack trackData = track.track;

            //check overwrites...
            string newDirectory = ROOT_FOLDER + track.exportFilename;
            if (!CreateFolder(newDirectory))
            {
                EditorUtility.ClearProgressBar();
                return;
            }

            EditorUtility.DisplayCancelableProgressBar(PROGRESSBAR_TEXT, "", 0.15f);

            int              numberOfCurves  = trackData.numberOfCurves;
            float            exportProgress  = 0.75f / (numberOfCurves * 6.0f);
            ExportMaterial[] exportMaterials = new ExportMaterial[1];
            ExportMaterial   exportTexture   = new ExportMaterial();

            string[] dynNames = new [] { "track", "bumper", "boundary", "bottom", "offread", "trackCollider" };
            for (int c = 0; c < numberOfCurves; c++)
            {
                TrackBuildRPoint curve = trackData[c];

                int numberOfDynMeshes = 6;
                DynamicMeshGenericMultiMaterialMesh[] dynMeshes = new DynamicMeshGenericMultiMaterialMesh[6];
                dynMeshes[0] = curve.dynamicTrackMesh;
                dynMeshes[1] = curve.dynamicBumperMesh;
                dynMeshes[2] = curve.dynamicBoundaryMesh;
                dynMeshes[3] = curve.dynamicBottomMesh;
                dynMeshes[4] = curve.dynamicOffroadMesh;
                dynMeshes[5] = curve.dynamicColliderMesh;

                int[] textureIndeices = new int[] { curve.trackTextureStyleIndex, curve.bumperTextureStyleIndex, curve.boundaryTextureStyleIndex, curve.bottomTextureStyleIndex, curve.offroadTextureStyleIndex, 0 };

                for (int d = 0; d < numberOfDynMeshes; d++)
                {
                    if (EditorUtility.DisplayCancelableProgressBar(PROGRESSBAR_TEXT, "Exporting Track Curve " + c + " " + dynNames[d], 0.15f + exportProgress * (c * 6 + d)))
                    {
                        EditorUtility.ClearProgressBar();
                        return;
                    }
                    DynamicMeshGenericMultiMaterialMesh exportDynMesh = dynMeshes[d];
                    if (track.includeTangents || exportDynMesh.isEmpty)
                    {
                        exportDynMesh.Build(track.includeTangents);//rebuild with tangents
                    }
                    TrackBuildRTexture texture = trackData.Texture(textureIndeices[d]);
                    exportTexture.name      = texture.customName;
                    exportTexture.material  = texture.material;
                    exportTexture.generated = false;
                    exportTexture.filepath  = texture.filePath;
                    exportMaterials[0]      = exportTexture;

                    int meshCount = exportDynMesh.meshCount;
                    for (int i = 0; i < meshCount; i++)
                    {
                        Mesh exportMesh = exportDynMesh[i].mesh;
                        MeshUtility.Optimize(exportMesh);
                        string filenameSuffix = trackModelName(dynNames[d], c, (meshCount > 1) ? i : -1);// "trackCurve" + c + ((meshCount > 1) ? "_" + i.ToString() : "");
                        string filename       = track.exportFilename + filenameSuffix;
                        Export(filename, ROOT_FOLDER + track.exportFilename + "/", track, exportMesh, exportMaterials);

                        if (track.createPrefabOnExport)
                        {
                            AssetDatabase.Refresh();//ensure the database is up to date...

                            string modelFilePath = ROOT_FOLDER + track.exportFilename + "/" + filename + FILE_EXTENTION;
                            if (d < numberOfDynMeshes - 1)
                            {
                                GameObject newModel = (GameObject)PrefabUtility.InstantiatePrefab(AssetDatabase.LoadMainAssetAtPath(modelFilePath));
                                newModel.name                    = filename;
                                newModel.transform.parent        = baseObject.transform;
                                newModel.transform.localPosition = Vector3.zero;
                                newModel.transform.localRotation = Quaternion.identity;
                            }
                            else
                            {
                                GameObject colliderObject = new GameObject("trackCollider");
                                colliderObject.AddComponent <MeshCollider>().sharedMesh = (Mesh)AssetDatabase.LoadAssetAtPath(modelFilePath, typeof(Mesh));
                                colliderObject.transform.parent        = baseObject.transform;
                                colliderObject.transform.localPosition = Vector3.zero;
                                colliderObject.transform.localRotation = Quaternion.identity;
                            }
                        }
                    }
                }
            }
            if (track.createPrefabOnExport)
            {
                string prefabPath = ROOT_FOLDER + track.exportFilename + "/" + track.exportFilename + ".prefab";
                Object prefab     = AssetDatabase.LoadAssetAtPath(prefabPath, typeof(GameObject));
                if (prefab == null)
                {
                    prefab = PrefabUtility.CreateEmptyPrefab(prefabPath);
                }
                PrefabUtility.ReplacePrefab(baseObject, prefab, ReplacePrefabOptions.ConnectToPrefab);
            }

            EditorUtility.DisplayCancelableProgressBar(PROGRESSBAR_TEXT, "", 0.70f);

            AssetDatabase.Refresh();//ensure the database is up to date...
        }
        catch (System.Exception e)
        {
            Debug.LogError("BuildR Export Error: " + e);
            EditorUtility.ClearProgressBar();
        }
        Object.DestroyImmediate(baseObject);
        EditorUtility.ClearProgressBar();
        EditorUtility.UnloadUnusedAssets();
        AssetDatabase.Refresh();
    }
Beispiel #28
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();
    }
Beispiel #29
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;
    }
Beispiel #30
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;
    }
Beispiel #31
0
    //private static BuildrData data;

    public static void InspectorGUI(BuildrEditMode editMode, BuildrData _data)
    {
        //ensure that the model exists in the scene
        if (editMode.fullMesh == null)
        {
            editMode.UpdateRender();
        }

        Undo.RecordObject(_data, "Building Modified");
        //texture library string array
        BuildrTexture[] textures         = _data.textures.ToArray();
        int             numberOfTextures = textures.Length;

        string[] textureNames = new string[numberOfTextures];
        for (int t = 0; t < numberOfTextures; t++)
        {
            textureNames[t] = textures[t].name;
        }

        //Render a full version version
        EditorGUILayout.LabelField("Building Generation Types");
        EditorGUILayout.BeginHorizontal(GUILayout.Width(400));
        EditorGUI.BeginDisabledGroup(editMode.renderMode == BuildrEditMode.renderModes.full);
        if (GUILayout.Button("Full Detail", GUILayout.Height(28)))
        {
            editMode.UpdateRender(BuildrEditMode.renderModes.full);
        }
        EditorGUI.EndDisabledGroup();

        //Render a low detail version
        EditorGUI.BeginDisabledGroup(editMode.renderMode == BuildrEditMode.renderModes.lowDetail);
        if (GUILayout.Button("Low Detail", GUILayout.Height(28)))
        {
            editMode.UpdateRender(BuildrEditMode.renderModes.lowDetail);
        }
        EditorGUI.EndDisabledGroup();

        //Render a box version
        EditorGUI.BeginDisabledGroup(editMode.renderMode == BuildrEditMode.renderModes.box);
        if (GUILayout.Button("Box Outline", GUILayout.Height(28)))
        {
            editMode.UpdateRender(BuildrEditMode.renderModes.box);
        }
        EditorGUI.EndDisabledGroup();
        EditorGUILayout.EndHorizontal();

        //Toggle showing the wireframe when we have selected the model.
        EditorGUILayout.BeginHorizontal(GUILayout.Width(400));
        EditorGUILayout.LabelField("Show Wireframe");
        editMode.showWireframe = EditorGUILayout.Toggle(editMode.showWireframe, GUILayout.Width(15));
        EditorGUILayout.EndHorizontal();

        //Tangent calculation
        EditorGUILayout.BeginHorizontal(GUILayout.Width(400));
        EditorGUI.BeginDisabledGroup(editMode.fullMesh.hasTangents);
        if (GUILayout.Button("Build Tangents", GUILayout.Height(38)))
        {
            if (editMode.fullMesh != null)
            {
                editMode.fullMesh.SolveTangents();
            }
            if (editMode.detailMesh != null)
            {
                editMode.detailMesh.SolveTangents();
            }
            GUI.changed = false;
        }
        EditorGUI.EndDisabledGroup();
        if (!editMode.fullMesh.hasTangents)
        {
            EditorGUILayout.HelpBox("The model doesn't have tangents", MessageType.Warning);
        }
        EditorGUILayout.EndHorizontal();

        //Lightmap rendering
        EditorGUILayout.BeginHorizontal(GUILayout.Width(400));
        EditorGUI.BeginDisabledGroup(editMode.fullMesh.lightmapUvsCalculated);
        if (GUILayout.Button("Build Lightmap UVs", GUILayout.Height(38)))
        {
//            Undo.RegisterSceneUndo("Build Lightmap UVs");
            if (editMode.fullMesh != null)
            {
                for (int i = 0; i < editMode.fullMesh.meshCount; i++)
                {
                    Unwrapping.GenerateSecondaryUVSet(editMode.fullMesh[i].mesh);
                }
            }
            editMode.fullMesh.lightmapUvsCalculated = true;
            if (editMode.detailMesh != null)
            {
                for (int i = 0; i < editMode.detailMesh.meshCount; i++)
                {
                    Unwrapping.GenerateSecondaryUVSet(editMode.detailMesh[i].mesh);
                }
                editMode.detailMesh.lightmapUvsCalculated = true;
            }
            int numberOfInteriors = editMode.interiorMeshes.Count;
            for (int i = 0; i < numberOfInteriors; i++)
            {
                DynamicMeshGenericMultiMaterialMesh interiorMesh = editMode.interiorMeshes[i];
                for (int j = 0; j < interiorMesh.meshCount; j++)
                {
                    Unwrapping.GenerateSecondaryUVSet(interiorMesh[j].mesh);
                }
                interiorMesh.lightmapUvsCalculated = true;
            }
            GUI.changed = false;
        }
        EditorGUI.EndDisabledGroup();
        if (!editMode.fullMesh.lightmapUvsCalculated)
        {
            EditorGUILayout.HelpBox("The model doesn't have lightmap UVs", MessageType.Warning);
        }
        EditorGUILayout.EndHorizontal();

        //Mesh Optimisation
        EditorGUILayout.BeginHorizontal(GUILayout.Width(400));
        EditorGUI.BeginDisabledGroup(editMode.fullMesh.optimised);
        if (GUILayout.Button("Optimise Mesh For Runtime", GUILayout.Height(38)))
        {
//            Undo.RegisterSceneUndo("Optimise Mesh");
            if (editMode.fullMesh != null)
            {
                for (int i = 0; i < editMode.fullMesh.meshCount; i++)
                {
                    MeshUtility.Optimize(editMode.fullMesh[i].mesh);
                }
                editMode.fullMesh.optimised = true;
            }

            if (editMode.detailMesh != null)
            {
                for (int i = 0; i < editMode.detailMesh.meshCount; i++)
                {
                    MeshUtility.Optimize(editMode.detailMesh[i].mesh);
                }
                editMode.detailMesh.optimised = true;
            }
            GUI.changed = false;
        }
        EditorGUI.EndDisabledGroup();
        if (!editMode.fullMesh.optimised)
        {
            EditorGUILayout.HelpBox("The model is currently fully optimised for runtime", MessageType.Warning);
        }
        EditorGUILayout.EndHorizontal();

        //Underside render toggle
        EditorGUILayout.BeginHorizontal(GUILayout.Width(400));
        EditorGUILayout.LabelField("Render Underside of Building");
        bool drawUnderside = EditorGUILayout.Toggle(_data.drawUnderside, GUILayout.Width(15));

        if (drawUnderside != _data.drawUnderside)
        {
            _data.drawUnderside = drawUnderside;
        }
        EditorGUILayout.EndHorizontal();

        //Define the height of foundations if you need them
        EditorGUILayout.BeginHorizontal(GUILayout.Width(400));
        EditorGUILayout.LabelField("Foundation Height", GUILayout.Width(120));
        _data.foundationHeight = EditorGUILayout.Slider(_data.foundationHeight, 0, 25);
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Foundation Texture", GUILayout.Width(120));
        _data.foundationTexture = EditorGUILayout.Popup(_data.foundationTexture, textureNames, GUILayout.Width(260));
        EditorGUILayout.EndHorizontal();

        //Collider mesh
        EditorGUILayout.BeginHorizontal(GUILayout.Width(400));
        EditorGUILayout.LabelField("Generate Collider");
        _data.generateCollider = (BuildrData.ColliderGenerationModes)EditorGUILayout.EnumPopup(_data.generateCollider);
        EditorGUILayout.EndHorizontal();

        //One draw call mesh  -TODO
//        EditorGUILayout.BeginHorizontal(GUILayout.Width(400));
//        EditorGUILayout.LabelField("One Draw Call");
//        _data.oneDrawCall = EditorGUILayout.Toggle(_data.oneDrawCall);
//        EditorGUILayout.EndHorizontal();

        for (int i = 0; i < editMode.fullMesh.meshCount; i++)
        {
            EditorUtility.SetSelectedWireframeHidden(editMode.meshHolders[i].GetComponent <Renderer>(), !editMode.showWireframe);
        }
    }
    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;
                BuildrInteriors.Build(interiorMesh, data, v);
                interiorMesh.Build(false);

                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);
                }
            }
        }
    }
    //returns the number of meshes
    private static int ExportDetails(BuildrData data)
    {
        DynamicMeshGenericMultiMaterialMesh DET_MESH = new DynamicMeshGenericMultiMaterialMesh();
        BuildrDetailExportObject exportObject = BuildrBuildingDetails.Build(DET_MESH, data);

        int numberOfMeshes = exportObject.detailMeshes.Length;
        if (numberOfMeshes == 0)
            return 0;

        string textureName = data.exportFilename + ATLASED_SUFFIX + DETAIL_SUFFIX;
        string textureFileName = textureName + ".png";
        string newDirectory = ROOT_FOLDER + data.exportFilename;

        File.WriteAllBytes(newDirectory + "/" + textureFileName, exportObject.texture.EncodeToPNG());
        ExportMaterial[] exportTextures = new ExportMaterial[1];
        ExportMaterial newTexture = new ExportMaterial();
        newTexture.name = textureName;
        newTexture.filepath = textureFileName;
        newTexture.generated = true;
        exportTextures[0] = newTexture;
        for(int i = 0; i < numberOfMeshes; i++)
        {
            string DetailSuffixIndex = ((numberOfMeshes > 1) ? "_"+i : "");
            string DetailFileName = data.exportFilename + DETAIL_SUFFIX + DetailSuffixIndex;
            string DetailFolder = ROOT_FOLDER + data.exportFilename + "/";
            Export(DetailFileName, DetailFolder, data, exportObject.detailMeshes[i], exportTextures);
        }

        Texture2D.DestroyImmediate(exportObject.texture);

        return numberOfMeshes;
    }
Beispiel #34
0
    /// <summary>
    /// Generate the detail meshes and return the export object
    /// </summary>
    /// <param name="mesh"></param>
    /// <param name="data"></param>
    /// <returns></returns>
    public static BuildrDetailExportObject Build(DynamicMeshGenericMultiMaterialMesh mesh, BuildrData data)
    {
        BuildrDetailExportObject exportObject   = new BuildrDetailExportObject();
        List <Texture2D>         detailTextures = new List <Texture2D>();
        List <int> detailSubmeshesWithTextures  = new List <int>();
        int        numberOfDetails = data.details.Count;

        mesh.Clear();
        mesh.subMeshCount = numberOfDetails;

        for (int d = 0; d < numberOfDetails; d++)
        {
            BuildrDetail detail = data.details[d];
            if (detail.mesh == null)
            {
                continue;
            }
            int        faceIndex       = detail.face;
            Vector3    position        = Vector3.zero;
            BuildrPlan plan            = data.plan;
            int        numberOfVolumes = plan.numberOfVolumes;
            Vector2    faceUv          = detail.faceUv;
            Quaternion faceAngle       = Quaternion.identity;
            //Place the detail mesh
            if (detail.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 p0           = plan.points[volume.points[indexA]].vector3;
                            Vector3 p1           = plan.points[volume.points[indexB]].vector3;
                            Vector3 basePosition = Vector3.Lerp(p0, p1, faceUv.x);
                            Vector3 detailHeight = Vector3.up * (volume.numberOfFloors * data.floorHeight * faceUv.y);
                            Vector3 facadeCross  = Vector3.Cross(Vector3.up, p1 - p0).normalized;
                            Vector3 detailDepth  = facadeCross * detail.faceHeight;
                            faceAngle   = Quaternion.LookRotation(facadeCross);
                            position    = basePosition + detailHeight + detailDepth;
                            facadeFound = true;
                            break;
                        }
                        facadeCount++;
                    }
                    if (facadeFound)
                    {
                        break;
                    }
                }
            }
            else//roof detail
            {
                BuildrVolume volume = plan.volumes[Mathf.Clamp(0, numberOfVolumes - 1, faceIndex)];
                int          numberOfVolumePoints = volume.points.Count;
                Vector3      minimumRoofPoint     = plan.points[volume.points[0]].vector3;
                Vector3      maximumRoofPoint     = minimumRoofPoint;
                for (int p = 1; p < numberOfVolumePoints; p++)
                {
                    Vector3 p0 = plan.points[volume.points[p]].vector3;
                    if (p0.x < minimumRoofPoint.x)
                    {
                        minimumRoofPoint.x = p0.x;
                    }
                    if (p0.z < minimumRoofPoint.y)
                    {
                        minimumRoofPoint.y = p0.z;
                    }
                    if (p0.x > maximumRoofPoint.x)
                    {
                        maximumRoofPoint.x = p0.x;
                    }
                    if (p0.z > maximumRoofPoint.y)
                    {
                        maximumRoofPoint.y = p0.z;
                    }
                }
                position.x = Mathf.Lerp(minimumRoofPoint.x, maximumRoofPoint.x, faceUv.x);
                position.z = Mathf.Lerp(minimumRoofPoint.y, maximumRoofPoint.y, faceUv.y);
                position.y = volume.numberOfFloors * data.floorHeight + detail.faceHeight;
            }

            Quaternion userRotation = Quaternion.Euler(detail.userRotation);
            int        vertexCount  = detail.mesh.vertexCount;
            Vector3[]  verts        = new Vector3[vertexCount];
            Quaternion rotate       = faceAngle * userRotation;
            for (int i = 0; i < vertexCount; i++)
            {
                Vector3 sourceVertex = Vector3.Scale(detail.mesh.vertices[i], detail.scale);
                Vector3 outputVertex = (rotate) * sourceVertex + position;
                verts[i] = outputVertex;
            }
            mesh.AddData(verts, detail.mesh.uv, detail.mesh.triangles, d);
            detail.worldPosition = position;
            detail.worldRotation = rotate;

            if (detail.material.mainTexture != null)
            {
#if UNITY_EDITOR
                string          texturePath     = AssetDatabase.GetAssetPath(detail.material.mainTexture);
                TextureImporter textureImporter = (TextureImporter)AssetImporter.GetAtPath(texturePath);

                if (!textureImporter.isReadable)
                {
                    Debug.LogWarning("The texture you have selected is not readable. Cannot render");
                    return(exportObject);
                }

                detailTextures.Add((Texture2D)detail.material.mainTexture);
                detailSubmeshesWithTextures.Add(d);
#endif
            }
        }

        if (detailtexture != null)
        {
            Object.DestroyImmediate(detailtexture);
        }

        List <Mesh> outputMeshes = new List <Mesh>();
        if (detailSubmeshesWithTextures.Count > 0)
        {
            Rect[] textureRects = BuildrTexturePacker2.Pack(out detailtexture, detailTextures.ToArray(), 512);
            if (detailSubmeshesWithTextures.Count > 0)
            {
                mesh.Atlas(detailSubmeshesWithTextures.ToArray(), textureRects);
            }
            mesh.CollapseSubmeshes();
            mesh.Build();
            int numberOfMeshes = mesh.meshCount;
            for (int i = 0; i < numberOfMeshes; i++)
            {
                outputMeshes.Add(mesh[i].mesh);
            }
        }

        exportObject.detailMeshes = outputMeshes.ToArray();
        exportObject.texture      = detailtexture;
        return(exportObject);

        /*if (detailMat == null)
         *      detailMat = new Material(Shader.Find("Diffuse"));
         *  detailMat.mainTexture = detailtexture;
         *  List<Mesh> outputMeshes = new List<Mesh>();
         *  for (int i = 0; i < numberOfMeshes; i++)
         *  {
         *      outputMeshes.Add(mesh[i].mesh);
         *      GameObject details = new GameObject("details " + i);
         *      details.AddComponent<MeshFilter>().mesh = mesh[i].mesh;
         *      details.AddComponent<MeshRenderer>().sharedMaterial = detailMat;
         *      detailGameobjects.Add(details);
         *  }
         * }
         * //        Debug.Log("BuildR Detail Pack Complete: " + (Time.realtimeSinceStartup - timestart) + " sec");
         * return detailGameobjects.ToArray();*/
    }
    private static void ExportModel(BuildrData data)
    {
        try
        {
            EditorUtility.DisplayCancelableProgressBar(PROGRESSBAR_TEXT, "", 0.0f);

            //check overwrites...
            string newDirectory = ROOT_FOLDER + data.exportFilename;
            if(!CreateFolder(newDirectory))
            {
                EditorUtility.ClearProgressBar();
                return;
            }

            EditorUtility.DisplayCancelableProgressBar(PROGRESSBAR_TEXT, "", 0.05f);
            if(data.fullmesh)
            {
                //export unpacked model
                DYN_MESH = new DynamicMeshGenericMultiMaterialMesh();
                DYN_MESH.subMeshCount = data.textures.Count;
                BuildrBuilding.Build(DYN_MESH, data);
                EditorUtility.DisplayCancelableProgressBar(PROGRESSBAR_TEXT, "", 0.30f);
                BuildrRoof.Build(DYN_MESH, data);
                EditorUtility.DisplayCancelableProgressBar(PROGRESSBAR_TEXT, "", 0.60f);
                DYN_MESH.Build(data.includeTangents);
                int meshCount = DYN_MESH.meshCount;

                List<int> unusedTextures = DYN_MESH.unusedSubmeshes;
                int numberOfUnpackedTextures = data.textures.Count;
                List<ExportMaterial> exportTextureList = new List<ExportMaterial>();
                for (int t = 0; t < numberOfUnpackedTextures; t++)
                {
                    if (unusedTextures.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;
                    exportTextureList.Add(newTexture);
                }
                for(int i = 0; i < meshCount; i++)
                {
                    EXPORT_MESH = DYN_MESH[i].mesh;
                    MeshUtility.Optimize(EXPORT_MESH);
                    Export(data, EXPORT_MESH, exportTextureList.ToArray());
                    string filenameSuffix = (meshCount>1)? i.ToString() : "";
                    string filename = data.exportFilename + filenameSuffix;
                    Export(filename, ROOT_FOLDER + data.exportFilename + "/", data, EXPORT_MESH, exportTextureList.ToArray());
                }
            }

            //Export Collider
            if(data.generateCollider != BuildrData.ColliderGenerationModes.None)
                ExportCollider(data);

            int[] numberOfInteriorMeshes = new int[data.plan.numberOfVolumes];
            if(data.renderInteriors && data.fullmesh)
                numberOfInteriorMeshes = ExportInteriors(data);

            int[] numberOfStairwells = new int[data.plan.numberOfVolumes];
            if (data.renderInteriors && data.fullmesh)
                numberOfStairwells = ExportStairwells(data);

            int numberOfDetailMeshes = 0;
            if(data.fullmesh)
                numberOfDetailMeshes = ExportDetails(data);

            EditorUtility.DisplayCancelableProgressBar(PROGRESSBAR_TEXT, "", 0.70f);

            //Place exported version into scene
            if(data.fullmesh)
            {
                AssetDatabase.Refresh();//ensure the database is up to date...
                GameObject baseObject = new GameObject(data.exportFilename);
                if((data.createPrefabOnExport || data.placeIntoScene))
                {
                    baseObject.transform.position = CURRENT_TRANSFORM.position;
                    baseObject.transform.rotation = CURRENT_TRANSFORM.rotation;

                    string modelFilePath = ROOT_FOLDER + data.exportFilename + "/" + data.exportFilename + FILE_EXTENTION;
                    GameObject newModel = (GameObject)PrefabUtility.InstantiatePrefab(AssetDatabase.LoadMainAssetAtPath(modelFilePath));
                    newModel.name = "model";
                    newModel.transform.parent = baseObject.transform;
                    newModel.transform.localPosition = Vector3.zero;
                    newModel.transform.localRotation = Quaternion.identity;
                    if(data.generateCollider != BuildrData.ColliderGenerationModes.None)
                    {
                        GameObject colliderObject = new GameObject("collider");
                        string colliderFilePath = ROOT_FOLDER + data.exportFilename + "/" + data.exportFilename + COLLIDER_SUFFIX + FILE_EXTENTION;
                        colliderObject.AddComponent<MeshCollider>().sharedMesh = (Mesh)AssetDatabase.LoadAssetAtPath(colliderFilePath, typeof(Mesh));
                        colliderObject.transform.parent = baseObject.transform;
                        colliderObject.transform.localPosition = Vector3.zero;
                        colliderObject.transform.localRotation = Quaternion.identity;
                    }

                    for (int i = 0; i < numberOfDetailMeshes; i++)
                    {
                        string detailSuffixIndex = ((numberOfDetailMeshes > 1) ? "_" + i : "");
                        string detailFileName = data.exportFilename + DETAIL_SUFFIX + detailSuffixIndex;
                        string detailFolder = ROOT_FOLDER + data.exportFilename + "/";
                        string detailFilepath = detailFolder + detailFileName + FILE_EXTENTION;
                        GameObject detailObject = (GameObject)PrefabUtility.InstantiatePrefab(AssetDatabase.LoadMainAssetAtPath(detailFilepath));
                        detailObject.name = "details";
                        detailObject.transform.parent = baseObject.transform;
                        detailObject.transform.localPosition = Vector3.zero;
                        detailObject.transform.localRotation = Quaternion.identity;
                    }

                    int numberOfVolumes = data.plan.numberOfVolumes;
                    GameObject interiorHolder = new GameObject("interiors");
                    interiorHolder.transform.parent = baseObject.transform;
                    interiorHolder.transform.localPosition = Vector3.zero;
                    interiorHolder.transform.localRotation = Quaternion.identity;
                    for (int v = 0; v < numberOfInteriorMeshes.Length; v++)
                    {
                        int numMeshes = numberOfInteriorMeshes[v];
                        for (int i = 0; i < numMeshes; i++)
                        {
                            string VolumeSuffix = ((numberOfVolumes > 1) ? "_" + v : "");
                            string DetailSuffixIndex = ((numMeshes > 1) ? "_" + i : "");
                            string DetailFileName = data.exportFilename + INTERIOR_SUFFIX + VolumeSuffix + DetailSuffixIndex;
                            string DetailFolder = ROOT_FOLDER + data.exportFilename + "/";
                            string filePath = DetailFolder + DetailFileName + FILE_EXTENTION;
                            GameObject interiorObject = (GameObject)PrefabUtility.InstantiatePrefab(AssetDatabase.LoadMainAssetAtPath(filePath));
                            interiorObject.name = INTERIOR_SUFFIX + VolumeSuffix + DetailSuffixIndex;
                            interiorObject.transform.parent = interiorHolder.transform;
                            interiorObject.transform.localPosition = Vector3.zero;
                            interiorObject.transform.localRotation = Quaternion.identity;
                        }
                    }

                    for(int v = 0; v < numberOfStairwells.Length; v++)
                    {
                        int numMeshes = numberOfStairwells[v];
                        for (int i = 0; i < numMeshes; i++)
                        {
                            string VolumeSuffix = ((numberOfVolumes > 1) ? "_" + v : "");
                            string DetailSuffixIndex = ((numMeshes > 1) ? "_" + i : "");
                            string DetailFileName = data.exportFilename + STAIR_SUFFIX + VolumeSuffix + DetailSuffixIndex;
                            string DetailFolder = ROOT_FOLDER + data.exportFilename + "/";
                            string filePath = DetailFolder + DetailFileName + FILE_EXTENTION;
                            GameObject interiorObject = (GameObject)PrefabUtility.InstantiatePrefab(AssetDatabase.LoadMainAssetAtPath(filePath));
                            interiorObject.name = STAIR_SUFFIX + VolumeSuffix + DetailSuffixIndex;
                            interiorObject.transform.parent = interiorHolder.transform;
                            interiorObject.transform.localPosition = data.plan.volumes[v].stairBaseVector[i];
                            interiorObject.transform.localRotation = Quaternion.identity;
                        }
                    }
                }

                if(data.createPrefabOnExport)
                {
                    string prefabPath = ROOT_FOLDER + data.exportFilename + "/" + data.exportFilename + ".prefab";
                    Object prefab = AssetDatabase.LoadAssetAtPath(prefabPath, typeof(GameObject));
                    if(prefab == null)
                        prefab = PrefabUtility.CreateEmptyPrefab(prefabPath);
                    PrefabUtility.ReplacePrefab(baseObject, prefab, ReplacePrefabOptions.ConnectToPrefab);
                }

                if(!data.placeIntoScene)
                    Object.DestroyImmediate(baseObject);
            }

            if(data.exportLowLOD)
            {
                ExportLowLOD(data);
            }

            DYN_MESH = null;
            EXPORT_MESH = null;

            EditorUtility.ClearProgressBar();
            EditorUtility.UnloadUnusedAssets();

            AssetDatabase.Refresh();
        }catch(System.Exception e)
        {
            Debug.LogError("BuildR Export Error: "+e);
            EditorUtility.ClearProgressBar();
        }
    }
Beispiel #36
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;
    }
    public void UpdateDetails()
    {
        int numberOfDetails = 0;
        if (details != null)
            numberOfDetails = details.Length;
        for (int i = 0; i < numberOfDetails; i++)
            DestroyImmediate(details[i]);

        if (data.plan == null)
            return;
        if (data.floorHeight == 0)
            return;
        if (data.details.Count == 0)
            return;
        if (detailMesh == null)
            detailMesh = new DynamicMeshGenericMultiMaterialMesh();

        if (renderMode != renderModes.full)
            return;//once data is cleared - asses if we want to rerender the details

        details = BuildrBuildingDetails.Render(detailMesh,data);
        numberOfDetails = details.Length;

        for (int i = 0; i < numberOfDetails; i++)
        {
           details[i].transform.parent = transform;
           details[i].transform.localPosition = Vector3.zero;
           details[i].transform.localRotation = Quaternion.identity;
        }
    }
Beispiel #38
0
    public static void Build(DynamicMeshGenericMultiMaterialMesh _mesh, BuildrData _data, Rect[] uvConstraints)
    {
        data = _data;
        mesh = _mesh;
        textures = data.textures.ToArray();
        BuildrFacadeDesign facadeDesign = data.facades[0];
        BuildrPlan plan = data.plan;
        int numberOfVolumes = plan.numberOfVolumes;

        if(plan.numberOfFacades != uvConstraints.Length)
            Debug.LogError("Incompatible amount of uv constraints " + plan.numberOfFacades +" uvc: "+ uvConstraints.Length);

        float largestDepthValue = 0;//deepest value of a bay design in the building
        foreach (BuildrBay bay in data.bays)
            largestDepthValue = Mathf.Max(largestDepthValue, bay.deepestValue);//get the deepest value
        foreach (BuildrFacadeDesign facade in data.facades)
            largestDepthValue = Mathf.Max(largestDepthValue, facade.simpleBay.deepestValue);//get the deepest value

        int facadeCount = 0;
        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 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;

                facadeCount++;

                float realFadeWidth = Vector3.Distance(p0, p1);
                float facadeWidth = realFadeWidth - largestDepthValue * 2.0f;
                Vector3 facadeDirection = (p1 - p0).normalized;
                Vector3 facadeCross = Vector3.Cross(facadeDirection, Vector3.up).normalized;
                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(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);
                p0 += floorHeightStart;
                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;

                float foundationHeight = data.foundationHeight;
                if (foundationHeight > 0 && floorBase == 0)
                {
                    int subMesh = _data.foundationTexture;
                    Vector3 foundationVector = Vector3.up * -foundationHeight;
                    Vector3 w0 = p0 + foundationVector;
                    Vector3 w1 = p1 + foundationVector;
                    Vector3 w2 = p0;
                    Vector3 w3 = p1;
                    AddPlane(w0, w1, w2, w3, subMesh, false, new Vector2(0, -foundationHeight), new Vector2(facadeWidth, 0));
                }

                Vector2 facadeUV = Vector2.zero;

                for (int r = 0; r < rows; r++)
                {
                    bool firstRow = r == 0;
                    bool lastRow = r == (rows - 1);
                    //Get the facade style id
                    //need to loop through the facade designs floor by floor until we get to the right one
                    float currentHeight = floorHeight * r;
                    Vector3 facadeFloorBaseVector = p0 + Vector3.up * currentHeight;
                    int modFloor = (r % floorPatternSize);
                    int modFloorPlus = ((r + 1) % floorPatternSize);
                    int modFloorMinus = (r > 0) ? ((r - 1) % floorPatternSize) : 0;
                    BuildrFacadeDesign lastFacadeDesign = null;
                    BuildrFacadeDesign nextFacadeDesign = null;

                    facadeDesign = data.facades[styleUnits[facadePatternReference[modFloor]].styleID];
                    nextFacadeDesign = data.facades[styleUnits[facadePatternReference[modFloorPlus]].styleID];
                    lastFacadeDesign = data.facades[styleUnits[facadePatternReference[modFloorMinus]].styleID];

                    bool isBlankWall = !facadeDesign.hasWindows;
                    if (facadeDesign.type == BuildrFacadeDesign.types.patterned)
                    {
                        if(data.bays.Count == 0 || facadeDesign.bayPattern.Count == 0)
                            isBlankWall = true;
                        else
                        {
                            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;
                    }

                    Vector3 windowBase = facadeFloorBaseVector;
                    facadeUV.x = 0;
                    facadeUV.y += currentHeight;
                    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;
                        }

                        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;

                            //                            float openingHeight = bayStyle.openingHeight;
                            BuildrTexture columnTexture = textures[bayStyle.GetTexture(BuildrBay.TextureNames.ColumnTexture)];
                            Vector2 columnuvunits = columnTexture.tileUnitUV;
                            float openingHeight = bayStyle.openingHeight;
                            if (columnTexture.patterned) openingHeight = Mathf.Round(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;
                            float windowSideDepth, bottomDepth;

                            if (!bayStyle.isOpening)
                            {
                                int wallSubMesh = bayStyle.GetTexture(BuildrBay.TextureNames.WallTexture);
                                bool wallFlipped = bayStyle.IsFlipped(BuildrBay.TextureNames.WallTexture);
                                float bayWidthSize = openingWidth + actualWindowSpacing;
                                if (firstColumn || lastColumn) bayWidthSize += largestDepthValue;
                                Vector3 bayWidth = facadeDirection * bayWidthSize;
                                Vector3 bayHeight = Vector3.up * floorHeight;
                                Vector3 bayDepth = facadeCross * largestDepthValue;
                                w0 = windowBase;
                                w1 = windowBase + bayWidth;
                                w2 = windowBase + bayHeight;
                                w3 = windowBase + bayWidth + bayHeight;
                                Vector2 bayOpeningUVEnd = facadeUV + new Vector2(openingWidth + actualWindowSpacing, floorHeight);
                                AddPlane(w0, w1, w2, w3, wallSubMesh, wallFlipped, facadeUV, bayOpeningUVEnd);

                                Vector2 UVEnd = new Vector2(1, floorHeight);
                                if (!previousBayIdentical && !firstColumn)//left
                                {
                                    Vector3 wA = w0 + bayDepth;
                                    Vector3 wB = w2 + bayDepth;
                                    AddPlane(w2, wB, w0, wA, wallSubMesh, wallFlipped, Vector2.zero, UVEnd);
                                }

                                if (!nextBayIdentical && !lastColumn)//right
                                {
                                    Vector3 wA = w1 + bayDepth;
                                    Vector3 wB = w3 + bayDepth;
                                    AddPlane(w1, wA, w3, wB, wallSubMesh, wallFlipped, Vector2.zero, UVEnd);
                                }

                                if (lastFacadeDesign != facadeDesign && !firstRow)//bottom
                                {
                                    Vector3 wA = w0 + ((!firstColumn) ? facadeCross*largestDepthValue : -lastFacadeDirection*largestDepthValue);
                                    Vector3 wB = w1 + ((!lastColumn) ? facadeCross*largestDepthValue : nextFacadeDirection*largestDepthValue);
                                    AddPlane(w0, wA, w1, wB, wallSubMesh, wallFlipped, Vector2.zero, UVEnd);
                                }
                                if (nextFacadeDesign != facadeDesign && !lastRow)//top
                                {
                                    Vector3 wA = w2 + ((!firstColumn) ? facadeCross*largestDepthValue : -lastFacadeDirection*largestDepthValue);
                                    Vector3 wB = w3 + ((!lastColumn) ? facadeCross*largestDepthValue : nextFacadeDirection*largestDepthValue);
                                    AddPlane(w3, wB, w2, wA, wallSubMesh, wallFlipped, Vector2.zero, UVEnd);
                                }

                                windowBase = w1;//move base vertor to next bay
                                facadeUV.x += bayWidthSize;
                                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;

                            Vector3 openingDepthVector = facadeCross * bayStyle.openingDepth;
                            Vector3 crossDepthVector = facadeCross * bayStyle.crossDepth;
                            Vector3 rowDepthVector = facadeCross * bayStyle.rowDepth;
                            Vector3 columnDepthVector = facadeCross * bayStyle.columnDepth;
                            Vector3 largestDepthVector = facadeCross * largestDepthValue;
                            Vector2 uvStart, uvEnd;

                            int windowSubMesh = bayStyle.GetTexture(BuildrBay.TextureNames.OpeningBackTexture);
                            int submeshBottom = bayStyle.GetTexture(BuildrBay.TextureNames.OpeningSillTexture);
                            int submeshTop = bayStyle.GetTexture(BuildrBay.TextureNames.OpeningCeilingTexture);
                            int columnSubMesh = bayStyle.GetTexture(BuildrBay.TextureNames.ColumnTexture);
                            int crossSubMesh = bayStyle.GetTexture(BuildrBay.TextureNames.CrossTexture);
                            int rowSubMesh = bayStyle.GetTexture(BuildrBay.TextureNames.RowTexture);
                            bool windowFlipped = bayStyle.IsFlipped(BuildrBay.TextureNames.OpeningBackTexture);
                            bool flippedBottom = bayStyle.IsFlipped(BuildrBay.TextureNames.OpeningSillTexture);
                            bool flippedTop = bayStyle.IsFlipped(BuildrBay.TextureNames.OpeningCeilingTexture);
                            bool columnFlipped = bayStyle.IsFlipped(BuildrBay.TextureNames.ColumnTexture);
                            bool crossFlipped = bayStyle.IsFlipped(BuildrBay.TextureNames.CrossTexture);
                            bool rowFlipped = bayStyle.IsFlipped(BuildrBay.TextureNames.RowTexture);
                            int windowBoxSubmesh = bayStyle.GetTexture(BuildrBay.TextureNames.OpeningSideTexture);
                            bool windowBoxFlipped = bayStyle.IsFlipped(BuildrBay.TextureNames.OpeningSideTexture);

                            ///WINDOWS
                            w0 = verts[5] + openingDepthVector;
                            w1 = verts[6] + openingDepthVector;
                            w2 = verts[9] + openingDepthVector;
                            w3 = verts[10] + openingDepthVector;
                            Vector2 windowUVStart = facadeUV + new Vector2(leftWidth, rowBottomHeight);
                            Vector2 windowUVEnd = windowUVStart + new Vector2(openingWidth, openingHeight);
                            if (bayStyle.renderBack && !data.cullBays)
                                AddPlane(w0, w1, w2, w3, windowSubMesh, windowFlipped, windowUVStart, windowUVEnd);

                            //Window Sides
                            w0 = verts[5] + largestDepthVector;
                            w1 = verts[6] + largestDepthVector;
                            w2 = verts[9] + largestDepthVector;
                            w3 = verts[10] + largestDepthVector;
                            windowSideDepth = Mathf.Min(bayStyle.columnDepth, bayStyle.openingDepth) - largestDepthValue;//Window Left
                            float columnDiff = bayStyle.columnDepth - bayStyle.openingDepth;
                            if (data.renderInteriors)//Inner Window Walls
                            {
                                //left
                                uvStart = facadeUV + new Vector2(leftWidth, rowBottomHeight);
                                uvEnd = uvStart + new Vector2(windowSideDepth, openingHeight);
                                Vector3 leftDepthVector = facadeCross * windowSideDepth;
                                if (firstColumn) leftDepthVector = facadeCross * -largestDepthValue;
                                Vector3 wl0 = w0 + leftDepthVector;
                                Vector3 wl2 = w2 + leftDepthVector;
                                AddPlane(wl0, w0, wl2, w2, windowBoxSubmesh, windowBoxFlipped, uvStart, uvEnd);
                                //right
                                uvStart = facadeUV + new Vector2(leftWidth + openingWidth - windowSideDepth, rowBottomHeight);
                                uvEnd = uvStart + new Vector2(windowSideDepth, openingHeight);
                                Vector3 rightDepthVector = facadeCross * windowSideDepth;
                                if (lastColumn) rightDepthVector = facadeCross * -largestDepthValue;
                                Vector3 wr1 = w1 + rightDepthVector;
                                Vector3 wr3 = w3 + rightDepthVector;
                                AddPlane(wr3, w3, wr1, w1, windowBoxSubmesh, windowBoxFlipped, uvEnd, uvStart);
                            }

                            if (columnDiff > 0 || !data.renderInteriors)//External Window Sides
                            {
                                //left
                                uvStart = facadeUV + new Vector2(leftWidth, rowBottomHeight);
                                uvEnd = uvStart + new Vector2(columnDiff, openingHeight);
                                Vector3 sideDepthVectorA = facadeCross * (bayStyle.columnDepth - largestDepthValue);
                                Vector3 sideDepthVectorB = facadeCross * (bayStyle.openingDepth - largestDepthValue);
                                if (firstColumn) sideDepthVectorA = facadeCross * -largestDepthValue;
                                Vector3 wd0l = w0 + sideDepthVectorA;
                                Vector3 wd1l = w2 + sideDepthVectorA;
                                Vector3 wd2l = w0 + sideDepthVectorB;
                                Vector3 wd3l = w2 + sideDepthVectorB;
                                AddPlane(wd0l, wd2l, wd1l, wd3l, windowBoxSubmesh, windowBoxFlipped, uvStart, uvEnd);
                                //      right                          
                                uvStart = facadeUV + new Vector2(leftWidth + openingWidth - windowSideDepth, rowBottomHeight);
                                uvEnd = uvStart + new Vector2(windowSideDepth, openingHeight);
                                sideDepthVectorA = facadeCross * (bayStyle.columnDepth - largestDepthValue);
                                sideDepthVectorB = facadeCross * (bayStyle.openingDepth - largestDepthValue);
                                if (lastColumn) sideDepthVectorA = facadeCross * -largestDepthValue;
                                Vector3 wd0r = w1 + sideDepthVectorA;
                                Vector3 wd1r = w3 + sideDepthVectorA;
                                Vector3 wd2r = w1 + sideDepthVectorB;
                                Vector3 wd3r = w3 + sideDepthVectorB;
                                AddPlane(wd1r, wd3r, wd0r, wd2r, windowBoxSubmesh, windowBoxFlipped, uvStart, uvEnd);
                            }

                            //Window Row Sides/Sills
                            bottomDepth = Mathf.Min(bayStyle.rowDepth, bayStyle.openingDepth) - largestDepthValue;
                            float rowDiff = bayStyle.rowDepth - bayStyle.openingDepth;
                            if (data.renderInteriors)//Window Sill Interiors
                            {
                                uvStart = new Vector2(leftWidth, 0);
                                uvEnd = uvStart + new Vector2(openingWidth, bottomDepth);

//                                if (rowBottomHeight > 0)//Bottom
//                                {
                                    Vector3 bottomDepthVector = facadeCross * bottomDepth;
                                    Vector3 wl0 = w0 + bottomDepthVector;
                                    Vector3 wl1 = w1 + bottomDepthVector;
                                    AddPlane(wl0, wl1, w0, w1, submeshBottom, flippedBottom, uvStart, uvEnd);
//                                }
//                                if (rowTopHeight > 0)//Top
//                                {
                                    Vector3 topDepthVector = facadeCross * bottomDepth;
                                    Vector3 wl2 = w2 + topDepthVector;
                                    Vector3 wl3 = w3 + topDepthVector;
                                    AddPlane(w2, w3, wl2, wl3, submeshTop, flippedTop, uvStart, uvEnd);
//                                }
                            }

                            if (rowDiff > 0 || !data.renderInteriors)//Window External Sills
                            {
                                uvStart = facadeUV + new Vector2(leftWidth, 0);
                                uvEnd = uvStart + new Vector2(openingWidth, rowDiff);

//                                if (rowBottomHeight > 0)//Bottom
//                                {
                                    Vector3 wd0l = w0 + facadeCross * (bayStyle.rowDepth - largestDepthValue);
                                    Vector3 wd1l = w1 + facadeCross * (bayStyle.rowDepth - largestDepthValue);
                                    Vector3 wd2l = w0 + facadeCross * (bayStyle.openingDepth - largestDepthValue);
                                    Vector3 wd3l = w1 + facadeCross * (bayStyle.openingDepth - largestDepthValue);
                                    AddPlane(wd0l, wd1l, wd2l, wd3l, submeshBottom, flippedBottom, uvStart, uvEnd);
//                                }

//                                if (rowTopHeight > 0)//Top
//                                {
                                    Vector3 wd0r = w2 + facadeCross * (bayStyle.rowDepth - largestDepthValue);
                                    Vector3 wd1r = w3 + facadeCross * (bayStyle.rowDepth - largestDepthValue);
                                    Vector3 wd2r = w2 + facadeCross * (bayStyle.openingDepth - largestDepthValue);
                                    Vector3 wd3r = w3 + facadeCross * (bayStyle.openingDepth - largestDepthValue);
                                    AddPlane(wd1r, wd0r, wd3r, wd2r, submeshTop, flippedTop, uvStart, uvEnd);
//                                }
                            }

                            ///COLUMNS
                            //Column Face
                            if (leftWidth > 0)//Column Face Left
                            {
                                Vector3 leftColumnDepthVector = (!firstColumn) ? columnDepthVector : Vector3.zero;
                                w0 = verts[4] + leftColumnDepthVector;
                                w1 = verts[5] + leftColumnDepthVector;
                                w2 = verts[8] + leftColumnDepthVector;
                                w3 = verts[9] + leftColumnDepthVector;
                                Vector2 leftColumnUVStart = facadeUV + new Vector2(0, rowBottomHeight);
                                Vector2 leftColumnUVEnd = leftColumnUVStart + new Vector2(leftWidth, openingHeight);
                                AddPlane(w0, w1, w2, w3, columnSubMesh, columnFlipped, leftColumnUVStart, leftColumnUVEnd);

                                if (!firstColumn)//Left Column Top Bottom
                                {
                                    w0 = verts[4] + largestDepthVector;
                                    w1 = verts[5] + largestDepthVector;
                                    w2 = verts[8] + largestDepthVector;
                                    w3 = verts[9] + largestDepthVector;

                                    bottomDepth = Mathf.Min(bayStyle.crossDepth, bayStyle.columnDepth) - largestDepthValue;
                                    float colDiff = bayStyle.crossDepth - bayStyle.columnDepth;
                                    if (bottomDepth != 0)
                                    {
                                        if (data.renderInteriors)
                                        {
                                            uvStart = new Vector2(0, 0);
                                            uvEnd = uvStart + new Vector2(leftWidth, bottomDepth);
                                            Vector3 bottomDepthVector = facadeCross * bottomDepth;
//                                            if(rowBottomHeight>0)
//                                            {
                                                Vector3 wl0 = w0 + bottomDepthVector;
                                                Vector3 wl1 = w1 + bottomDepthVector;
                                                AddPlane(wl0, wl1, w0, w1, submeshBottom, flippedBottom, uvStart, uvEnd);
//                                            }
//                                            if(rowTopHeight > 0)
//                                            {
                                                Vector3 wl2 = w2 + bottomDepthVector;
                                                Vector3 wl3 = w3 + bottomDepthVector;
                                                AddPlane(w2, w3, wl2, wl3, submeshTop, flippedTop, uvStart, uvEnd);
//                                            }
                                        }

                                        if (colDiff > 0 || !data.renderInteriors)
                                        {
                                            uvStart = new Vector2(0, rowBottomHeight);
                                            uvEnd = uvStart + new Vector2(rowDiff, openingHeight);
//                                            if(rowBottomHeight > 0)//Bottom
//                                            {
                                                Vector3 wd0l = w0 + facadeCross * (bayStyle.crossDepth - largestDepthValue);
                                                Vector3 wd1l = w1 + facadeCross * (bayStyle.crossDepth - largestDepthValue);
                                                Vector3 wd2l = w0 + facadeCross * (bayStyle.columnDepth - largestDepthValue);
                                                Vector3 wd3l = w1 + facadeCross * (bayStyle.columnDepth - largestDepthValue);
                                                AddPlane(wd2l, wd0l, wd3l, wd1l, submeshBottom, flippedBottom, uvStart, uvEnd);
//                                            }
//                                            if(rowTopHeight > 0)//Top
//                                            {
                                                Vector3 wd0r = w2 + facadeCross * (bayStyle.crossDepth - largestDepthValue);
                                                Vector3 wd1r = w3 + facadeCross * (bayStyle.crossDepth - largestDepthValue);
                                                Vector3 wd2r = w2 + facadeCross * (bayStyle.columnDepth - largestDepthValue);
                                                Vector3 wd3r = w3 + facadeCross * (bayStyle.columnDepth - largestDepthValue);
                                                AddPlane(wd3r, wd1r, wd2r, wd0r, submeshTop, flippedTop, uvStart, uvEnd);
//                                            }
                                        }
                                    }
                                }
                            }
                            if ((!nextBayIdentical || lastColumn) && rightWidth > 0)//Column Right
                            {
                                Vector3 rightColumeDepthVector = (!lastColumn) ? columnDepthVector : Vector3.zero;
                                w0 = verts[6] + rightColumeDepthVector;
                                w1 = verts[7] + rightColumeDepthVector;
                                w2 = verts[10] + rightColumeDepthVector;
                                w3 = verts[11] + rightColumeDepthVector;
                                Vector2 rightColumnUVStart = facadeUV + new Vector2(leftWidth + openingWidth, rowBottomHeight);
                                Vector2 rightColumnUVEnd = rightColumnUVStart + new Vector2(rightWidth, openingHeight);
                                AddPlane(w0, w1, w2, w3, columnSubMesh, columnFlipped, rightColumnUVStart, rightColumnUVEnd);
                                if (!lastColumn)//Right Column Top Bottom
                                {
                                    w0 = verts[6] + largestDepthVector;
                                    w1 = verts[7] + largestDepthVector;
                                    w2 = verts[10] + largestDepthVector;
                                    w3 = verts[11] + largestDepthVector;

                                    bottomDepth = Mathf.Min(bayStyle.crossDepth, bayStyle.columnDepth) - largestDepthValue;//Window Left
                                    float colDiff = bayStyle.crossDepth - bayStyle.columnDepth;
                                    if (bottomDepth != 0)
                                    {
                                        if (data.renderInteriors)
                                        {
                                            uvStart = new Vector2(leftWidth+openingWidth, 0);
                                            uvEnd = uvStart + new Vector2(rightWidth, bottomDepth);
                                            Vector3 bottomDepthVector = facadeCross * bottomDepth;
                                            if (rowBottomHeight > 0)
                                            {
                                                Vector3 wl0 = w0 + bottomDepthVector;
                                                Vector3 wl1 = w1 + bottomDepthVector;
                                                AddPlane(wl0, wl1, w0, w1, submeshBottom, flippedBottom, uvStart, uvEnd);
                                            }
                                            if (rowTopHeight > 0)
                                            {
                                                Vector3 wl2 = w2 + bottomDepthVector;
                                                Vector3 wl3 = w3 + bottomDepthVector;
                                                AddPlane(wl3, wl2, w3, w2, submeshTop, flippedTop, uvStart, uvEnd);
                                            }
                                        }

                                        if (colDiff > 0 || !data.renderInteriors)
                                        {
                                            uvStart = facadeUV + new Vector2(0, rowBottomHeight);
                                            uvEnd = uvStart + new Vector2(rowDiff, openingHeight);
                                            if (rowBottomHeight > 0)//Bottom
                                            {
                                                Vector3 wd0l = w0 + facadeCross * (bayStyle.crossDepth - largestDepthValue);
                                                Vector3 wd1l = w1 + facadeCross * (bayStyle.crossDepth - largestDepthValue);
                                                Vector3 wd2l = w0 + facadeCross * (bayStyle.columnDepth - largestDepthValue);
                                                Vector3 wd3l = w1 + facadeCross * (bayStyle.columnDepth - largestDepthValue);
                                                AddPlane(wd2l, wd0l, wd3l, wd1l, submeshBottom, flippedBottom, uvStart, uvEnd);
                                            }
                                            if (rowTopHeight > 0)//Top
                                            {
                                                Vector3 wd0r = w2 + facadeCross * (bayStyle.crossDepth - largestDepthValue);
                                                Vector3 wd1r = w3 + facadeCross * (bayStyle.crossDepth - largestDepthValue);
                                                Vector3 wd2r = w2 + facadeCross * (bayStyle.columnDepth - largestDepthValue);
                                                Vector3 wd3r = w3 + facadeCross * (bayStyle.columnDepth - largestDepthValue);
                                                AddPlane(wd3r, wd1r, wd2r, wd0r, submeshTop, flippedTop, uvStart, uvEnd);
                                            }
                                        }
                                    }
                                }
                            }

                            ///ROWS
                            //Row Bottom
                            w0 = verts[1] + rowDepthVector;
                            w1 = verts[2] + rowDepthVector;
                            w2 = verts[5] + rowDepthVector;
                            w3 = verts[6] + rowDepthVector;
                            if (rowBottomHeight > 0)
                            {
                                Vector2 bottomRowUVStart = facadeUV + new Vector2(leftWidth, 0);
                                Vector2 bottomRowUVEnd = bottomRowUVStart + new Vector2(openingWidth, rowBottomHeight);
                                AddPlane(w0, w1, w2, w3, rowSubMesh, rowFlipped, bottomRowUVStart, bottomRowUVEnd);

                                //Row Sides
                                w0 = verts[1] + largestDepthVector;
                                w1 = verts[2] + largestDepthVector;
                                w2 = verts[5] + largestDepthVector;
                                w3 = verts[6] + largestDepthVector;
                                uvStart = facadeUV + new Vector2(0, 0);
                                uvEnd = uvStart + new Vector2(largestDepthValue, rowBottomHeight);
                                if (leftWidth > 0)//Left Side
                                {
                                    Vector3 sideDepthVectorA = facadeCross * (bayStyle.crossDepth - largestDepthValue);
                                    Vector3 sideDepthVectorB = facadeCross * (bayStyle.rowDepth - largestDepthValue);
                                    if(firstColumn)
                                    {
                                        sideDepthVectorA = facadeCross * -largestDepthValue;
                                    }
//                                    uvEnd.x = largestDepthValue;//Vector3.Distance(sideDepthVectorA, sideDepthVectorB);
//                                    uvEnd.y = Vector3.Distance(sideDepthVectorA,sideDepthVectorB);
                                    Vector3 wd0l = w0 + sideDepthVectorA;
                                    Vector3 wd1l = w2 + sideDepthVectorA;
                                    Vector3 wd2l = w0 + sideDepthVectorB;
                                    Vector3 wd3l = w2 + sideDepthVectorB;
                                    AddPlane(wd0l, wd2l, wd1l, wd3l, rowSubMesh, rowFlipped, uvStart, uvEnd);
                                }

//                                if (rightWidth > 0)//Right Side
//                                {
                                    Vector3 sideDepthVectorC = facadeCross * (bayStyle.crossDepth - largestDepthValue);
                                    Vector3 sideDepthVectorD = facadeCross * (bayStyle.rowDepth - largestDepthValue);
                                    if (lastColumn) sideDepthVectorC = facadeCross * -largestDepthValue;
                                    Vector3 wd0r = w1 + sideDepthVectorC;
                                    Vector3 wd1r = w3 + sideDepthVectorC;
                                    Vector3 wd2r = w1 + sideDepthVectorD;
                                    Vector3 wd3r = w3 + sideDepthVectorD;
                                    AddPlane(wd1r, wd3r, wd0r, wd2r, rowSubMesh, rowFlipped, uvStart, uvEnd);
//                                }
                            }

                            //Row Top
                            w0 = verts[9] + rowDepthVector;
                            w1 = verts[10] + rowDepthVector;
                            w2 = verts[13] + rowDepthVector;
                            w3 = verts[14] + rowDepthVector;

                            if (rowTopHeight > 0)
                            {
                                Vector2 topRowUVStart = facadeUV + new Vector2(leftWidth, rowBottomHeight + openingHeight);
                                Vector2 topRowUVEnd = topRowUVStart + new Vector2(openingWidth, rowTopHeight);
                                AddPlane(w0, w1, w2, w3, rowSubMesh, rowFlipped, topRowUVStart, topRowUVEnd);

                                //Row Sides
                                w0 = verts[9] + largestDepthVector;
                                w1 = verts[10] + largestDepthVector;
                                w2 = verts[13] + largestDepthVector;
                                w3 = verts[14] + largestDepthVector;
                                uvStart = facadeUV + new Vector2(0, rowBottomHeight+openingHeight);
                                uvEnd = uvStart + new Vector2(largestDepthValue, rowTopHeight);
                                if (leftWidth > 0)//Left Side
                                {
                                    Vector3 sideDepthVectorA = facadeCross * (bayStyle.crossDepth - largestDepthValue);
                                    Vector3 sideDepthVectorB = facadeCross * (bayStyle.rowDepth - largestDepthValue);
                                    if (firstColumn) sideDepthVectorA = facadeCross * -largestDepthValue;
                                    Vector3 wd0l = w0 + sideDepthVectorA;
                                    Vector3 wd1l = w2 + sideDepthVectorA;
                                    Vector3 wd2l = w0 + sideDepthVectorB;
                                    Vector3 wd3l = w2 + sideDepthVectorB;
                                    AddPlane(wd0l, wd2l, wd1l, wd3l, rowSubMesh, rowFlipped, uvStart, uvEnd);
                                }

//                                if (rightWidth > 0)//Right Side
//                                {
                                    Vector3 sideDepthVectorC = facadeCross * (bayStyle.crossDepth - largestDepthValue);
                                    Vector3 sideDepthVectorD = facadeCross * (bayStyle.rowDepth - largestDepthValue);
                                    if (lastColumn) sideDepthVectorC = facadeCross * -largestDepthValue;
                                    Vector3 wd0r = w1 + sideDepthVectorC;
                                    Vector3 wd1r = w3 + sideDepthVectorC;
                                    Vector3 wd2r = w1 + sideDepthVectorD;
                                    Vector3 wd3r = w3 + sideDepthVectorD;
                                    AddPlane(wd1r, wd3r, wd0r, wd2r, rowSubMesh, rowFlipped, uvStart, uvEnd);
//                                }
                            }

                            //Cross Left Bottom
                            Vector3 leftCrossDepthVector = (!firstColumn) ? crossDepthVector : Vector3.zero;
                            w0 = verts[0] + leftCrossDepthVector;
                            w1 = verts[1] + leftCrossDepthVector;
                            w2 = verts[4] + leftCrossDepthVector;
                            w3 = verts[5] + leftCrossDepthVector;
                            Vector2 crossLBUVStart = facadeUV + new Vector2(0, 0);
                            Vector2 crossLBUVEnd = crossLBUVStart + new Vector2(leftWidth, rowBottomHeight);
                            AddPlane(w0, w1, w2, w3, crossSubMesh, crossFlipped, crossLBUVStart, crossLBUVEnd);
                           
                            //Cross Left Top
                            if (rowTopHeight > 0)
                            {
                                w0 = verts[8] + leftCrossDepthVector;
                                w1 = verts[9] + leftCrossDepthVector;
                                w2 = verts[12] + leftCrossDepthVector;
                                w3 = verts[13] + leftCrossDepthVector;
                                Vector2 crossLTUVStart = facadeUV + new Vector2(0, rowBottomHeight + openingHeight);
                                Vector2 crossLTUVEnd = crossLTUVStart + new Vector2(leftWidth, rowTopHeight);
                                AddPlane(w0, w1, w2, w3, crossSubMesh, crossFlipped, crossLTUVStart, crossLTUVEnd);
                            }

                            if ((!nextBayIdentical || lastColumn) && rightWidth > 0)
                            {
                                if(lastColumn) crossDepthVector = Vector3.zero;//zero the ends of buildings
                                //Cross Right Bottom
                                w0 = verts[2] + crossDepthVector;
                                w1 = verts[3] + crossDepthVector;
                                w2 = verts[6] + crossDepthVector;
                                w3 = verts[7] + crossDepthVector;
                                Vector2 crossRBUVStart = facadeUV + new Vector2(leftWidth + openingWidth, 0);
                                Vector2 crossRBUVEnd = crossRBUVStart + new Vector2(rightWidth, rowBottomHeight);
                                AddPlane(w0, w1, w2, w3, crossSubMesh, crossFlipped, crossRBUVStart, crossRBUVEnd);

                                //Cross Right Top
                                if (rowTopHeight > 0)
                                {
                                    w0 = verts[10] + crossDepthVector;
                                    w1 = verts[11] + crossDepthVector;
                                    w2 = verts[14] + crossDepthVector;
                                    w3 = verts[15] + crossDepthVector;
                                    Vector2 crossRTUVStart = facadeUV + new Vector2(leftWidth + openingWidth, rowBottomHeight + openingHeight);
                                    Vector2 crossRTUVEnd = crossRTUVStart + new Vector2(rightWidth, rowTopHeight);
                                    AddPlane(w0, w1, w2, w3, crossSubMesh, crossFlipped, crossRTUVStart, crossRTUVEnd);
                                }
                            }

                            ///FACADE BOTTOMS
                            if (lastFacadeDesign != facadeDesign && rowBottomHeight > 0)
                            {
                                //Row Bottom
                                w0 = verts[1] + largestDepthVector;
                                w1 = verts[2] + largestDepthVector;

                                bottomDepth = bayStyle.rowDepth - largestDepthValue;
                                uvStart = facadeUV + new Vector2(leftWidth, 0);
                                uvEnd = uvStart + new Vector2(openingWidth, bottomDepth);

                                Vector3 bottomDepthVector = facadeCross * bottomDepth;
                                Vector3 wl0 = w0 + bottomDepthVector;
                                Vector3 wl1 = w1 + bottomDepthVector;
                                AddPlane(w0, w1, wl0, wl1, submeshBottom, flippedBottom, uvStart, uvEnd);

                                if(!firstColumn)
                                {
                                    //Left Cross Bottom
                                    w0 = verts[0] + largestDepthVector;
                                    w1 = verts[1] + largestDepthVector;

                                    bottomDepth = bayStyle.crossDepth - largestDepthValue;
                                    uvStart = facadeUV + new Vector2(0, 0);
                                    uvEnd = uvStart + new Vector2(leftWidth, bottomDepth);

                                    bottomDepthVector = facadeCross * bottomDepth;
                                    wl0 = w0 + bottomDepthVector;
                                    wl1 = w1 + bottomDepthVector;
                                    AddPlane(w0, w1, wl0, wl1, submeshBottom, flippedBottom, uvStart, uvEnd);
                                }

                                //Right Cross Bottom
                                if ((!nextBayIdentical && !lastColumn) && rightWidth > 0)
                                {
                                    w0 = verts[2] + largestDepthVector;
                                    w1 = verts[3] + largestDepthVector;

                                    bottomDepth = bayStyle.crossDepth - largestDepthValue;
                                    uvStart = facadeUV + new Vector2(leftWidth + openingWidth, 0);
                                    uvEnd = uvStart + new Vector2(rightWidth, bottomDepth);

                                    bottomDepthVector = facadeCross * bottomDepth;
                                    wl0 = w0 + bottomDepthVector;
                                    wl1 = w1 + bottomDepthVector;
                                    AddPlane(w0, w1, wl0, wl1, submeshBottom, flippedBottom, uvStart, uvEnd);
                                }
                            }


                            ///FACADE TOPS
                            if (nextFacadeDesign != facadeDesign && rowTopHeight > 0)
                            {
                                //Row Top
                                w0 = verts[13] + largestDepthVector;
                                w1 = verts[14] + largestDepthVector;

                                bottomDepth = bayStyle.rowDepth - largestDepthValue;
                                uvStart = facadeUV + new Vector2(leftWidth, 0);
                                uvEnd = uvStart + new Vector2(openingWidth, bottomDepth);

                                Vector3 bottomDepthVector = facadeCross * bottomDepth;
                                Vector3 wl0 = w0 + bottomDepthVector;
                                Vector3 wl1 = w1 + bottomDepthVector;
                                AddPlane(wl0, wl1, w0, w1, submeshBottom, flippedBottom, uvStart, uvEnd);

                                //Left Cross Top
                                if (!firstColumn)
                                {
                                    w0 = verts[12] + largestDepthVector;
                                    w1 = verts[13] + largestDepthVector;

                                    bottomDepth = bayStyle.crossDepth - largestDepthValue;
                                    uvStart = facadeUV + new Vector2(0, 0);
                                    uvEnd = uvStart + new Vector2(leftWidth,bottomDepth);

                                    bottomDepthVector = facadeCross * bottomDepth;
                                    wl0 = w0 + bottomDepthVector;
                                    wl1 = w1 + bottomDepthVector;
                                    AddPlane(wl0, wl1, w0, w1, submeshBottom, flippedBottom, uvStart, uvEnd);
                                }

                                //Right Cross Top
                                if ((!nextBayIdentical && !lastColumn) && rightWidth > 0)
                                {
                                    w0 = verts[14] + largestDepthVector;
                                    w1 = verts[15] + largestDepthVector;

                                    bottomDepth = bayStyle.crossDepth - largestDepthValue;
                                    uvStart = facadeUV + new Vector2(leftWidth+openingWidth, 0);
                                    uvEnd = uvStart + new Vector2(rightWidth, bottomDepth);

                                    bottomDepthVector = facadeCross * bottomDepth;
                                    wl0 = w0 + bottomDepthVector;
                                    wl1 = w1 + bottomDepthVector;
                                    AddPlane(wl0, wl1, w0, w1, submeshBottom, flippedBottom, uvStart, uvEnd);
                                }
                            }

                            ///BAY SIDES
                            // LEFT
                            if(!previousBayIdentical)
                            {
                                //Column
                                w1 = verts[4] + largestDepthVector;
                                w3 = verts[8] + largestDepthVector;
                                windowSideDepth = bayStyle.columnDepth - largestDepthValue;
                                uvStart = facadeUV + new Vector2(0, rowBottomHeight);
                                uvEnd = uvStart + new Vector2(windowSideDepth, openingHeight);
                                Vector3 depthVector = facadeCross * windowSideDepth;
                                Vector3 wr1 = w1 + depthVector;
                                Vector3 wr3 = w3 + depthVector;
                                AddPlane(wr3, w3, wr1, w1, columnSubMesh, columnFlipped, uvStart, uvEnd);

                                //Cross Bottom
                                w1 = verts[0] + largestDepthVector;
                                w3 = verts[4] + largestDepthVector;
                                windowSideDepth = bayStyle.crossDepth - largestDepthValue;
                                uvStart = facadeUV + new Vector2(0, 0);
                                uvEnd = uvStart + new Vector2(windowSideDepth, rowBottomHeight);
                                depthVector = facadeCross * windowSideDepth;
                                wr1 = w1 + depthVector;
                                wr3 = w3 + depthVector;
                                AddPlane(wr3, w3, wr1, w1, crossSubMesh, crossFlipped, uvStart, uvEnd);
                                //Cross Top
                                if (rowTopHeight > 0)
                                {
                                    w1 = verts[8] + largestDepthVector;
                                    w3 = verts[12] + largestDepthVector;
                                    windowSideDepth = bayStyle.crossDepth - largestDepthValue;
                                    uvStart = facadeUV + new Vector2(0, 0);
                                    uvEnd = uvStart + new Vector2(windowSideDepth, rowTopHeight);
                                    depthVector = facadeCross * windowSideDepth;
                                    wr1 = w1 + depthVector;
                                    wr3 = w3 + depthVector;
                                    AddPlane(wr3, w3, wr1, w1, crossSubMesh, crossFlipped, uvStart, uvEnd);
                                }
                            }

                            //RIGHT
                            if (!nextBayIdentical && !lastColumn)
                            {
                                //Column Sides
                                w1 = verts[7] + largestDepthVector;
                                w3 = verts[11] + largestDepthVector;
                                windowSideDepth = bayStyle.columnDepth - largestDepthValue;
                                uvStart = facadeUV + new Vector2(0, rowBottomHeight);
                                uvEnd = uvStart + new Vector2(windowSideDepth, openingHeight);
                                Vector3 depthVector = facadeCross * windowSideDepth;
                                Vector3 wr1 = w1 + depthVector;
                                Vector3 wr3 = w3 + depthVector;
                                AddPlane(w3, wr3, w1, wr1, columnSubMesh, columnFlipped, uvStart, uvEnd);

                                //Cross Bottom
                                w1 = verts[3] + largestDepthVector;
                                w3 = verts[7] + largestDepthVector;
                                windowSideDepth = bayStyle.crossDepth - largestDepthValue;
                                uvStart = facadeUV + new Vector2(0, 0);
                                uvEnd = uvStart + new Vector2(windowSideDepth, rowBottomHeight);
                                depthVector = facadeCross * windowSideDepth;
                                wr1 = w1 + depthVector;
                                wr3 = w3 + depthVector;
                                AddPlane(w3, wr3, w1, wr1, crossSubMesh, crossFlipped, uvStart, uvEnd);
                                //Cross Top
                                if (rowTopHeight > 0)
                                {
                                    w1 = verts[11] + largestDepthVector;
                                    w3 = verts[15] + largestDepthVector;
                                    windowSideDepth = bayStyle.crossDepth - largestDepthValue;
                                    uvStart = facadeUV + new Vector2(0, 0);
                                    uvEnd = uvStart + new Vector2(windowSideDepth, rowTopHeight);
                                    depthVector = facadeCross * windowSideDepth;
                                    wr1 = w1 + depthVector;
                                    wr3 = w3 + depthVector;
                                    AddPlane(w3, wr3, w1, wr1, crossSubMesh, crossFlipped, uvStart, uvEnd);
                                }
                            }
                        }
                    }
                    else
                    {
                        // windowless wall
                        Vector3 wallVector = (facadeDirection * (facadeWidth+largestDepthValue*2.0f));
                        Vector3 wallHeightVector = Vector3.up * floorHeight;
                        Vector3 w0 = facadeFloorBaseVector;
                        Vector3 w1 = facadeFloorBaseVector + wallVector;
                        Vector3 w2 = facadeFloorBaseVector + wallHeightVector;
                        Vector3 w3 = facadeFloorBaseVector + wallVector + wallHeightVector;
                        int wallSubmesh = facadeDesign.simpleBay.GetTexture(BuildrBay.TextureNames.WallTexture);
                        bool flipped = facadeDesign.simpleBay.IsFlipped(BuildrBay.TextureNames.WallTexture);
                        Vector2 wallUVStart = facadeUV;
                        Vector2 wallUVEnd = facadeUV + new Vector2(realFadeWidth, floorHeight);
                        AddPlane(w0, w1, w2, w3, wallSubmesh, flipped, wallUVStart, wallUVEnd);//face

                        if (nextFacadeDesign.hasWindows && !lastRow)
                        {
                            Vector3 wl2 = w2 - lastFacadeDirection*largestDepthValue;
                            Vector3 wl3 = w3 + nextFacadeDirection*largestDepthValue;
                            Vector2 uvEnd = new Vector2(facadeWidth, 1);
                            AddPlane(w3, wl3, w2, wl2, wallSubmesh, flipped, wallUVStart, uvEnd);//top
                        }
                    }
                }
            }
            //Bottom of the mesh - it's mostly to ensure the model can render certain shadows correctly
            if (data.drawUnderside)
            {
                Vector3 foundationDrop = Vector3.down * data.foundationHeight;
                var newEndVerts = new Vector3[numberOfVolumePoints];
                var newEndUVs = new Vector2[numberOfVolumePoints];
                for (int i = 0; i < numberOfVolumePoints; i++)
                {
                    newEndVerts[i] = plan.points[volume.points[i]].vector3 + foundationDrop;
                    newEndUVs[i] = Vector2.zero;
                }
                var tris = new List<int>(data.plan.GetTrianglesBySectorBase(v));
                tris.Reverse();
                int bottomSubMesh = facadeDesign.GetTexture(BuildrFacadeDesign.textureNames.columnTexture);
                mesh.AddData(newEndVerts, newEndUVs, tris.ToArray(), bottomSubMesh);
            }
        }
        data = null;
        mesh = null;
        textures = null;
    }
    public void UpdateRender(renderModes _mode)
    {
        if(data.plan==null)
            return;
        if (data.floorHeight == 0)
            return;
        if (fullMesh == null)
            fullMesh = new DynamicMeshGenericMultiMaterialMesh();

        fullMesh.Clear();
        fullMesh.subMeshCount = data.textures.Count;

        foreach(DynamicMeshGenericMultiMaterialMesh intMesh in interiorMeshes)
        {
            intMesh.Clear();
        }

        switch(_mode)
        {
                case renderModes.full:
                    if(data.oneDrawCall)
                    {
                        BuildrBuildingOneDrawCall.Build(fullMesh, data);
                    }
                    else
                    {
                        BuildrBuilding.Build(fullMesh, data);
                        BuildrRoof.Build(fullMesh, data);
                    }
                break;

                case renderModes.lowDetail:
                    BuildrBuildingLowDetail2.Build(fullMesh, data);
                    fullMesh.CollapseSubmeshes();
                break;

                case renderModes.box:
                    BuildrBuildingBox.Build(fullMesh, data);
                break;
        }

        fullMesh.Build(false);

        while (meshHolders.Count > 0)
        {
            GameObject destroyOld = meshHolders[0];
            meshHolders.RemoveAt(0);
            DestroyImmediate(destroyOld);
        }
        while (colliderHolders.Count > 0)
        {
            GameObject destroyOld = colliderHolders[0];
            colliderHolders.RemoveAt(0);
            DestroyImmediate(destroyOld);
        }

        int numberOfMeshes = fullMesh.meshCount;
        for(int i = 0; i < numberOfMeshes; i++)
        {
            GameObject newMeshHolder = new GameObject("model " + (i + 1));
            newMeshHolder.transform.parent = transform;
            newMeshHolder.transform.localPosition = Vector3.zero;
            meshFilt = newMeshHolder.AddComponent<MeshFilter>();
            meshRend = newMeshHolder.AddComponent<MeshRenderer>();
            meshFilt.mesh = fullMesh[i].mesh;
            meshHolders.Add(newMeshHolder);
        }

        while (interiorMeshHolders.Count > 0)
        {
            GameObject destroyOld = interiorMeshHolders[0];
            interiorMeshHolders.RemoveAt(0);
            DestroyImmediate(destroyOld);
        }

        switch (_mode)
        {
            case renderModes.full:
                renderMode = renderModes.full;
                UpdateInteriors();
                UpdateTextures();
                UpdateDetails();
                UpdateBayModels();
                break;

            case renderModes.lowDetail:
                renderMode = renderModes.lowDetail;
                meshRend.sharedMaterials = new Material[0];
                lowDetailMat.mainTexture = data.LODTextureAtlas;
                meshRend.sharedMaterial = lowDetailMat;
                UpdateDetails();
                break;

            case renderModes.box:
                renderMode = renderModes.box;
                meshRend.sharedMaterials = new Material[0];
                lowDetailMat.mainTexture = data.textures[0].texture;
                meshRend.sharedMaterial = lowDetailMat;
                UpdateDetails();
                break;
        }

        #if UNITY_EDITOR
        EditorUtility.UnloadUnusedAssets();
        #endif
    }
Beispiel #40
0
 public static void Build(DynamicMeshGenericMultiMaterialMesh _mesh, BuildrData _data)
 {
     Build(_mesh, _data, false);
 }
Beispiel #41
0
    public void UpdateRender()
    {
        if (track.numberOfCurves == 0)
        {
            return;
        }

        track.RecalculateCurves();
        float trackMeshRes = track.meshResolution;

        float bumperDistanceA = 0;
        float bumperDistanceB = 0;


        int   numberOfCurves = track.numberOfCurves;
        bool  renderTrack    = track.render;
        float UVOffset       = 0;
        int   polyCount      = 0;

        for (int i = 0; i < numberOfCurves; i++)
        {
            TrackBuildRPoint curve = track[i];

            DynamicMeshGenericMultiMaterialMesh dynamicTrackMesh    = curve.dynamicTrackMesh;
            DynamicMeshGenericMultiMaterialMesh dynamicBoundaryMesh = curve.dynamicBoundaryMesh;
            DynamicMeshGenericMultiMaterialMesh dynamicOffroadMesh  = curve.dynamicOffroadMesh;
            DynamicMeshGenericMultiMaterialMesh dynamicBumperMesh   = curve.dynamicBumperMesh;
            DynamicMeshGenericMultiMaterialMesh dynamicColliderMesh = curve.dynamicColliderMesh;
            DynamicMeshGenericMultiMaterialMesh dynamicBottomMesh   = curve.dynamicBottomMesh;

            if (!curve.render || !renderTrack)
            {
                dynamicTrackMesh.Clear();
                dynamicBoundaryMesh.Clear();
                dynamicColliderMesh.Clear();
                dynamicOffroadMesh.Clear();
                dynamicBumperMesh.Clear();
                dynamicBottomMesh.Clear();
            }

            if (curve.shouldReRender && curve.render && renderTrack)
            {
                dynamicTrackMesh.Clear();
                dynamicTrackMesh.subMeshCount = 1;
                dynamicBoundaryMesh.Clear();
                dynamicBoundaryMesh.subMeshCount = 1;
                dynamicColliderMesh.Clear();
                dynamicColliderMesh.subMeshCount = 1;
                dynamicOffroadMesh.Clear();
                dynamicOffroadMesh.subMeshCount = 1;
                dynamicBumperMesh.Clear();
                dynamicBumperMesh.subMeshCount = 1;
                dynamicBottomMesh.Clear();
                dynamicBottomMesh.subMeshCount = 1;

                dynamicTrackMesh.name    = "curve " + i + " track mesh";
                dynamicBoundaryMesh.name = "curve " + i + " boundary mesh";
                dynamicColliderMesh.name = "curve " + i + " trackCollider mesh";
                dynamicOffroadMesh.name  = "curve " + i + " offroad mesh";
                dynamicBumperMesh.name   = "curve " + i + " bumper mesh";
                dynamicBottomMesh.name   = "curve " + i + " bottom mesh";

                bool trackTextureFlip    = (track.numberOfTextures > 0) ? track.Texture(curve.trackTextureStyleIndex).flipped : false;
                bool boundaryTextureFlip = (track.numberOfTextures > 0) ? track.Texture(curve.boundaryTextureStyleIndex).flipped : false;
                bool bumperTextureFlip   = (track.numberOfTextures > 0) ? track.Texture(curve.bumperTextureStyleIndex).flipped : false;
                bool bottomTextureFlip   = (track.numberOfTextures > 0) ? track.Texture(curve.bottomTextureStyleIndex).flipped : false;

                int   storedPointSize = curve.storedPointSize;
                float curveLength     = curve.arcLength;
                //Store these points so we can use previous values when Bezier clips itself
                Vector3 leftPointA  = curve.sampledLeftBoundaryPoints[0];
                Vector3 rightPointA = curve.sampledRightBoundaryPoints[0];
                Vector3 leftPointB  = curve.sampledLeftBoundaryPoints[0];
                Vector3 rightPointB = curve.sampledRightBoundaryPoints[0];
                for (int p = 0; p < storedPointSize - 1; p++)
                {
                    float   tA           = curve.normalisedT[p];
                    float   tB           = curve.normalisedT[p + 1];
                    int     sampleIndexA = p;
                    int     sampleIndexB = sampleIndexA + 1;
                    Vector3 pointA       = curve.sampledPoints[sampleIndexA];
                    Vector3 pointB       = curve.sampledPoints[sampleIndexB];
                    float   trackWidthA  = curve.sampledWidths[sampleIndexA] * 0.5f;
                    float   trackWidthB  = curve.sampledWidths[sampleIndexB] * 0.5f;
                    float   trackCrownA  = curve.sampledCrowns[sampleIndexA];
                    float   trackCrownB  = curve.sampledCrowns[sampleIndexB];
                    Vector3 trackUpA     = curve.sampledTrackUps[sampleIndexA];
                    Vector3 trackUpB     = curve.sampledTrackUps[sampleIndexB];
                    Vector3 trackCrossA  = curve.sampledTrackCrosses[sampleIndexA];
                    Vector3 trackCrossB  = curve.sampledTrackCrosses[sampleIndexB];
                    float   trackAngle   = curve.sampledAngles[sampleIndexA];

                    if (trackUpA == Vector3.zero || trackUpB == Vector3.zero)
                    {
                        return;
                    }

                    //TrackBuildRTexture texture = track.Texture(curve.trackTextureStyleIndex) ;// track.trackTexture;
                    int       pointANumber     = Mathf.Max(Mathf.CeilToInt(trackWidthA / trackMeshRes / 2) * 2, 2); //number of verts along line A
                    int       pointBNumber     = Mathf.Max(Mathf.CeilToInt(trackWidthB / trackMeshRes / 2) * 2, 2); //number of verts along line B
                    int       numberOfNewVerts = pointANumber + pointBNumber;
                    Vector3[] uncrownedVerts   = new Vector3[numberOfNewVerts];
                    if (curve.clipArrayLeft[sampleIndexA])
                    {
                        leftPointA = (pointA + (trackCrossA * -trackWidthA));
                    }
                    if (curve.clipArrayRight[sampleIndexA])
                    {
                        rightPointA = (pointA + (trackCrossA * trackWidthA));
                    }
                    float curveLengthA = (curveLength * tA) / trackWidthA + UVOffset;
                    float curveLengthB = (curveLength * tB) / trackWidthB + UVOffset;
                    float lerpASize    = 1.0f / (pointANumber - 1);

                    //track vertex/uv data for point nextNormIndex
                    Vector3[] newAPoints     = new Vector3[pointANumber];
                    Vector3[] newTrackPoints = new Vector3[pointANumber + pointBNumber];
                    Vector2[] newTrackUVs    = new Vector2[pointANumber + pointBNumber];
                    for (int pa = 0; pa < pointANumber; pa++)
                    {
                        float   lerpValue     = lerpASize * pa;
                        Vector3 crownVector   = Quaternion.LookRotation(trackUpA) * new Vector3(0, 0, Mathf.Sin(lerpValue * Mathf.PI) * trackCrownA);
                        Vector3 uncrownedVert = Vector3.Lerp(leftPointA, rightPointA, lerpValue);
                        uncrownedVerts[pa] = uncrownedVert;
                        Vector3 newVert = uncrownedVert + crownVector;
                        newAPoints[pa]     = newVert;
                        newTrackPoints[pa] = newVert;
                        Vector2 newUV = (!trackTextureFlip) ? new Vector2(lerpValue, curveLengthA) : new Vector2(curveLengthA, lerpValue);
                        newTrackUVs[pa] = newUV;
                    }

                    //track vertex/uv data for point prevNormIndex
                    if (curve.clipArrayLeft[sampleIndexB])
                    {
                        leftPointB = (pointB + (trackCrossB * -trackWidthB));
                    }
                    if (curve.clipArrayRight[sampleIndexB])
                    {
                        rightPointB = (pointB + (trackCrossB * trackWidthB));
                    }
                    float     lerpBSize  = 1.0f / (pointBNumber - 1);
                    Vector3[] newBPoints = new Vector3[pointBNumber];
                    for (int pb = 0; pb < pointBNumber; pb++)
                    {
                        float   lerpValue     = lerpBSize * pb;
                        Vector3 crownVector   = Quaternion.LookRotation(trackUpB) * new Vector3(0, 0, Mathf.Sin(lerpValue * Mathf.PI) * trackCrownB);
                        Vector3 uncrownedVert = Vector3.Lerp(leftPointB, rightPointB, lerpValue);
                        uncrownedVerts[pb + pointANumber] = uncrownedVert;
                        Vector3 newVert = uncrownedVert + crownVector;
                        newBPoints[pb] = newVert;
                        newTrackPoints[pb + pointANumber] = newVert;
                        Vector2 newUV = (!trackTextureFlip) ? new Vector2(lerpValue, curveLengthB) : new Vector2(curveLengthB, lerpValue);
                        newTrackUVs[pb + pointANumber] = newUV;
                    }
                    int   baseTriPointA     = 0;
                    int   baseTriPointB     = pointANumber;
                    int   triPointA         = baseTriPointA;
                    int   triPointB         = baseTriPointB;
                    int   newTriPointCountA = 1;
                    int   newTriPointCountB = 1;
                    int[] newTrackTris      = new int[(numberOfNewVerts - 2) * 3];
                    for (int v = 0; v < numberOfNewVerts - 2; v++)
                    {
                        int newTriPointA = baseTriPointA + newTriPointCountA;
                        int newTriPointB = baseTriPointB + newTriPointCountB;

                        float newTriPointADist, newTriPointBDist;
                        if (newTriPointA >= baseTriPointA + pointANumber)
                        {
                            newTriPointADist = float.PositiveInfinity;
                        }
                        else
                        {
                            newTriPointADist = Vector3.SqrMagnitude(uncrownedVerts[newTriPointA] - uncrownedVerts[baseTriPointA]);
                        }

                        if (newTriPointB >= baseTriPointB + pointBNumber)
                        {
                            newTriPointBDist = float.PositiveInfinity;
                        }
                        else
                        {
                            newTriPointBDist = Vector3.SqrMagnitude(uncrownedVerts[newTriPointB] - uncrownedVerts[baseTriPointB]);
                        }

                        if (newTriPointADist < newTriPointBDist)
                        {
                            newTrackTris[v * 3]     = triPointA;
                            newTrackTris[v * 3 + 1] = triPointB;
                            newTrackTris[v * 3 + 2] = newTriPointA;
                            triPointA = newTriPointA;
                            newTriPointCountA++;
                        }
                        else
                        {
                            newTrackTris[v * 3]     = triPointA;
                            newTrackTris[v * 3 + 1] = triPointB;
                            newTrackTris[v * 3 + 2] = newTriPointB;
                            triPointB = newTriPointB;
                            newTriPointCountB++;
                        }
                    }
                    dynamicTrackMesh.AddData(newTrackPoints, newTrackUVs, newTrackTris, 0);
                    dynamicColliderMesh.AddData(newTrackPoints, newTrackUVs, newTrackTris, 0);

                    //Boundary
                    float trackBoundaryWallHeight = curve.boundaryHeight;// track.boundaryHeight;

                    Vector3 leftBoundaryPointA, leftBoundaryPointB, rightBoundaryPointA, rightBoundaryPointB;
                    if (track.disconnectBoundary)
                    {
                        leftBoundaryPointA  = curve.sampledLeftBoundaryPoints[sampleIndexA];
                        leftBoundaryPointB  = curve.sampledLeftBoundaryPoints[sampleIndexB];
                        rightBoundaryPointA = curve.sampledRightBoundaryPoints[sampleIndexA];
                        rightBoundaryPointB = curve.sampledRightBoundaryPoints[sampleIndexB];
                    }
                    else
                    {
                        leftBoundaryPointA  = leftPointA;
                        leftBoundaryPointB  = leftPointB;
                        rightBoundaryPointA = rightPointA;
                        rightBoundaryPointB = rightPointB;
                    }

                    Vector3[] newWallVerts;
                    Vector2[] newWallUVs;
                    int[]     newWallTris;

                    //Boundary Render Mesh
                    if (curve.renderBounds)
                    {
                        //LEFT
                        newWallVerts = new[] { leftBoundaryPointA, leftBoundaryPointB, leftBoundaryPointA + trackUpA * trackBoundaryWallHeight, leftBoundaryPointB + trackUpB * trackBoundaryWallHeight };

                        if (!boundaryTextureFlip)
                        {
                            newWallUVs = new[] { new Vector2(curveLengthA, 0), new Vector2(curveLengthB, 0), new Vector2(curveLengthA, 1), new Vector2(curveLengthB, 1), }
                        }
                        ;
                        else
                        {
                            newWallUVs = new[] { new Vector2(1, curveLengthA), new Vector2(1, curveLengthB), new Vector2(0, curveLengthA), new Vector2(0, curveLengthB), }
                        };
                        newWallTris = new[] { 1, 0, 2, 1, 2, 3 };
                        //                    newWallTris = (boundaryTextureFlip) ? (new[] { 1, 0, 2, 1, 2, 3 }) : (new[] { 0,2,1,2,3,1 });
                        //                    newWallTris = (!track.renderBoundaryWallReverse) ? new[] { 1, 0, 2, 1, 2, 3 } : new[] { 1, 0, 2, 1, 2, 3, 0, 1, 2, 2, 1, 3 };
                        dynamicBoundaryMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0);
                        if (track.renderBoundaryWallReverse)
                        {
                            newWallTris = new[] { 0, 1, 2, 2, 1, 3 };
                            //                        newWallTris = (boundaryTextureFlip) ? (new[] { 0, 1, 2, 2, 1, 3 }) : (new[] { 0, 2, 1, 2, 3, 1 });
                            dynamicBoundaryMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0);
                        }

                        //RIGHT
                        newWallVerts = (new[] { rightBoundaryPointA, rightBoundaryPointB, rightBoundaryPointA + trackUpA * trackBoundaryWallHeight, rightBoundaryPointB + trackUpB * trackBoundaryWallHeight });
                        //newWallUVs = new[] { new Vector2(curveLengthA, 0), new Vector2(curveLengthB, 0), new Vector2(curveLengthA, 1), new Vector2(curveLengthB, 1), };
                        if (!boundaryTextureFlip)
                        {
                            newWallUVs = new[] { new Vector2(curveLengthA, 0), new Vector2(curveLengthB, 0), new Vector2(curveLengthA, 1), new Vector2(curveLengthB, 1), }
                        }
                        ;
                        else
                        {
                            newWallUVs = new[] { new Vector2(1, curveLengthA), new Vector2(1, curveLengthB), new Vector2(0, curveLengthA), new Vector2(0, curveLengthB), }
                        };

                        newWallTris = new[] { 0, 1, 2, 2, 1, 3 };
                        //newWallTris = (!track.renderBoundaryWallReverse) ? new[] { 0, 1, 2, 2, 1, 3 } : new[] { 1, 0, 2, 1, 2, 3, 0, 1, 2, 2, 1, 3 };
                        dynamicBoundaryMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0);
                        if (track.renderBoundaryWallReverse)
                        {
                            newWallTris = new[] { 1, 0, 2, 1, 2, 3 };
                            dynamicBoundaryMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0);
                        }
                    }

                    if (curve.trackCollider)
                    {
                        //COLLIDER walls for on track border
                        float trackColliderWallHeight = track.trackColliderWallHeight;
                        if (curve.colliderSides)
                        {
                            newWallVerts = (new[] { leftBoundaryPointA, leftBoundaryPointB, leftBoundaryPointA + trackUpA * trackColliderWallHeight, leftBoundaryPointB + trackUpB * trackColliderWallHeight });
                            newWallUVs   = (new[] { Vector2.zero, Vector2.zero, Vector2.zero, Vector2.zero });
                            newWallTris  = (new[] { 1, 0, 2, 1, 2, 3 });
                            dynamicColliderMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0);
                            newWallVerts = (new[] { rightBoundaryPointA, rightBoundaryPointB, rightBoundaryPointA + trackUpA * trackColliderWallHeight, rightBoundaryPointB + trackUpB * trackColliderWallHeight });
                            newWallUVs   = (new[] { Vector2.zero, Vector2.zero, Vector2.zero, Vector2.zero });
                            newWallTris  = (new[] { 0, 1, 2, 2, 1, 3 });
                            dynamicColliderMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0);
                        }

                        //offroad bits
                        if (track.disconnectBoundary)
                        {
                            Vector2 offroadTextureSize = Vector2.one;
                            if (track.numberOfTextures > 0)
                            {
                                offroadTextureSize = track.Texture(curve.offroadTextureStyleIndex).textureUnitSize;// track.offroadTexture.textureUnitSize;
                            }
                            newWallVerts = (new[] { leftPointA, leftPointB, leftBoundaryPointA, leftBoundaryPointB });
                            newWallUVs   = (new[] { new Vector2(leftPointA.x / offroadTextureSize.x, leftPointA.z / offroadTextureSize.y), new Vector2(leftPointB.x / offroadTextureSize.x, leftPointB.z / offroadTextureSize.y), new Vector2(leftBoundaryPointA.x / offroadTextureSize.x, leftBoundaryPointA.z / offroadTextureSize.y), new Vector2(leftBoundaryPointB.x / offroadTextureSize.x, leftBoundaryPointB.z / offroadTextureSize.y) });
                            newWallTris  = (new[] { 1, 0, 2, 1, 2, 3 });
                            dynamicOffroadMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0);

                            newWallVerts = (new[] { rightPointA, rightPointB, rightBoundaryPointA, rightBoundaryPointB });
                            newWallUVs   = (new[] { new Vector2(rightPointA.x / offroadTextureSize.x, rightPointA.z / offroadTextureSize.y), new Vector2(rightPointB.x / offroadTextureSize.x, rightPointB.z / offroadTextureSize.y), new Vector2(rightBoundaryPointA.x / offroadTextureSize.x, rightBoundaryPointA.z / offroadTextureSize.y), new Vector2(rightBoundaryPointB.x / offroadTextureSize.x, rightBoundaryPointB.z / offroadTextureSize.y) });
                            newWallTris  = (new[] { 0, 1, 2, 2, 1, 3 });
                            dynamicOffroadMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0);

                            newWallVerts = (new[] { leftPointA, leftPointB, leftBoundaryPointA, leftBoundaryPointB });
                            newWallUVs   = (new[] { Vector2.zero, Vector2.zero, Vector2.zero, Vector2.zero });
                            newWallTris  = (new[] { 1, 0, 2, 1, 2, 3 });
                            dynamicColliderMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0);
                            newWallVerts = (new[] { rightPointA, rightPointB, rightBoundaryPointA, rightBoundaryPointB });
                            newWallUVs   = (new[] { Vector2.zero, Vector2.zero, Vector2.zero, Vector2.zero });
                            newWallTris  = (new[] { 0, 1, 2, 2, 1, 3 });
                            dynamicColliderMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0);
                        }

                        if (track.includeColliderRoof)
                        {
                            newWallVerts = (new[] { leftBoundaryPointA + trackUpA * trackColliderWallHeight, leftBoundaryPointB + trackUpB * trackColliderWallHeight, rightBoundaryPointA + trackUpA * trackColliderWallHeight, rightBoundaryPointB + trackUpB * trackColliderWallHeight });
                            newWallUVs   = (new[] { Vector2.zero, Vector2.zero, Vector2.zero, Vector2.zero });
                            newWallTris  = (new[] { 1, 0, 2, 1, 2, 3 });
                            dynamicColliderMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0);
                        }
                    }

                    if ((track.trackBumpers && curve.generateBumpers) || curve.generateBumpers)
                    {
                        float   bumperWidth          = track.bumperWidth;
                        float   bumperHeight         = track.bumperHeight;
                        Vector3 bumperRaisedA        = trackUpA * bumperHeight;
                        Vector3 bumperRaisedB        = trackUpB * bumperHeight;
                        float   trackAngleThreashold = track.bumperAngleThresold;

                        //left bumpers
                        if (trackAngle >= trackAngleThreashold)
                        {
                            Vector3 offroadEdgeDirectionA = (leftBoundaryPointA - leftPointA).normalized;
                            Vector3 trackEdgeDirectionA   = (newAPoints[1] - newAPoints[0]).normalized;
                            Vector3 bumperDirectionA      = (Vector3.Project(offroadEdgeDirectionA, trackUpA) - trackEdgeDirectionA).normalized;
                            Vector3 offroadEdgeDirectionB = (leftBoundaryPointB - leftPointB).normalized;
                            Vector3 trackEdgeDirectionB   = (newBPoints[1] - newBPoints[0]).normalized;
                            Vector3 bumperDirectionB      = (Vector3.Project(offroadEdgeDirectionB, trackUpB) - trackEdgeDirectionB).normalized;
                            float   trackEdgeA            = Vector3.Distance(pointA, leftPointA);
                            float   offroadEdgeA          = Vector3.Distance(pointA, leftBoundaryPointA);
                            bool    offroadBumper         = (trackEdgeA < (offroadEdgeA - bumperWidth));
                            Vector3 bumperLeft0           = (offroadBumper ? leftPointA + bumperDirectionA * bumperWidth : leftBoundaryPointA) + bumperRaisedA;
                            Vector3 bumperLeft1           = (offroadBumper ? leftPointA : bumperLeft0 - (bumperDirectionA * bumperWidth) - bumperRaisedB);//bumperLeft0 + (trackEdgeDirectionA * bumperWidth)) - bumperRaisedB;

                            Vector3 bumperLeft2 = (offroadBumper ? leftPointB + bumperDirectionB * bumperWidth : leftBoundaryPointB) + bumperRaisedB;
                            Vector3 bumperLeft3 = (offroadBumper ? leftPointB : bumperLeft2 - (bumperDirectionB * bumperWidth) - bumperRaisedB);

                            float bumperSegmentDistanceA = Vector3.Distance(bumperLeft0, bumperLeft2);
                            float uvStartA, uvEndA;
                            if (track.numberOfTextures > 0)
                            {
                                uvStartA = bumperDistanceA / track.Texture(curve.bumperTextureStyleIndex).textureUnitSize.y;                            // track.bumperTexture.textureUnitSize.y;
                                uvEndA   = (bumperDistanceA + bumperSegmentDistanceA) / track.Texture(curve.bumperTextureStyleIndex).textureUnitSize.y; // track.bumperTexture.textureUnitSize.y;
                            }
                            else
                            {
                                uvStartA = bumperDistanceA;                            // track.bumperTexture.textureUnitSize.y;
                                uvEndA   = (bumperDistanceA + bumperSegmentDistanceA); // track.bumperTexture.textureUnitSize.y;
                            }
                            newWallVerts = (new[] { bumperLeft0, bumperLeft1, bumperLeft2, bumperLeft3 });
                            if (!bumperTextureFlip)
                            {
                                newWallUVs = (new[] { new Vector2(uvStartA, 1), new Vector2(uvStartA, 0), new Vector2(uvEndA, 1), new Vector2(uvEndA, 0) });
                            }
                            else
                            {
                                newWallUVs = (new[] { new Vector2(1, uvStartA), new Vector2(0, uvStartA), new Vector2(1, uvEndA), new Vector2(0, uvEndA) });
                            }
                            newWallTris = (new[] { 1, 0, 2, 1, 2, 3 });
                            dynamicBumperMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0);
                            bumperDistanceA += bumperSegmentDistanceA;

                            newWallVerts = (new[] { bumperLeft0, bumperLeft1, bumperLeft2, bumperLeft3 });
                            newWallUVs   = (new[] { Vector2.zero, Vector2.zero, Vector2.zero, Vector2.zero });
                            newWallTris  = (new[] { 1, 0, 2, 1, 2, 3 });
                            dynamicColliderMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0);
                        }

                        //Right bumpers
                        if (trackAngle < -trackAngleThreashold)
                        {
                            Vector3 trackEdgeDirectionA = (newAPoints[pointANumber - 2] - newAPoints[pointANumber - 1]).normalized;
                            Vector3 trackEdgeDirectionB = (newBPoints[pointBNumber - 2] - newBPoints[pointBNumber - 1]).normalized;

                            Vector3 bumperRight0 = ((Vector3.Distance(pointA, rightPointA) < (Vector3.Distance(pointA, rightBoundaryPointA) - bumperWidth)) ? rightPointA : rightBoundaryPointA) + bumperRaisedA;
                            Vector3 bumperRight1 = bumperRight0 + (trackEdgeDirectionA * bumperWidth);

                            Vector3 bumperRight2 = ((Vector3.Distance(pointB, rightPointB) < (Vector3.Distance(pointB, rightBoundaryPointB) - bumperWidth)) ? rightPointB : rightBoundaryPointB) + bumperRaisedB;
                            Vector3 bumperRight3 = bumperRight2 + (trackEdgeDirectionB * bumperWidth);

                            float bumperSegmentDistanceB = Vector3.Distance(bumperRight0, bumperRight2);
                            //float bumperSegmentDistanceA = Vector3.Distance(bumperLeft0, bumperLeft2);

                            float uvStartB, uvEndB;
                            if (track.numberOfTextures > 0)
                            {
                                uvStartB = bumperDistanceB / track.Texture(curve.bumperTextureStyleIndex).textureUnitSize.y;                            // track.bumperTexture.textureUnitSize.y;
                                uvEndB   = (bumperDistanceB + bumperSegmentDistanceB) / track.Texture(curve.bumperTextureStyleIndex).textureUnitSize.y; // track.bumperTexture.textureUnitSize.y;
                            }
                            else
                            {
                                uvStartB = bumperDistanceB;
                                uvEndB   = (bumperDistanceB + bumperSegmentDistanceB);
                            }
                            newWallVerts = (new[] { bumperRight0, bumperRight1, bumperRight2, bumperRight3 });
                            if (!bumperTextureFlip)
                            {
                                newWallUVs = (new[] { new Vector2(uvStartB, 1), new Vector2(uvStartB, 0), new Vector2(uvEndB, 1), new Vector2(uvEndB, 0) });
                            }
                            else
                            {
                                newWallUVs = (new[] { new Vector2(1, uvStartB), new Vector2(0, uvStartB), new Vector2(1, uvEndB), new Vector2(0, uvEndB) });
                            }
//                            newWallTris = (new[] { 1, 0, 2, 1, 2, 3 });
                            newWallTris = (new[] { 0, 1, 2, 1, 3, 2 });
                            dynamicBumperMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0);
                            bumperDistanceB += bumperSegmentDistanceB;
                        }
                    }


                    //Track Bottom Mesh
                    if (curve.extrudeTrack || curve.extrudeTrackBottom)
                    {
                        float   extrusionLength = curve.extrudeLength;
                        Vector3 extrusionA      = -trackUpA * extrusionLength;
                        Vector3 extrusionB      = -trackUpB * extrusionLength;
                        Vector3 pl0             = leftBoundaryPointA;
                        Vector3 pl1             = leftBoundaryPointB;
                        Vector3 pl2             = leftBoundaryPointA + extrusionA;
                        Vector3 pl3             = leftBoundaryPointB + extrusionB;
                        Vector3 pr0             = rightBoundaryPointA;
                        Vector3 pr1             = rightBoundaryPointB;
                        Vector3 pr2             = rightBoundaryPointA + extrusionA;
                        Vector3 pr3             = rightBoundaryPointB + extrusionB;

                        float   bevelLerp = 0.5f - curve.extrudeBevel * 0.3333f;
                        Vector3 bevelOutA = trackCrossA.normalized * (trackWidthA * 0.5f);
                        Vector3 bevelOutB = trackCrossB.normalized * (trackWidthB * 0.5f);
                        Vector3 pl2b      = Vector3.Lerp(pl2 - bevelOutA, pr2 + bevelOutA, bevelLerp);
                        Vector3 pl3b      = Vector3.Lerp(pl3 - bevelOutB, pr3 + bevelOutB, bevelLerp);
                        Vector3 pr2b      = Vector3.Lerp(pr2 + bevelOutA, pl2 - bevelOutA, bevelLerp);
                        Vector3 pr3b      = Vector3.Lerp(pr3 + bevelOutB, pl3 - bevelOutB, bevelLerp);

                        if (curve.extrudeTrack)
                        {
                            //LEFT

                            newWallVerts = new[] { pl0, pl1, pl2b, pl3b };

                            if (!bottomTextureFlip)
                            {
                                newWallUVs = new[] { new Vector2(curveLengthA, 0), new Vector2(curveLengthB, 0), new Vector2(curveLengthA, 1), new Vector2(curveLengthB, 1), }
                            }
                            ;
                            else
                            {
                                newWallUVs = new[] { new Vector2(1, curveLengthA), new Vector2(1, curveLengthB), new Vector2(0, curveLengthA), new Vector2(0, curveLengthB), }
                            };
                            newWallTris = new[] { 1, 0, 2, 1, 2, 3 };
                            dynamicBottomMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0);
                            if (curve.trackCollider)
                            {
                                dynamicColliderMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0);
                            }

                            //RIGHT
                            newWallVerts = (new[] { pr0, pr1, pr2b, pr3b });
                            if (!bottomTextureFlip)
                            {
                                newWallUVs = new[] { new Vector2(curveLengthA, 0), new Vector2(curveLengthB, 0), new Vector2(curveLengthA, 1), new Vector2(curveLengthB, 1), }
                            }
                            ;
                            else
                            {
                                newWallUVs = new[] { new Vector2(1, curveLengthA), new Vector2(1, curveLengthB), new Vector2(0, curveLengthA), new Vector2(0, curveLengthB), }
                            };

                            newWallTris = new[] { 0, 1, 2, 2, 1, 3 };
                            dynamicBottomMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0);
                            if (curve.trackCollider)
                            {
                                dynamicColliderMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0);
                            }

                            if (curve.extrudeCurveEnd)
                            {
                                //Ends
                                if (p == 0)
                                {
                                    newWallVerts = (new[] { pl0, pl2b, pr0, pr2b });
                                    if (!bottomTextureFlip)
                                    {
                                        newWallUVs = new[] { new Vector2(curveLengthA, 0), new Vector2(curveLengthB, 0), new Vector2(curveLengthA, 1), new Vector2(curveLengthB, 1), }
                                    }
                                    ;
                                    else
                                    {
                                        newWallUVs = new[] { new Vector2(1, curveLengthA), new Vector2(1, curveLengthB), new Vector2(0, curveLengthA), new Vector2(0, curveLengthB), }
                                    };
                                    newWallTris = new[] { 1, 0, 2, 1, 2, 3 };
                                    dynamicBottomMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0);
                                    if (curve.trackCollider)
                                    {
                                        dynamicColliderMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0);
                                    }
                                }
                                if (p == storedPointSize - 2)
                                {
                                    newWallVerts = (new[] { pl1, pl3b, pr1, pr3b });
                                    if (!bottomTextureFlip)
                                    {
                                        newWallUVs = new[] { new Vector2(curveLengthA, 0), new Vector2(curveLengthB, 0), new Vector2(curveLengthA, 1), new Vector2(curveLengthB, 1), }
                                    }
                                    ;
                                    else
                                    {
                                        newWallUVs = new[] { new Vector2(1, curveLengthA), new Vector2(1, curveLengthB), new Vector2(0, curveLengthA), new Vector2(0, curveLengthB), }
                                    };
                                    newWallTris = new[] { 0, 1, 2, 2, 1, 3 };
                                    dynamicBottomMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0);
                                    if (curve.trackCollider)
                                    {
                                        dynamicColliderMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0);
                                    }
                                }
                            }
                        }

                        if (curve.extrudeTrackBottom)
                        {
                            if (!curve.extrudeTrack)
                            {
                                newWallVerts = new[] { pl0, pl1, pr0, pr1 }
                            }
                            ;
                            else
                            {
                                newWallVerts = new[] { pl2b, pl3b, pr2b, pr3b }
                            };

                            if (!bottomTextureFlip)
                            {
                                newWallUVs = new[] { new Vector2(curveLengthA, 0), new Vector2(curveLengthB, 0), new Vector2(curveLengthA, 1), new Vector2(curveLengthB, 1), }
                            }
                            ;
                            else
                            {
                                newWallUVs = new[] { new Vector2(1, curveLengthA), new Vector2(1, curveLengthB), new Vector2(0, curveLengthA), new Vector2(0, curveLengthB), }
                            };

                            newWallTris = new[] { 1, 0, 2, 1, 2, 3 };
                            dynamicBottomMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0);
                            if (curve.trackCollider)
                            {
                                dynamicColliderMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0);
                            }
                        }
                    }

                    if (p == storedPointSize - 2)
                    {
                        UVOffset = curveLengthB;
                    }
                }

                if (curve.holder != null)
                {
                    DestroyImmediate(curve.holder);
                }

                GameObject newCurveMeshHolder = new GameObject("curve " + (i + 1));
                newCurveMeshHolder.transform.parent        = transform;
                newCurveMeshHolder.transform.localPosition = Vector3.zero;
                curve.holder = newCurveMeshHolder;
                int numberOfMeshes;
                if (!dynamicTrackMesh.isEmpty)
                {
                    dynamicTrackMesh.name = "Curve " + i + " Track Mesh";
                    dynamicTrackMesh.Build();
                    numberOfMeshes = dynamicTrackMesh.meshCount;
                    for (int m = 0; m < numberOfMeshes; m++)
                    {
                        GameObject newMeshHolder = new GameObject("model " + (m + 1));
                        newMeshHolder.transform.parent        = curve.holder.transform;
                        newMeshHolder.transform.localPosition = Vector3.zero;
                        newMeshHolder.AddComponent <MeshFilter>().sharedMesh = dynamicTrackMesh[m].mesh;
                        if (track.numberOfTextures > 0)
                        {
                            newMeshHolder.AddComponent <MeshRenderer>().material = track.Texture(curve.trackTextureStyleIndex).GetMaterial();// track.trackTexture.material;
                        }
#if UNITY_EDITOR
                        EditorUtility.SetSelectedWireframeHidden(newMeshHolder.renderer, !track.showWireframe);
#endif
                    }
                }


                if (!dynamicBoundaryMesh.isEmpty)
                {
                    dynamicBoundaryMesh.Build();
                    numberOfMeshes = dynamicBoundaryMesh.meshCount;
                    for (int m = 0; m < numberOfMeshes; m++)
                    {
                        GameObject newMeshHolder = new GameObject("boundary " + (m + 1));
                        newMeshHolder.transform.parent        = curve.holder.transform;
                        newMeshHolder.transform.localPosition = Vector3.zero;
                        newMeshHolder.AddComponent <MeshFilter>().sharedMesh = dynamicBoundaryMesh[m].mesh;
                        if (track.numberOfTextures > 0)
                        {
                            newMeshHolder.AddComponent <MeshRenderer>().material = track.Texture(curve.boundaryTextureStyleIndex).GetMaterial();// track.trackTexture.material;
                        }
#if UNITY_EDITOR
                        EditorUtility.SetSelectedWireframeHidden(newMeshHolder.renderer, !track.showWireframe);
#endif
                    }
                }

                if (track.disconnectBoundary && !dynamicOffroadMesh.isEmpty)
                {
                    dynamicOffroadMesh.Build();
                    numberOfMeshes = dynamicOffroadMesh.meshCount;
                    for (int m = 0; m < numberOfMeshes; m++)
                    {
                        GameObject newMeshHolder = new GameObject("offroad " + (m + 1));
                        newMeshHolder.transform.parent        = curve.holder.transform;
                        newMeshHolder.transform.localPosition = Vector3.zero;
                        newMeshHolder.AddComponent <MeshFilter>().sharedMesh = dynamicOffroadMesh[m].mesh;
                        if (track.numberOfTextures > 0)
                        {
                            newMeshHolder.AddComponent <MeshRenderer>().material = track.Texture(curve.offroadTextureStyleIndex).GetMaterial();// track.offroadTexture.material;
                        }
#if UNITY_EDITOR
                        EditorUtility.SetSelectedWireframeHidden(newMeshHolder.renderer, !track.showWireframe);
#endif
                    }
                }

                if (track.includeCollider && curve.trackCollider && !dynamicColliderMesh.isEmpty)
                {
                    dynamicColliderMesh.Build();
                    int numberOfColliderMeshes = dynamicColliderMesh.meshCount;
                    for (int m = 0; m < numberOfColliderMeshes; m++)
                    {
                        GameObject newMeshHolder = new GameObject("trackCollider " + (m + 1));
                        newMeshHolder.transform.parent        = curve.holder.transform;
                        newMeshHolder.transform.localPosition = Vector3.zero;
                        newMeshHolder.AddComponent <MeshCollider>().sharedMesh = dynamicColliderMesh[m].mesh;
                    }
                }

                if (track.trackBumpers && !dynamicBumperMesh.isEmpty)
                {
                    dynamicBumperMesh.Build();
                    numberOfMeshes = dynamicBumperMesh.meshCount;
                    for (int m = 0; m < numberOfMeshes; m++)
                    {
                        GameObject newMeshHolder = new GameObject("bumper " + (m + 1));
                        newMeshHolder.transform.parent        = curve.holder.transform;
                        newMeshHolder.transform.localPosition = Vector3.zero;
                        newMeshHolder.AddComponent <MeshFilter>().sharedMesh = dynamicBumperMesh[m].mesh;
                        if (track.numberOfTextures > 0)
                        {
                            newMeshHolder.AddComponent <MeshRenderer>().material = track.Texture(curve.bumperTextureStyleIndex).GetMaterial();// track.bumperTexture.material;
                        }
#if UNITY_EDITOR
                        EditorUtility.SetSelectedWireframeHidden(newMeshHolder.renderer, !track.showWireframe);
#endif
                    }
                }

                if (!dynamicBottomMesh.isEmpty)
                {
                    dynamicBottomMesh.Build();
                    numberOfMeshes = dynamicBottomMesh.meshCount;
                    for (int m = 0; m < numberOfMeshes; m++)
                    {
                        GameObject newMeshHolder = new GameObject("bottom " + (m + 1));
                        newMeshHolder.transform.parent        = curve.holder.transform;
                        newMeshHolder.transform.localPosition = Vector3.zero;
                        newMeshHolder.AddComponent <MeshFilter>().sharedMesh = dynamicBottomMesh[m].mesh;
                        if (track.numberOfTextures > 0)
                        {
                            newMeshHolder.AddComponent <MeshRenderer>().material = track.Texture(curve.bottomTextureStyleIndex).GetMaterial();// track.trackTexture.material;
                        }
#if UNITY_EDITOR
                        EditorUtility.SetSelectedWireframeHidden(newMeshHolder.renderer, !track.showWireframe);
#endif
                    }
                }
            }
            else
            {
                if (curve.holder != null && (!curve.render || !renderTrack))
                {
                    DestroyImmediate(curve.holder);
                }
            }

            polyCount += dynamicBottomMesh.triangleCount / 3;
            polyCount += dynamicBoundaryMesh.triangleCount / 3;
            polyCount += dynamicBumperMesh.triangleCount / 3;
            polyCount += dynamicOffroadMesh.triangleCount / 3;
            polyCount += dynamicTrackMesh.triangleCount / 3;
        }

        track.TrackRendered();

        track.lastPolycount = polyCount;

#if UNITY_EDITOR
        EditorUtility.UnloadUnusedAssets();
#endif
    }
Beispiel #42
0
    public void UpdateRender(renderModes _mode)
    {
        if (data.plan == null)
        {
            return;
        }
        if (data.floorHeight == 0)
        {
            return;
        }
        if (fullMesh == null)
        {
            fullMesh = new DynamicMeshGenericMultiMaterialMesh();
        }

        fullMesh.Clear();
        fullMesh.subMeshCount = data.textures.Count;

        foreach (DynamicMeshGenericMultiMaterialMesh intMesh in interiorMeshes)
        {
            intMesh.Clear();
        }

        switch (_mode)
        {
        case renderModes.full:
            BuildrBuilding.Build(fullMesh, data);
            BuildrRoof.Build(fullMesh, data);
            break;

        case renderModes.lowDetail:
            BuildrBuildingLowDetail2.Build(fullMesh, data);
            fullMesh.CollapseSubmeshes();
            break;

        case renderModes.box:
            BuildrBuildingBox.Build(fullMesh, data);
            break;
        }

        fullMesh.Build(false);

        while (meshHolders.Count > 0)
        {
            GameObject destroyOld = meshHolders[0];
            meshHolders.RemoveAt(0);
            DestroyImmediate(destroyOld);
        }

        int numberOfMeshes = fullMesh.meshCount;

        for (int i = 0; i < numberOfMeshes; i++)
        {
            GameObject newMeshHolder = new GameObject("model " + (i + 1));
            newMeshHolder.transform.parent        = transform;
            newMeshHolder.transform.localPosition = Vector3.zero;
            meshFilt      = newMeshHolder.AddComponent <MeshFilter>();
            meshRend      = newMeshHolder.AddComponent <MeshRenderer>();
            meshFilt.mesh = fullMesh[i].mesh;
            meshHolders.Add(newMeshHolder);
        }

        while (interiorMeshHolders.Count > 0)
        {
            GameObject destroyOld = interiorMeshHolders[0];
            interiorMeshHolders.RemoveAt(0);
            DestroyImmediate(destroyOld);
        }

        switch (_mode)
        {
        case renderModes.full:
            UpdateInteriors();
            UpdateTextures();
            break;

        case renderModes.lowDetail:
            meshRend.sharedMaterials = new Material[0];
            lowDetailMat.mainTexture = data.LODTextureAtlas;
            meshRend.sharedMaterial  = lowDetailMat;
            break;

        case renderModes.box:
            meshRend.sharedMaterials = new Material[0];
            lowDetailMat.mainTexture = data.textures[0].texture;
            meshRend.sharedMaterial  = lowDetailMat;
            break;
        }
    }
    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();
    }
    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;
    }
Beispiel #45
0
 public static void Build(DynamicMeshGenericMultiMaterialMesh _mesh, BuildrData _data)
 {
     Build(_mesh, _data, false);
 }
Beispiel #46
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();
        }

    }
Beispiel #47
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();
    }
Beispiel #48
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));
            }
        }
    }