Esempio n. 1
0
        public bool PlanLegalityCheck()
        {
            for (int p = 0; p < numberOfPoints; p++)
            {
                this[p].illegal = false;
            }
            bool output = false;

            for (int indexAA = 0; indexAA < numberOfPoints; indexAA++)
            {
                Vector2Int p0      = _points[indexAA].position;
                int        indexAB = (indexAA + 1) % numberOfPoints;
                Vector2Int p1      = _points[indexAB].position;
                for (int indexBA = 0; indexBA < numberOfPoints; indexBA++)
                {
                    if (indexAA == indexBA)
                    {
                        continue;                                        //skip testing wall on itself
                    }
                    int indexBB = (indexBA + 1) % numberOfPoints;
                    if (indexAA == indexBB)
                    {
                        continue;                                        //skip testing wall on itself
                    }
                    Vector2Int p2 = _points[indexBA].position;
                    Vector2Int p3 = _points[indexBB].position;


                    if (BuildrUtils.PointOnLine(p0, p2, p3))
                    {
                        _points[indexAA].illegal = true;
                        _points[indexBA].illegal = true;
                        output = true;
                        continue;
                    }

                    if (indexAA == indexBB || indexAB == indexBA || indexAB == indexBB)
                    {
                        continue;                                                                                    //don't test lines that connect
                    }
                    //                    if (p0 == p2 || p0 == p3 || p1 == p2 || p1 == p3) continue;//don't test lines that connect

                    if (BuildrUtils.FastLineIntersection(p0, p1, p2, p3))
                    {
                        _points[indexAA].illegal = true;
                        _points[indexBA].illegal = true;
                        output = true;
                    }
                }
            }
            return(output);
        }
Esempio n. 2
0
        public static RawMeshData GeneratePlot(IPlot plot)
        {
            int pointSize = plot.numberOfEdges;

            int[]     sortedIndexes = BuildrUtils.SortPointByAngle(plot.pointsV2, plot.center);
            Vector2[] sortedPoints  = new Vector2[pointSize];
            for (int i = 0; i < pointSize; i++)
            {
                sortedPoints[i] = plot.pointsV2[sortedIndexes[i]];
            }
            bool clockwise = Clockwise(sortedPoints);

            int vertCount = pointSize + 1;
            int triCount  = pointSize * 3;

            RawMeshData output = new RawMeshData(vertCount, triCount);

            for (int v = 0; v < vertCount - 1; v++)
            {
                output.vertices[v] = new Vector3(sortedPoints[v].x, 0, sortedPoints[v].y);
            }
            output.vertices[vertCount - 1] = new Vector3(plot.center.x, 0, plot.center.y);

            int vertIndex = 0;

            for (int t = 0; t < triCount; t += 3)
            {
                output.triangles[t + 0] = vertCount - 1;
                if (clockwise)
                {
                    output.triangles[t + 1] = vertIndex;
                    output.triangles[t + 2] = (vertIndex < vertCount - 2) ? vertIndex + 1 : 0;
                }
                else
                {
                    output.triangles[t + 1] = (vertIndex < vertCount - 2) ? vertIndex + 1 : 0;
                    output.triangles[t + 2] = vertIndex;
                }
                vertIndex++;
            }

            return(output);
        }
Esempio n. 3
0
        private bool PlanLegality()
        {
            for (int p = 0; p < numberOfPoints; p++)
            {
                this[p].illegal = false;
            }
            for (int p = 0; p < numberOfPoints - 1; p++)
            {
                if (this[p] == this[p + 1])
                {
                    _points.RemoveAt(p + 1);//remove duplicate points
                }
            }
            bool output = false;

            for (int pA = 0; pA < numberOfPoints; pA++)
            {
                Vector2Int p0 = _points[pA].position;
                Vector2Int p1 = _points[(pA + 1) % numberOfPoints].position;
                for (int pB = 0; pB < numberOfPoints; pB++)
                {
                    if (pA == pB)
                    {
                        continue;          //skip testing wall on itself
                    }
                    Vector2Int p2 = _points[pB].position;
                    Vector2Int p3 = _points[(pB + 1) % numberOfPoints].position;

                    if (p0 == p2 || p0 == p3 || p1 == p2 || p1 == p3)
                    {
                        continue;                                              //don't test lines that connect
                    }
                    if (BuildrUtils.FastLineIntersection(p0, p1, p2, p3))
                    {
                        _points[pA].illegal = true;
                        _points[pB].illegal = true;
                        output = true;
                    }
                }
            }
            return(output);
        }
Esempio n. 4
0
//            _drag = Drag2D(_drag, r);
//
//            if (_mPrevRender == null)
//                _mPrevRender = new PreviewRenderUtility();
//
//            //            Vector3 max = _wallSection.previewMesh.bounds.size;
//            //            float radius = Mathf.Max(max.x, Mathf.Max(max.y, max.z)) * 1.333f;
//            float dist = radius / (Mathf.Sin(_mPrevRender.camera.fieldOfView * Mathf.Deg2Rad));
//            _mPrevRender.camera.transform.position = Vector2.zero;
//            _mPrevRender.camera.transform.rotation = Quaternion.Euler(new Vector3(-_drag.y, -_drag.x, 0));
//            _mPrevRender.camera.transform.position = _mPrevRender.camera.transform.forward * -dist;
//            _mPrevRender.camera.nearClipPlane = 0.1f;
//            _mPrevRender.camera.farClipPlane = 500;
//
//            _mPrevRender.lights[0].intensity = 0.5f;
//            _mPrevRender.lights[0].transform.rotation = Quaternion.Euler(30f, 30f, 0f);
//            _mPrevRender.lights[1].intensity = 0.5f;
//
//            _mPrevRender.BeginPreview(r, background);
//
//            if (_plane != null && _blueprintMaterial != null)
//            {
//                Matrix4x4 matrix = Matrix4x4.TRS(new Vector3(-25, -25, 1), Quaternion.identity, new Vector3(10, 10, 1));
//                _mPrevRender.DrawMesh(_plane, matrix, _blueprintMaterial, 0);
//                _mPrevRender.camera.Render();
//            }
//
//
//            int materialCount = mats.Length;
//            int submeshCount = mesh.subMeshCount;
//            int count = Mathf.Min(materialCount, submeshCount);
//            for (int c = 0; c < count; c++)
//            {
//                Material mat = c < materialCount ? mats[c] : AssetDatabase.GetBuiltinExtraResource<Material>("Default-Material.mat");
//                if (mat == null) mat = AssetDatabase.GetBuiltinExtraResource<Material>("Default-Material.mat");
//                _mPrevRender.DrawMesh(mesh, Matrix4x4.identity, mat, c);
//            }
//
//            _mPrevRender.camera.Render();
//            Texture texture = _mPrevRender.EndPreview();
//
//            GUI.DrawTexture(r, texture);
//        }
//
//        public static Vector2 Drag2D(Vector2 scrollPosition, Rect position)
//        {
//            int controlID = GUIUtility.GetControlID("Slider".GetHashCode(), FocusType.Passive);
//            Event current = Event.current;
//            switch (current.GetTypeForControl(controlID))
//            {
//                case EventType.MouseDown:
//                    if (position.Contains(current.mousePosition) && position.width > 50f)
//                    {
//                        GUIUtility.hotControl = controlID;
//                        current.Use();
//                        EditorGUIUtility.SetWantsMouseJumping(1);
//                    }
//                    break;
//                case EventType.MouseUp:
//                    if (GUIUtility.hotControl == controlID)
//                    {
//                        GUIUtility.hotControl = 0;
//                    }
//                    EditorGUIUtility.SetWantsMouseJumping(0);
//                    break;
//                case EventType.MouseDrag:
//                    if (GUIUtility.hotControl == controlID)
//                    {
//                        scrollPosition -= current.delta * (float)((!current.shift) ? 1 : 3) / Mathf.Min(position.width, position.height) * 140f;
//                        scrollPosition.y = Mathf.Clamp(scrollPosition.y, -90f, 90f);
//                        current.Use();
//                        GUI.changed = true;
//                    }
//                    break;
//            }
//            return scrollPosition;
//        }


        public static FloorplanClick OnInteriorSelectionClick(Ray mouseRay)
        {
            FloorplanClick output    = new FloorplanClick();
            Building       building  = BuildingEditor.building;
            Volume         volume    = BuildingEditor.volume;
            Floorplan      floorplan = BuildingEditor.floorplan;

            output.volume    = volume;
            output.floorplan = floorplan;

            if (floorplan != null)
            {
                Vector3 basePosition = building.transform.position;
                float   baseHeight   = volume.baseHeight;
                Vector3 testPoint    = basePosition + Vector3.up * baseHeight;
                if (Vector3.Dot(mouseRay.direction, testPoint - mouseRay.origin) < 0)//volume behind camera
                {
                    return(output);
                }

                float       floorHeight = volume.floorHeight;
                List <Room> rooms       = floorplan.rooms;
                int         roomCount   = rooms.Count;
                float       minDistance = Mathf.Infinity;
                for (int rm = 0; rm < roomCount; rm++)
                {
                    Room         room        = rooms[rm];
                    RoomPortal[] portals     = room.GetAllPortals();
                    int          portalCount = portals.Length;
                    for (int p = 0; p < portalCount; p++)
                    {
                        RoomPortal portal = portals[p];

                        int     wallIndex = portal.wallIndex;
                        Vector3 p0        = room[wallIndex].position.vector3XZ;
                        Vector3 p1        = room[(wallIndex + 1) % room.numberOfPoints].position.vector3XZ;
                        Vector3 baseUp    = Vector3.up * (floorHeight - portal.height) * portal.verticalPosition;
                        Vector3 portalUp  = baseUp + Vector3.up * portal.height;
                        Vector3 pointPos  = SceneMeshHandler.PortalPosition(Quaternion.identity, room, portal);
                        pointPos.y = baseHeight;
                        Vector3 wallDirection = (p1 - p0).normalized;
                        float   defaultWidth  = portal.width * 0.5f;
//                        float defaultDepth = 0.1f;

                        Vector3 v0 = pointPos - wallDirection * defaultWidth;
                        Vector3 v1 = pointPos + wallDirection * defaultWidth;
                        Vector3 v2 = v0 + portalUp;
                        Vector3 v3 = v1 + portalUp;

//                        Debug.DrawLine(v0,v1,Color.red,20);
//                        Debug.DrawLine(v1,v3,Color.red,20);
//                        Debug.DrawLine(v3,v2,Color.red,20);
//                        Debug.DrawLine(v2,v0,Color.red,20);

                        float distance = 0;
                        if (RayTriangle.QuadIntersection(v0, v1, v2, v3, mouseRay, out distance, false))
                        {
                            if (minDistance > distance)
                            {
                                minDistance    = distance;
                                output.room    = room;
                                output.portal  = portal;
                                output.opening = null;
                            }
                        }
                    }
                }

                VerticalOpening[] openings = building.GetAllOpenings();
                int openingCount           = openings.Length;
                for (int o = 0; o < openingCount; o++)
                {
                    VerticalOpening opening = openings[o];

                    Vector3 openingPosition = opening.position.vector3XZ;
                    openingPosition.y = volume.floorHeight * opening.baseFloor;
                    Vector3    openingSize     = opening.size.vector3XZ;
                    float      openingWidth    = openingSize.x;
                    float      openingHeight   = openingSize.z;
                    Quaternion openingRotation = Quaternion.Euler(0, opening.rotation, 0);
                    Vector3    p0 = openingPosition + openingRotation * new Vector3(-openingWidth, 0, -openingHeight) * 0.5f;
                    Vector3    p1 = openingPosition + openingRotation * new Vector3(openingWidth, 0, -openingHeight) * 0.5f;
                    Vector3    p2 = openingPosition + openingRotation * new Vector3(openingWidth, 0, openingHeight) * 0.5f;
                    Vector3    p3 = openingPosition + openingRotation * new Vector3(-openingWidth, 0, openingHeight) * 0.5f;
//                    Vector3 openingUp = Vector3.up * volume.floorHeight * (opening.floors + 1);

                    Vector3 floorUpA = Vector3.up * volume.CalculateFloorHeight(volume.Floor(BuildingEditor.floorplan));
//                    Vector3 floorUpB = floorUpA + Vector3.up * volume.floorHeight;

                    float distance = 0;
                    if (RayTriangle.QuadIntersection(p0 + floorUpA, p1 + floorUpA, p2 + floorUpA, p3 + floorUpA, mouseRay, out distance, false))
                    {
                        if (minDistance > distance)
                        {
                            minDistance    = distance;
                            output.room    = null;
                            output.portal  = null;
                            output.opening = opening;
                        }
                    }
                }

                if (output.opening != null)
                {
                    return(output);
                }

                if (output.portal != null)
                {
                    return(output);
                }

                float   intPlanBaseHeight = volume.CalculateFloorHeight(volume.Floor(floorplan));
                Vector3 baseUpV           = Vector3.up * intPlanBaseHeight;
                Plane   planPlane         = new Plane(Vector3.up, baseUpV);
                float   rayDistance       = 0;
                if (planPlane.Raycast(mouseRay, out rayDistance))
                {
                    Vector3    clickPos           = mouseRay.GetPoint(rayDistance) - basePosition;
                    Vector2Int floorClickPosition = new Vector2Int(clickPos, true);

                    for (int rm = 0; rm < roomCount; rm++)
                    {
                        Vector2Int[] roomPoints = rooms[rm].AllPoints();
                        if (BuildrUtils.PointInsidePoly(floorClickPosition, roomPoints))
                        {
                            output.room = rooms[rm];
                        }
                    }
                }
            }
            return(output);
        }
Esempio n. 5
0
        public static void GenerateFacade(FacadeData data, BuildRMesh dmesh, BuildRCollider collider = null)
        {
//		    Debug.Log("******************* "+data.facadeDesign.ToString());
            Vector3 facadeVector = data.baseB - data.baseA;

            if (facadeVector.magnitude < Mathf.Epsilon)
            {
                return;
            }
            Vector3   facadeDirection = facadeVector.normalized;
            Vector3   facadeNormal    = Vector3.Cross(facadeDirection, Vector3.up);
            Vector4   facadeTangent   = BuildRMesh.CalculateTangent(facadeDirection);
            RandomGen rGen            = new RandomGen();

            rGen.GenerateNewSeed();
            float                 wallThickness = data.wallThickness;
            float                 foundation    = data.foundationDepth;
            BuildingMeshTypes     meshType      = data.meshType;
            BuildingColliderTypes colliderType  = data.colliderType;
            int     wallSections = 0;
            Vector2 wallSectionSize;
            float   facadeLength = 0;

            if (data.isStraight)
            {
                facadeLength = facadeVector.magnitude;
                wallSections = Mathf.FloorToInt(facadeLength / data.minimumWallUnitLength);
                if (wallSections < 1)
                {
                    wallSections = 1;
                }
                wallSectionSize = new Vector2(facadeLength / wallSections, data.floorHeight);
            }
            else
            {
                wallSections = data.anchors.Count - 1;
                if (wallSections < 1)
                {
                    wallSections = 1;
                }
                float sectionWidth = Vector2.Distance(data.anchors[0].vector2, data.anchors[1].vector2);
                wallSectionSize = new Vector2(sectionWidth, data.floorHeight);
            }

            Dictionary <WallSection, RawMeshData>           generatedSections                  = new Dictionary <WallSection, RawMeshData>();
            Dictionary <WallSection, RawMeshData>           generatedSectionMeshColliders      = new Dictionary <WallSection, RawMeshData>();
            Dictionary <WallSection, BuildRCollider.BBox[]> generatedSectionPrimitiveColliders = new Dictionary <WallSection, BuildRCollider.BBox[]>();

            int startFloor = data.startFloor;

//		    Debug.Log("st fl "+startFloor);
//		    Debug.Log("fl ct "+ data.floorCount);
            for (int fl = startFloor; fl < data.floorCount; fl++)
            {
//			    Debug.Log(fl);
                if (data.facadeDesign.randomisationMode == Facade.RandomisationModes.RandomRows)
                {
                    generatedSections.Clear();                                                                             //recalculate each row
                }
//			    Debug.Log(wallSections);
                for (int s = 0; s < wallSections; s++)
                {
//				    Debug.Log(s);
                    WallSection section = data.facadeDesign.GetWallSection(s, fl + data.actualStartFloor, wallSections, data.floorCount);
//				    Debug.Log(section);
                    dmesh.submeshLibrary.Add(section);                    //add the wallsection to the main submesh library
                    RawMeshData generatedSection         = null;
                    RawMeshData generatedSectionCollider = null;

                    BuildRCollider.BBox[] bboxes = new BuildRCollider.BBox[0];

                    if (section == null)
                    {
                        GenerationOutput output         = GenerationOutput.CreateRawOutput();
                        GenerationOutput outputCollider = null;
                        if (colliderType == BuildingColliderTypes.Complex)
                        {
                            outputCollider = GenerationOutput.CreateRawOutput();
                        }
                        if (colliderType == BuildingColliderTypes.Primitive)
                        {
                            BuildRCollider.BBox[] bbox = WallSectionGenerator.Generate(section, wallSectionSize, wallThickness);
                            generatedSectionPrimitiveColliders.Add(section, bbox);
                        }
                        WallSectionGenerator.Generate(section, output, wallSectionSize, false, wallThickness, true, outputCollider, dmesh.submeshLibrary);

                        generatedSection = output.raw;
                        if (outputCollider != null)
                        {
                            generatedSectionCollider = outputCollider.raw;
                        }
                    }
                    else
                    {
                        if (generatedSections.ContainsKey(section))
                        {
                            generatedSection = generatedSections[section];
                            if (generatedSectionMeshColliders.ContainsKey(section))
                            {
                                generatedSectionCollider = generatedSectionMeshColliders[section];
                            }
                        }
                        else
                        {
                            GenerationOutput output         = GenerationOutput.CreateRawOutput();
                            GenerationOutput outputCollider = null;
                            bool             cullOpening    = data.cullDoors && section.isDoor;
                            if (colliderType == BuildingColliderTypes.Complex)
                            {
                                outputCollider = GenerationOutput.CreateRawOutput();
                            }
                            if (colliderType == BuildingColliderTypes.Primitive)
                            {
                                BuildRCollider.BBox[] bbox = WallSectionGenerator.Generate(section, wallSectionSize, wallThickness, cullOpening);
                                generatedSectionPrimitiveColliders.Add(section, bbox);
                            }
                            WallSectionGenerator.Generate(section, output, wallSectionSize, false, wallThickness, cullOpening, outputCollider, dmesh.submeshLibrary);

                            generatedSections.Add(section, output.raw);
                            if (generatedSectionCollider != null)
                            {
                                generatedSectionMeshColliders.Add(section, outputCollider.raw);
                            }

                            generatedSection = output.raw;
                            if (generatedSectionCollider != null)
                            {
                                generatedSectionCollider = outputCollider.raw;
                            }
                        }

                        if (generatedSectionPrimitiveColliders.ContainsKey(section))
                        {
                            bboxes = generatedSectionPrimitiveColliders[section];
                        }
                    }

//				    Debug.Log("data strt" + data.isStraight);
                    if (data.isStraight)
                    {
                        Quaternion meshRot           = Quaternion.LookRotation(facadeNormal, Vector3.up);
                        Vector3    baseMeshPos       = data.baseA + facadeDirection * wallSectionSize.x + Vector3.up * wallSectionSize.y;
                        Vector3    wallSectionVector = new Vector3(wallSectionSize.x * s, wallSectionSize.y * fl, 0);
                        baseMeshPos += meshRot * wallSectionVector;
                        Vector3 meshPos = baseMeshPos + meshRot * -wallSectionSize * 0.5f;

                        Vector2 uvOffset       = new Vector2(wallSectionSize.x * s, wallSectionSize.y * fl);
                        Vector2 uvOffsetScaled = uvOffset;
                        if (section != null && section.wallSurface != null)
                        {
                            uvOffsetScaled = CalculateUv(uvOffsetScaled, section.wallSurface);
                        }

                        //TODO account for the mesh mode of the wall section - custom meshes
                        if (meshType == BuildingMeshTypes.Full)
                        {
                            dmesh.AddData(generatedSection, meshPos, meshRot, Vector3.one, uvOffsetScaled);
                        }
                        if (collider != null && generatedSectionCollider != null)
                        {
                            collider.mesh.AddData(generatedSectionCollider, meshPos, meshRot, Vector3.one);
                        }
                        if (collider != null && bboxes.Length > 0)
                        {
                            collider.AddBBox(bboxes, meshPos, meshRot);
                        }

//					    Debug.Log("foundation");
                        if (fl == 0 && foundation > Mathf.Epsilon)
                        {
                            Vector3 fp3 = baseMeshPos + Vector3.down * wallSectionSize.y;
                            Vector3 fp2 = fp3 - facadeDirection * wallSectionSize.x;
                            Vector3 fp0 = fp2 + Vector3.down * foundation;
                            Vector3 fp1 = fp3 + Vector3.down * foundation;

                            if (meshType == BuildingMeshTypes.Full)
                            {
                                Surface foundationSurface = data.foundationSurface != null ? data.foundationSurface : section.wallSurface;
                                int     foundationSubmesh = dmesh.submeshLibrary.SubmeshAdd(foundationSurface);                            //facadeSurfaces.IndexOf(section.wallSurface));
                                dmesh.AddPlane(fp0, fp1, fp2, fp3, new Vector2(uvOffset.x, -foundation), new Vector2(uvOffset.x + wallSectionSize.x, 0), -facadeNormal, facadeTangent, foundationSubmesh, foundationSurface);
                            }
                            if (collider != null && generatedSectionCollider != null)
                            {
                                collider.mesh.AddPlane(fp0, fp1, fp2, fp3, 0);
                            }
                        }
                    }
                    else
                    {
                        //todo switch - support wall section based curves for now

                        Vector3 cp0 = data.anchors[s].vector3XZ;
                        cp0.y = data.baseA.y;
                        Vector3 cp1 = data.anchors[s + 1].vector3XZ;
                        cp1.y = data.baseA.y;
                        Vector3 curveVector    = cp1 - cp0;
                        Vector3 curveDirection = curveVector.normalized;
                        Vector3 curveNormal    = Vector3.Cross(curveDirection, Vector3.up);
                        float   actualWidth    = curveVector.magnitude;

                        Quaternion meshRot           = Quaternion.LookRotation(curveNormal, Vector3.up);
                        Vector3    meshPos           = cp1 + Vector3.up * wallSectionSize.y;
                        Vector3    wallSectionVector = new Vector3(0, wallSectionSize.y * fl, 0);
                        meshPos += meshRot * wallSectionVector;
                        meshPos += meshRot * -new Vector3(actualWidth, wallSectionSize.y, 0) * 0.5f;
                        Vector3 meshScale = new Vector3(actualWidth / wallSectionSize.x, 1, 1);

                        //Thanks Anthony Cuellar - issue #12
                        Vector2 uvOffset       = new Vector2(wallSectionVector.x, wallSectionVector.y + (section.hasOpening ? 0 : wallSectionSize.y / 2f));
                        Vector2 uvOffsetScaled = CalculateUv(uvOffset, section.wallSurface);
                        //TODO account for the mesh mode of the wall section - custom meshes
                        if (meshType == BuildingMeshTypes.Full)
                        {
                            dmesh.AddData(generatedSection, meshPos, meshRot, meshScale, uvOffsetScaled);
                        }
                        if (collider != null && generatedSectionCollider != null)
                        {
                            collider.mesh.AddData(generatedSectionCollider, meshPos, meshRot, meshScale);
                        }
                        if (collider != null && bboxes.Length > 0)
                        {
                            collider.AddBBox(bboxes, meshPos, meshRot);
                        }

//					    Debug.Log("foundation");
                        if (fl == 0 && foundation > Mathf.Epsilon)
                        {
                            Vector3 fp3 = cp1;
                            Vector3 fp2 = fp3 - curveDirection * actualWidth;
                            Vector3 fp0 = fp2 + Vector3.down * foundation;
                            Vector3 fp1 = fp3 + Vector3.down * foundation;

                            if (meshType == BuildingMeshTypes.Full)
                            {
                                Surface foundationSurface = data.foundationSurface != null ? data.foundationSurface : section.wallSurface;
                                int     foundationSubmesh = dmesh.submeshLibrary.SubmeshAdd(foundationSurface);                            //facadeSurfaces.IndexOf(section.wallSurface);
                                dmesh.AddPlane(fp0, fp1, fp2, fp3, new Vector2(uvOffset.x, -foundation), new Vector2(uvOffset.x + actualWidth, 0), -curveNormal, facadeTangent, foundationSubmesh, foundationSurface);
                            }
                            if (collider != null && generatedSectionCollider != null)
                            {
                                collider.mesh.AddPlane(fp0, fp1, fp2, fp3, 0);
                            }
                        }
                    }
                }

                //string course is completely ignored for a collision
//			    Debug.Log("string");
                if (fl > 0 && data.facadeDesign.stringCourse && meshType == BuildingMeshTypes.Full)                //no string course on ground floor
                {
                    float   baseStringCoursePosition = wallSectionSize.y * fl + wallSectionSize.y * data.facadeDesign.stringCoursePosition;
                    Vector3 scBaseUp = baseStringCoursePosition * Vector3.up;
                    Vector3 scTopUp  = (data.facadeDesign.stringCourseHeight + baseStringCoursePosition) * Vector3.up;
                    if (data.isStraight)
                    {
                        Vector3 scNm    = data.facadeDesign.stringCourseDepth * facadeNormal;
                        Vector3 p0      = data.baseA;
                        Vector3 p1      = data.baseB;
                        Vector3 p0o     = data.baseA - scNm;
                        Vector3 p1o     = data.baseB - scNm;
                        int     submesh = dmesh.submeshLibrary.SubmeshAdd(data.facadeDesign.stringCourseSurface);                                                                                        //data.facadeDesign.stringCourseSurface != null ? facadeSurfaces.IndexOf(data.facadeDesign.stringCourseSurface) : 0;
                        Vector2 uvMax   = new Vector2(facadeLength, data.facadeDesign.stringCourseHeight);
                        dmesh.AddPlane(p0o + scBaseUp, p1o + scBaseUp, p0o + scTopUp, p1o + scTopUp, Vector3.zero, uvMax, -facadeNormal, facadeTangent, submesh, data.facadeDesign.stringCourseSurface); //front
                        dmesh.AddPlane(p0 + scBaseUp, p0o + scBaseUp, p0 + scTopUp, p0o + scTopUp, facadeNormal, facadeTangent, submesh);                                                                //left
                        dmesh.AddPlane(p1o + scBaseUp, p1 + scBaseUp, p1o + scTopUp, p1 + scTopUp, facadeNormal, facadeTangent, submesh);                                                                //right
                        float facadeAngle = BuildrUtils.CalculateFacadeAngle(facadeDirection);
                        dmesh.AddPlaneComplexUp(p0 + scBaseUp, p1 + scBaseUp, p0o + scBaseUp, p1o + scBaseUp, facadeAngle, Vector3.down, facadeTangent, submesh, data.facadeDesign.stringCourseSurface); //bottom
                        dmesh.AddPlaneComplexUp(p1 + scTopUp, p0 + scTopUp, p1o + scTopUp, p0o + scTopUp, facadeAngle, Vector3.up, facadeTangent, submesh, data.facadeDesign.stringCourseSurface);       //top
                    }
                    else
                    {
                        int       baseCurvePointCount = data.anchors.Count;                  //baseCurvepoints.Count;
                        Vector3[] interSectionNmls    = new Vector3[baseCurvePointCount];
                        for (int i = 0; i < baseCurvePointCount - 1; i++)
                        {
                            Vector3 p0 = data.anchors[i].vector3XZ;                            //baseCurvepoints[i];
                            Vector3 p1 = data.anchors[i + 1].vector3XZ;                        //baseCurvepoints[i + 1];
                            Vector3 p2 = data.anchors[Mathf.Max(i - 1, 0)].vector3XZ;          //baseCurvepoints[Mathf.Max(i - 1, 0)];
                            interSectionNmls[i] = Vector3.Cross((p1 - p0 + p0 - p2).normalized, Vector3.up);
                        }

                        for (int i = 0; i < baseCurvePointCount - 1; i++)
                        {
                            Vector3 p0            = data.anchors[i].vector3XZ;                 //baseCurvepoints[i];
                            Vector3 p1            = data.anchors[i + 1].vector3XZ;             //baseCurvepoints[i + 1];
                            Vector3 sectionVector = p1 - p0;
                            Vector3 sectionDir    = sectionVector.normalized;
                            Vector3 sectionNml    = Vector3.Cross(sectionDir, Vector3.up);
                            Vector4 sectionTgnt   = BuildRMesh.CalculateTangent(sectionDir);
                            Vector3 scNmA         = data.facadeDesign.stringCourseDepth * interSectionNmls[i + 0];
                            Vector3 scNmB         = data.facadeDesign.stringCourseDepth * interSectionNmls[i + 1];
                            Vector3 p0o           = p0 - scNmA;
                            Vector3 p1o           = p1 - scNmB;
                            int     submesh       = dmesh.submeshLibrary.SubmeshAdd(data.facadeDesign.stringCourseSurface);                  //data.facadeDesign.stringCourseSurface != null ? facadeSurfaces.IndexOf(data.facadeDesign.stringCourseSurface) : 0;
                            dmesh.AddPlane(p0o + scBaseUp, p1o + scBaseUp, p0o + scTopUp, p1o + scTopUp, sectionNml, sectionTgnt, submesh);
                            dmesh.AddPlane(p0 + scBaseUp, p0o + scBaseUp, p0 + scTopUp, p0o + scTopUp, sectionNml, sectionTgnt, submesh);
                            dmesh.AddPlane(p1o + scBaseUp, p1 + scBaseUp, p1o + scTopUp, p1 + scTopUp, sectionNml, sectionTgnt, submesh);
                            float facadeAngle = BuildrUtils.CalculateFacadeAngle(sectionDir);
                            dmesh.AddPlaneComplexUp(p0 + scBaseUp, p1 + scBaseUp, p0o + scBaseUp, p1o + scBaseUp, facadeAngle, Vector3.down, sectionTgnt, submesh, data.facadeDesign.stringCourseSurface);                      //bottom
                            dmesh.AddPlaneComplexUp(p1 + scTopUp, p0 + scTopUp, p1o + scTopUp, p0o + scTopUp, facadeAngle, Vector3.up, sectionTgnt, submesh, data.facadeDesign.stringCourseSurface);                            //top
                        }
                    }
                }
            }
        }
Esempio n. 6
0
        public static void Generate(IBuilding building)
        {
            int numberOfVolumes = building.numberOfVolumes;

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

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

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

                #region Exteriors

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

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

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

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

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

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

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

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

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

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

                #endregion

                #region Interiors

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

                #endregion

                #region Volume Underside Generation

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

                #endregion

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

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

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

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

                case BuildingMeshTypes.Full:
                    visual.materials = dMesh.materials.ToArray();
                    break;
                }
            }
        }
Esempio n. 7
0
        public static VolumeShape[] GetTopShape(IBuilding building, IVolume volume, Vector2[] usePoints = null)
        {
            VolumeShape[] output;
            Clipper       clipper = new Clipper();

            Paths subj = new Paths();

            if (usePoints == null)
            {
                subj.Add(VolumeToPath(volume));
            }
            else
            {
                subj.Add(Vector2ToPath(usePoints));
            }
            Paths clip = new Paths();

            int numberOfAbovePlans = volume.abovePlanCount;

            Vector2[][] aboveVolumeShapes = new Vector2[numberOfAbovePlans][];
            for (int op = 0; op < numberOfAbovePlans; op++)
            {
                if (volume.AbovePlanList()[op] == null)
                {
                    continue;
                }
                aboveVolumeShapes[op] = volume.AbovePlanList()[op].AllPointsV2();
                clip.Add(Vector2ToPath(aboveVolumeShapes[op]));
            }

            VerticalOpening[] volumeOpenings = BuildrUtils.GetOpeningsQuick(building, volume);
            int numberOfOpenings             = volumeOpenings.Length;
            int volumeTopFloor = volume.floors + building.VolumeBaseFloor(volume);

            for (int op = 0; op < numberOfOpenings; op++)
            {
                if (!volumeOpenings[op].FloorIsIncluded(volumeTopFloor))
                {
                    continue;
                }

                bool      isInOtherVolume = false;
                Vector2[] openingPoints   = volumeOpenings[op].Points();
                int       openingSize     = openingPoints.Length;
                for (int v = 0; v < numberOfAbovePlans; v++)
                {
                    if (volume.AbovePlanList()[v] == null)
                    {
                        continue;
                    }
                    for (int p = 0; p < openingSize; p++)
                    {
                        if (PointInPolygon(openingPoints[p], aboveVolumeShapes[v]))
                        {
                            isInOtherVolume = true;
                            break;
                        }
                    }
                    if (isInOtherVolume)
                    {
                        break;
                    }
                }

                if (!isInOtherVolume)
                {
                    clip.Add(OpeningToPath(volumeOpenings[op]));
                }
            }


            if (clip.Count > 0)
            {
                PolyTree pTree = new PolyTree();
                clipper.AddPaths(subj, PolyType.ptSubject, true);
                clipper.AddPaths(clip, PolyType.ptClip, true);
                clipper.Execute(ClipType.ctDifference, pTree, PolyFillType.pftNonZero, PolyFillType.pftNonZero);

                int shapeCount = pTree.ChildCount;
                //                Debug.Log("GetTopShape "+shapeCount);
                output = new VolumeShape[shapeCount];
                for (int s = 0; s < shapeCount; s++)
                {
                    PolyNode node = pTree.Childs[s];
                    output[s]       = new VolumeShape();
                    output[s].outer = PathToVector2(node.Contour);
                    int holeCount = node.ChildCount;
                    output[s].holes = new Vector2[holeCount][];
                    for (int h = 0; h < holeCount; h++)
                    {
                        PolyNode holeNode = node.Childs[h];
                        output[s].holes[h] = PathToVector2(holeNode.Contour);
                    }
                }
            }
            else
            {
                output          = new VolumeShape[1];
                output[0]       = new VolumeShape();
                output[0].outer = usePoints;
                output[0].holes = new Vector2[0][];
            }

            SplitSelfIntersecting(output);

            return(output);
        }
Esempio n. 8
0
        public static void OnSceneGUI(Building _building)
        {
            Vector3 position = _building.transform.position;
//            Quaternion rotation = _building.transform.rotation;

            bool shiftIsDown = Event.current.shift;
//            bool controlIsDown = Event.current.control;
//            bool altIsDown = Event.current.alt;

//            Camera sceneCamera = Camera.current;
            Ray     ray           = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition);//sceneCamera.ScreenPointToRay(new Vector3(Event.current.mousePosition.x, Screen.height - Event.current.mousePosition.y - 30, 0));
            Event   current       = Event.current;
            IVolume mouseOverPlan = BuildrUtils.OnFloorplanSelectionClick(_building, ray).volume;

//            Volume clickedPlan = null;

            switch (current.type)
            {
            case EventType.MouseMove:
                SceneView.RepaintAll();
                break;

            case EventType.MouseDown:
//                    if (current.button == 0)
//                        clickedPlan = mouseOverPlan;
                break;

            case EventType.ScrollWheel:

                break;
            }

            Vector3 basePosition = position;

            if (BuildingEditor.volume != null)
            {
                basePosition += BuildingEditor.volume.baseHeight * Vector3.up;
            }
            Plane buildingPlane = new Plane(Vector3.up, basePosition);

            Vector3 mousePlanePoint = Vector3.zero;
            float   mouseRayDistance;

            if (buildingPlane.Raycast(ray, out mouseRayDistance))
            {
                mousePlanePoint = ray.GetPoint(mouseRayDistance);
            }
            if (shiftIsDown)
            {
                mousePlanePoint.x = Mathf.Round(mousePlanePoint.x);
                mousePlanePoint.y = Mathf.Round(mousePlanePoint.y);
                mousePlanePoint.z = Mathf.Round(mousePlanePoint.z);
            }
//            float mouseHandleSize = HandleUtility.GetHandleSize(mousePlanePoint) * 0.2f;

            DrawFloorplans(_building, mouseOverPlan);

//            if (clickedPlan != null && clickedPlan != SELECTED_VOLUME)
//            {
//                SELECTED_VOLUME = clickedPlan;
//                Repaint();
//                current.Use();
//            }
        }
Esempio n. 9
0
        private static void DrawFloorplans(IBuilding _building, IVolume mouseOverPlan)
        {
            int        numberOfFloorplans = _building.numberOfPlans;
            Vector3    position           = _building.transform.position;
            Quaternion rotation           = _building.transform.rotation;

            Camera sceneCamera = Camera.current;

            Vector3[] centerPoints = new Vector3[numberOfFloorplans];
            for (int f = 0; f < numberOfFloorplans; f++)
            {
                centerPoints[f] = BuildrUtils.CalculateFloorplanCenter(_building[f]);
            }
            //            Ray ray = sceneCamera.ScreenPointToRay(new Vector3(Event.current.mousePosition.x, Screen.height - Event.current.mousePosition.y - 30, 0));
            //            Floorplan mouseOverPlan = BuildrUtils.OnFloorplanSelectionClick(_building, ray);

            //Draw Floorplan outlines
            for (int f = 0; f < numberOfFloorplans; f++)
            {
                IVolume volume         = _building[f];
                int     numberOfPoints = volume.numberOfPoints;
                Vector2 leftPoint      = Vector2.right;
                Vector3 labelPoint     = volume.BuildingPoint(0) + position;

                int numberOfTopPoints = 0;
                for (int p = 0; p < numberOfPoints; p++)
                {
                    if (volume.IsWallStraight(p))
                    {
                        numberOfTopPoints++;
                    }
                    else
                    {
                        numberOfTopPoints += 9;
                    }
                }
                Vector3[] planVs     = new Vector3[numberOfTopPoints];
                int       planVIndex = 0;
                Vector3   planUp     = Vector3.up * volume.planHeight;

                for (int p = 0; p < numberOfPoints; p++)
                {
                    Vector3 p0   = volume.WorldPoint(p) + planUp;//rotation * floorplan.BuildingPoint(p) + position);
                    Vector2 p0ss = sceneCamera.WorldToScreenPoint(p0);
                    if (p0ss.x < leftPoint.x)
                    {
                        leftPoint  = p0ss;
                        labelPoint = p0;
                    }
                    //Render handles
                    if (volume.IsWallStraight(p))
                    {
                        planVs[planVIndex] = p0;
                        planVIndex++;
                    }
                    else
                    {
                        Vector3   p1        = volume.WorldPoint((p + 1) % numberOfPoints) + planUp; //rotation * floorplan.BuildingPoint((p + 1) % numberOfPoints) + position);
                        Vector3   cw0       = volume.WorldControlPointA(p) + planUp;                //rotation * floorplan.BuildingControlPoint(p) + position);
                        Vector3   cw1       = volume.WorldControlPointB(p) + planUp;                //rotation * floorplan.BuildingControlPoint(p) + position);
                        Vector3[] curveWall = new Vector3[10];
                        for (int t = 0; t < 10; t++)
                        {
                            Vector3 cp = FacadeSpline.Calculate(p0, cw0, cw1, p1, t / 9f);
                            curveWall[t] = cp;
                            if (t < 9)
                            {
                                planVs[planVIndex] = cp;
                                planVIndex++;
                            }
                        }
                    }
                }

                if ((Volume)volume == BuildingEditor.volume)
                {
                    Handles.color = SELECTED_BLUEPRINT_COLOUR;
                }
                else if (mouseOverPlan == volume)
                {
                    Handles.color = HIGHLIGHTED_BLUEPRINT_COLOUR;
                }
                else
                {
                    Handles.color = UNSELECTED_BLUEPRINT_COLOUR;
                }

                //                Handles.DrawAAConvexPolygon(planVs);//draw plan outline
                DrawConcavePolygonHandle.Shape(planVs, Handles.color);
//                Vector2 textDimensions = GUI.skin.label.CalcSize(new GUIContent(volume.name));
                Handles.Label(labelPoint, volume.name);

                int     linkCount  = volume.linkPlanCount;
                Vector3 thisCenter = centerPoints[f];
                Handles.color = Color.green;
                for (int l = 0; l < linkCount; l++)
                {
                    if (f == l)
                    {
                        continue;
                    }
//                    Volume link = volume.linkedPlans[l];
                    Vector3 linkCenter = centerPoints[l];
                    Handles.DrawDottedLine(thisCenter, linkCenter, 5);
                }

                int     numberOfFloors  = volume.floors;
                float   planHeight      = volume.floorHeight;
                float   totalPlanHeight = volume.planHeight;
                Vector3 planHeightV     = totalPlanHeight * Vector3.up;

                Handles.color = new Color(0, 0.2f, 1, 0.5f);

                for (int p = 0; p < numberOfPoints; p++)
                {
                    Vector3 p0 = rotation * volume.BuildingPoint(p) + position;
                    Vector3 p1 = rotation * volume.BuildingPoint((p + 1) % numberOfPoints) + position;

                    //Render handles
                    if (volume.IsWallStraight(p))
                    {
                        int wallSections = Mathf.FloorToInt(Vector3.Distance(p0, p1) / volume.minimumWallUnitLength);
                        if (wallSections < 1)
                        {
                            wallSections = 1;
                        }
                        for (int ws = 0; ws < wallSections + 1; ws++)
                        {
                            float   lerp    = ws / ((float)wallSections);
                            Vector3 basePos = Vector3.Lerp(p0, p1, lerp);
                            Handles.DrawLine(basePos, basePos + planHeightV);
                        }

                        for (int fl = 0; fl < numberOfFloors + 1; fl++)
                        {
                            Handles.color = fl == 0 || fl == numberOfFloors ? MAIN_LINE_COLOUR : SUB_LINE_COLOUR;
                            float   lineHeight  = fl * planHeight;
                            Vector3 lineHeightV = lineHeight * Vector3.up;
                            Handles.DrawLine(p0 + lineHeightV, p1 + lineHeightV);
                        }
                    }
                    else
                    {
                        Vector3   cw0       = volume.WorldControlPointA(p);
                        Vector3   cw1       = volume.WorldControlPointB(p);
                        Vector3[] curveWall = new Vector3[10];
                        float     arcLength = 0;
                        for (int t = 0; t < 10; t++)
                        {
                            Vector3 cp = FacadeSpline.Calculate(p0, cw0, cw1, p1, t / 9f);
                            curveWall[t] = cp;
                            if (t > 0)
                            {
                                arcLength += Vector3.Distance(curveWall[t - 1], curveWall[t]);
                            }
                        }

                        for (int fl = 0; fl < numberOfFloors + 1; fl++)
                        {
                            Handles.color = fl == 0 || fl == numberOfFloors ? MAIN_LINE_COLOUR : SUB_LINE_COLOUR;
                            float   lineHeight  = fl * planHeight;
                            Vector3 lineHeightV = lineHeight * Vector3.up;

                            for (int t = 0; t < 9; t++)
                            {
                                Vector3 cwp0 = curveWall[t];
                                Vector3 cwp1 = curveWall[t + 1];
                                Handles.DrawLine(cwp0 + lineHeightV, cwp1 + lineHeightV);
                            }
                            //                            Handles.DrawLine(p0 + lineHeightV, p1 + lineHeightV);
                        }
                    }

                    Handles.color = MAIN_LINE_COLOUR;
                    Handles.DrawLine(p0, p0 + Vector3.up * totalPlanHeight);

                    if ((Volume)volume == BuildingEditor.volume)
                    {
                        Vector3 facadeCenter = Vector3.Lerp(p0, p1, 0.5f) + planUp;
//                        float gtbSize = HandleUtility.GetHandleSize(facadeCenter) * 0.1f;
//                        Handles.Label(facadeCenter, "Is gabled");
//                        Handles.Button(facadeCenter, Quaternion.identity, gtbSize, gtbSize, Handles.DotCap);

                        Handles.BeginGUI();
                        Vector2 portalScreenPos = Camera.current.WorldToScreenPoint(facadeCenter);
                        portalScreenPos.y = Camera.current.pixelHeight - portalScreenPos.y;
                        Rect screenRect = new Rect(portalScreenPos, new Vector2(350, 500));
                        GUILayout.BeginArea(screenRect);

                        EditorGUILayout.LabelField(string.Format("Facade: {0}", p + 1));
                        //                        RoofFacadeInspectorGUI(volume, p);

                        GUILayout.EndArea();
                        Handles.EndGUI();
                    }
                }
            }
        }
Esempio n. 10
0
        public static void BuildFloorplan()
        {
            LAYERS.Clear();
            SceneMeshLayer layerOpengings = new SceneMeshLayer();
            SceneMeshLayer layer0         = new SceneMeshLayer();
            SceneMeshLayer layer1         = new SceneMeshLayer();
            SceneMeshLayer layer2         = new SceneMeshLayer();

            LAYERS.Add(layerOpengings);
            LAYERS.Add(layer0);
            LAYERS.Add(layer1);
            LAYERS.Add(layer2);

            Building building = BuildingEditor.building;

            bPosition = building.transform.position;
            bRotation = building.transform.rotation;
            BuildRSettings settings        = building.settings;
            int            numberOfVolumes = building.numberOfPlans;
            Quaternion     rotation        = building.transform.rotation;

            Vector3[] centerPoints = new Vector3[numberOfVolumes];
            for (int f = 0; f < numberOfVolumes; f++)
            {
                centerPoints[f] = BuildrUtils.CalculateFloorplanCenter(building[f]);
            }
            for (int v = 0; v < numberOfVolumes; v++)
            {
                Volume  volume           = (Volume)building[v];
                bool    isSelectedVolume = BuildingEditor.volume == volume;
                int     numberOfPoints   = volume.numberOfPoints;
                Vector3 vUp = Vector3.up * volume.floorHeight;
                Dictionary <int, List <Vector2Int> > anchorPoints = volume.facadeWallAnchors;

                IFloorplan[] floorplans     = volume.InteriorFloorplans();
                int          floorplanCount = floorplans.Length;
                for (int f = 0; f < floorplanCount; f++)//floors
                {
                    IFloorplan floorplan           = floorplans[f];
                    bool       isSelectedFloorplan = BuildingEditor.floorplan == (Floorplan)floorplan;
                    float      intPlanBaseHeight   = volume.CalculateFloorHeight(f);
                    Vector3    baseUpV             = Vector3.up * intPlanBaseHeight;

                    //draw external outline of selected floor
                    if (numberOfPoints > 0 && isSelectedVolume)
                    {
                        SceneMeshLayer    useLayer = isSelectedFloorplan ? layer1 : layer0;
                        List <Vector2Int> planVs   = new List <Vector2Int>();
                        Color             fillCol  = settings.subLineColour;
                        Color             lineCol  = settings.mainLineColour;
                        for (int p = 0; p < numberOfPoints; p++)
                        {
                            if (volume.IsWallStraight(p))
                            {
                                if (!planVs.Contains(volume[p].position))
                                {
                                    planVs.Add(volume[p].position);
                                }
                                Vector3 p0 = volume[p].position.vector3XZ + baseUpV;
                                Vector3 p1 = volume[(p + 1) % numberOfPoints].position.vector3XZ + baseUpV;
                                Vector3 p2 = p0 + vUp;
                                Vector3 p3 = p1 + vUp;

                                useLayer.shapes.Add(new SceneMeshShape(fillCol, p0, p1, p3, p2));
                                useLayer.lines.Add(new SceneMeshLine(p2, p3, lineCol));
                                useLayer.lines.Add(new SceneMeshLine(p0, p2, lineCol));
                                useLayer.lines.Add(new SceneMeshLine(p1, p3, lineCol));
                                if (isSelectedFloorplan)
                                {
                                    useLayer.lines.Add(new SceneMeshLine(p0, p1, Color.red));

                                    List <Vector2Int> anchors = anchorPoints[p];
                                    int wallSections          = anchors.Count;
                                    for (int w = 0; w < wallSections - 1; w++)
                                    {
                                        Vector3 a          = anchors[w].vector3XZ + baseUpV;
                                        float   anchorSize = 0.05f;
                                        if (w == 0)
                                        {
                                            anchorSize *= 2;
                                        }
                                        useLayer.dots.Add(new SceneMeshDot(a, anchorSize, settings.anchorColour));
                                    }
                                }
                            }
                            else
                            {
                                List <Vector2Int> anchors = anchorPoints[p];
                                int wallSections          = anchors.Count;
                                for (int w = 0; w < wallSections - 2; w++)
                                {
                                    if (!planVs.Contains(anchors[w]))
                                    {
                                        planVs.Add(anchors[w]);
                                    }
                                    Vector3 p0 = anchors[w].vector3XZ + baseUpV;
                                    Vector3 p1 = anchors[w + 1].vector3XZ + baseUpV;
                                    Vector3 p2 = p0 + vUp;
                                    Vector3 p3 = p1 + vUp;

                                    useLayer.lines.Add(new SceneMeshLine(p2, p3, lineCol));
                                    if (w == 0)
                                    {
                                        useLayer.lines.Add(new SceneMeshLine(p0, p2, lineCol));
                                    }
                                    if (w == wallSections - 2)
                                    {
                                        useLayer.lines.Add(new SceneMeshLine(p1, p3, lineCol));
                                    }

                                    useLayer.shapes.Add(new SceneMeshShape(fillCol, p0, p1, p3, p2));

                                    if (isSelectedFloorplan)
                                    {
                                        useLayer.lines.Add(new SceneMeshLine(p0, p1, Color.red));

                                        float anchorSize = 0.05f;
                                        if (w == 0)
                                        {
                                            anchorSize *= 2;
                                        }
                                        if (w < wallSections - 1)
                                        {
                                            useLayer.dots.Add(new SceneMeshDot(p0, anchorSize, settings.anchorColour));
                                        }
                                    }
                                }
                            }
                        }

                        if (isSelectedFloorplan)
                        {
                            int       planVCount = planVs.Count;
                            Vector3[] planV3     = new Vector3[planVCount];
                            for (int pv = 0; pv < planVCount; pv++)
                            {
                                planV3[pv] = planVs[pv].vector3XZ + baseUpV;
                            }
                            ShapeWithLines(useLayer, planV3, Color.red, new Color(1, 1, 1, 0.9f));
                        }
                    }

                    if (isSelectedFloorplan)
                    {
                        Room[]            rooms       = floorplan.AllRooms();
                        int               roomCount   = rooms.Length;
                        List <Vector2Int> shapePoints = new List <Vector2Int>();
                        for (int r = 0; r < roomCount; r++)
                        {
                            Room room           = rooms[r];
                            bool isRoomSelected = room == BuildingEditor.room && BuildingEditor.roomPortal == null && BuildingEditor.opening == null;
                            shapePoints.Clear();

                            FloorplanUtil.RoomWall[] roomWalls = FloorplanUtil.CalculatePoints(room, volume);
                            int roomWallCount = roomWalls.Length;

                            Color wallCol     = isRoomSelected ? settings.roomWallSelectedColour : settings.roomWallColour;
                            Color floorCol    = isRoomSelected ? settings.roomWallSelectedColour : settings.roomFloorColour;
                            Color mainLineCol = isRoomSelected ? settings.selectedPointColour : settings.mainLineColour;
                            Color subLineCol  = isRoomSelected ? settings.selectedPointColour : settings.subLineColour;

                            for (int rwp = 0; rwp < roomWallCount; rwp++)
                            {
                                FloorplanUtil.RoomWall roomWall = roomWalls[rwp];
                                int offsetCount = roomWall.offsetPoints.Length;

                                Vector2Int pi0 = roomWall.baseA;
                                Vector2Int pi1 = roomWall.baseB;

                                if (pi0 == pi1)
                                {
                                    continue;            //not a wall
                                }
                                for (int op = 0; op < offsetCount - 1; op++)
                                {
                                    Vector2Int wsint0 = new Vector2Int(roomWall.offsetPoints[op]);
                                    if (!shapePoints.Contains(wsint0))
                                    {
                                        shapePoints.Add(wsint0);
                                    }
                                    Vector3 ws0 = new Vector3(roomWall.offsetPoints[op].x, 0, roomWall.offsetPoints[op].y) + baseUpV;

                                    if (isSelectedFloorplan)//draw anchor points
                                    {
                                        float anchorSize = 0.05f;
                                        if (op == 0)
                                        {
                                            anchorSize *= 2;
                                        }
                                        layer1.dots.Add(new SceneMeshDot(ws0, anchorSize * 0.05f, settings.linkedAnchorColour));
                                    }

                                    int     nextIndex = (op + 1) % offsetCount;
                                    Vector3 ws1       = new Vector3(roomWall.offsetPoints[nextIndex].x, 0, roomWall.offsetPoints[nextIndex].y) + baseUpV;
                                    Vector3 ws2       = ws0 + vUp;
                                    Vector3 ws3       = ws1 + vUp;

                                    layer1.lines.Add(new SceneMeshLine(ws0, ws1, mainLineCol));
                                    layer1.lines.Add(new SceneMeshLine(ws0, ws2, subLineCol));
                                    layer1.lines.Add(new SceneMeshLine(ws1, ws3, subLineCol));

                                    layer1.shapes.Add(new SceneMeshShape(wallCol, ws0, ws1, ws3, ws2));
                                }
                            }

                            int       shapePointsCount = shapePoints.Count;
                            Vector3[] planV3           = new Vector3[shapePointsCount];
                            for (int pv = 0; pv < shapePointsCount; pv++)
                            {
                                planV3[pv] = shapePoints[pv].vector3XZ + baseUpV;
                            }
                            ShapeWithLines(layer1, planV3, mainLineCol, floorCol, settings.highlightPerpendicularity, settings.highlightPerpendicularityColour, settings.highlightAngleColour);

                            RoomPortal[] portals     = room.GetAllPortals();
                            int          portalCount = portals.Length;
                            for (int pt = 0; pt < portalCount; pt++)
                            {
                                RoomPortal portal           = portals[pt];
                                bool       isSelected       = BuildingEditor.roomPortal == portal;
                                Color      portalLineColour = isSelectedFloorplan ? settings.mainLineColour : settings.subLineColour;
                                Color      portalFillColour = isSelected ? settings.selectedPointColour : settings.mainLineColour;
                                if (!isSelectedFloorplan)
                                {
                                    portalFillColour = Color.clear;
                                }
                                DrawPortal(layer2, rotation, intPlanBaseHeight, volume.floorHeight, room, portal, portalLineColour, portalFillColour);
                            }
                        }

                        for (int r = 0; r < roomCount; r++)
                        {
                            Room    room       = rooms[r];
                            Vector3 roomCenter = room.center.vector3XZ + baseUpV + Vector3.up * volume.floorHeight;
                            layer1.labels.Add(new SceneMeshLabel(roomCenter, string.Format("Room {0}", (r + 1))));
                        }
                    }

                    //Draw vertical openings
                    if (BuildingEditor.floorplan != null)
                    {
                        VerticalOpening[] openings = building.GetAllOpenings();
                        int openingCount           = openings.Length;
                        for (int o = 0; o < openingCount; o++)
                        {
                            VerticalOpening opening           = openings[o];
                            bool            isSelectedOpening = BuildingEditor.opening == opening;

                            Vector3 openingPosition = opening.position.vector3XZ;
                            openingPosition.y = volume.floorHeight * opening.baseFloor;
                            Vector3    openingSize     = opening.size.vector3XZ;
                            float      openingWidth    = openingSize.x;
                            float      openingHeight   = openingSize.z;
                            Quaternion openingRotation = Quaternion.Euler(0, opening.rotation, 0);
                            Vector3    p0        = openingPosition + openingRotation * new Vector3(-openingWidth, 0, -openingHeight) * 0.5f;
                            Vector3    p1        = openingPosition + openingRotation * new Vector3(openingWidth, 0, -openingHeight) * 0.5f;
                            Vector3    p2        = openingPosition + openingRotation * new Vector3(openingWidth, 0, openingHeight) * 0.5f;
                            Vector3    p3        = openingPosition + openingRotation * new Vector3(-openingWidth, 0, openingHeight) * 0.5f;
                            Vector3    openingUp = Vector3.up * volume.floorHeight * (opening.floors + 1);

                            //"Phil" Mitchels
                            Color fillCol = settings.subLineColour;
                            fillCol.a = 0.05f;
                            layerOpengings.shapes.Add(new SceneMeshShape(fillCol, p0, p1, p2, p3));
                            layerOpengings.shapes.Add(new SceneMeshShape(fillCol, p0, p1, p1 + openingUp, p0 + openingUp));
                            layerOpengings.shapes.Add(new SceneMeshShape(fillCol, p1, p2, p2 + openingUp, p1 + openingUp));
                            layerOpengings.shapes.Add(new SceneMeshShape(fillCol, p2, p3, p3 + openingUp, p2 + openingUp));
                            layerOpengings.shapes.Add(new SceneMeshShape(fillCol, p3, p0, p0 + openingUp, p3 + openingUp));

                            //lines
                            Color lineCol = settings.invertLineColour;
                            layer0.lines.Add(new SceneMeshLine(p0, p1, lineCol));
                            layer0.lines.Add(new SceneMeshLine(p1, p2, lineCol));
                            layer0.lines.Add(new SceneMeshLine(p2, p3, lineCol));
                            layer0.lines.Add(new SceneMeshLine(p3, p0, lineCol));

                            layer0.lines.Add(new SceneMeshLine(p0 + openingUp, p1 + openingUp, lineCol));
                            layer0.lines.Add(new SceneMeshLine(p1 + openingUp, p2 + openingUp, lineCol));
                            layer0.lines.Add(new SceneMeshLine(p2 + openingUp, p3 + openingUp, lineCol));
                            layer0.lines.Add(new SceneMeshLine(p3 + openingUp, p0 + openingUp, lineCol));

                            layer0.lines.Add(new SceneMeshLine(p0, p0 + openingUp, lineCol));
                            layer0.lines.Add(new SceneMeshLine(p1, p1 + openingUp, lineCol));
                            layer0.lines.Add(new SceneMeshLine(p2, p2 + openingUp, lineCol));
                            layer0.lines.Add(new SceneMeshLine(p3, p3 + openingUp, lineCol));


                            layer0.labels.Add(new SceneMeshLabel(openingPosition + openingUp, string.Format("Opening {0}", o + 1)));

                            if (volume == BuildingEditor.volume && BuildingEditor.floorplan != null)
                            {
                                Vector3 floorUpA = Vector3.up * volume.CalculateFloorHeight(volume.Floor(BuildingEditor.floorplan));
                                Vector3 floorUpB = floorUpA + Vector3.up * volume.floorHeight;

                                Color          col      = isSelectedOpening ? Color.green : Color.red;
                                SceneMeshLayer useLayer = isSelectedOpening ? layer2 : layer2;

                                useLayer.lines.Add(new SceneMeshLine(p0 + floorUpA, p1 + floorUpA, col));
                                useLayer.lines.Add(new SceneMeshLine(p1 + floorUpA, p2 + floorUpA, col));
                                useLayer.lines.Add(new SceneMeshLine(p2 + floorUpA, p3 + floorUpA, col));
                                useLayer.lines.Add(new SceneMeshLine(p3 + floorUpA, p0 + floorUpA, col));

                                useLayer.lines.Add(new SceneMeshLine(p0 + floorUpB, p1 + floorUpB, col));
                                useLayer.lines.Add(new SceneMeshLine(p1 + floorUpB, p2 + floorUpB, col));
                                useLayer.lines.Add(new SceneMeshLine(p2 + floorUpB, p3 + floorUpB, col));
                                useLayer.lines.Add(new SceneMeshLine(p3 + floorUpB, p0 + floorUpB, col));

                                useLayer.lines.Add(new SceneMeshLine(p0 + floorUpA, p0 + floorUpB, col));
                                useLayer.lines.Add(new SceneMeshLine(p1 + floorUpA, p1 + floorUpB, col));
                                useLayer.lines.Add(new SceneMeshLine(p2 + floorUpA, p2 + floorUpB, col));
                                useLayer.lines.Add(new SceneMeshLine(p3 + floorUpA, p3 + floorUpB, col));
                            }
                        }
                    }
                }
            }
        }
Esempio n. 11
0
        public static bool Generate(BuildRMesh mesh, BuildRCollider collider, Vector2[] points, int[] facadeIndices, float roofBaseHeight, IVolume volume)
        {
            if (points.Length == 0)
            {
                return(false);
            }

            if (BuildrUtils.SelfIntersectingPoly(points))
            {
                return(false);
            }

            Roof  design     = volume.roof;
            float floorWidth = design.floorDepth;
            float roofDepth  = design.depth;
            float roofHeight = design.height;

            Surface mainSurface  = design.mainSurface;
            Surface floorSurface = design.floorSurface;
            int     mainSubmesh  = mesh.submeshLibrary.SubmeshAdd(mainSurface);
            int     floorSubmesh = mesh.submeshLibrary.SubmeshAdd(floorSurface);

            //mansard floor
            if (floorWidth > 0)
            {
                OffsetSkeleton offsetFloorPoly = new OffsetSkeleton(points, null, floorWidth);
                offsetFloorPoly.direction = 1;
                offsetFloorPoly.Execute();
                Shape floorShape = offsetFloorPoly.shape;

                if (floorShape != null)
                {
                    ToMesh(ref mesh, ref floorShape, roofBaseHeight, 0, facadeIndices, volume, floorSubmesh, design.floorSurface);

                    points = new Vector2[floorShape.terminatedNodeCount];
                    for (int i = 0; i < floorShape.terminatedNodeCount; i++)
                    {
                        points[i] = floorShape.TerminatedNode(i).position;
                    }
                }
                else
                {
                    return(false);
                    //todo
                }
            }

            if (points.Length == 0)
            {
                return(false);
            }

            //mansard pitch
            OffsetSkeleton offsetRoofPoly = new OffsetSkeleton(points, null, roofDepth);

            offsetRoofPoly.direction = 1;
            offsetRoofPoly.Execute();
            Shape roofShape = offsetRoofPoly.shape;

            if (roofShape == null)
            {
                return(false);
            }

            if (facadeIndices.Length < roofShape.baseEdges.Count)
            {
                return(false);
            }

            ToMesh(ref mesh, ref roofShape, roofBaseHeight, roofHeight, facadeIndices, volume, mainSubmesh, mainSurface, design.hasDormers);

            points = new Vector2[roofShape.terminatedNodeCount];
            for (int i = 0; i < roofShape.terminatedNodeCount; i++)
            {
                points[i] = roofShape.TerminatedNode(i).position;
            }

            //mansard top
            ToMesh(ref mesh, points, roofBaseHeight + roofHeight, facadeIndices, volume, floorSubmesh, floorSurface);

            return(true);
        }