예제 #1
0
        public VerticalOpening AddOpening()
        {
            VerticalOpening output = new VerticalOpening();

            _openings.Add(output);
            return(output);
        }
예제 #2
0
 public static void Generate(BuildRMesh mesh, VerticalOpening opening, Vector3 basePosition, float height, int floor, int wallSubmesh = -1, BuildRCollider collider = null)
 {
     if (collider != null)
     {
         collider.thickness = VerticalOpening.WALL_THICKNESS;
     }
     GenerateWall(mesh, opening, basePosition, height, wallSubmesh, collider);
     GenerateStairs(mesh, opening, basePosition, height, floor, wallSubmesh, collider);
 }
예제 #3
0
        private static Path OpeningToPath(VerticalOpening opening)
        {
            Path output = new Path();

            Vector2[] points = opening.PointsRotated();
            points = QuickPolyOffset.Execute(points, VerticalOpening.WALL_THICKNESS);
            int numberOfPoints = points.Length;

            for (int p = 0; p < numberOfPoints; p++)
            {
                output.Add(Vector2ToIntpoint(points[p]));
            }
            return(output);
        }
예제 #4
0
        /// <summary>
        /// This one ignores finding openings within specific shapes as we'll be doing this for rooms in floorplan gen
        /// </summary>
        /// <param name="building"></param>
        /// <param name="volume"></param>
        /// <returns></returns>
        public static VerticalOpening[] GetOpeningsQuick(IBuilding building, IVolume volume)
        {
            List <VerticalOpening> output = new List <VerticalOpening>();
            int count = building.openingCount;

            VerticalOpening[] openings = building.GetAllOpenings();

            int volumeBaseFloor = building.VolumeBaseFloor(volume);
            int volumeTopFloor  = volumeBaseFloor + volume.floors;

            for (int i = 0; i < count; i++)
            {
                VerticalOpening opening          = openings[i];
                int             openingBaseFloor = opening.baseFloor;
                int             openingTopFloor  = openingBaseFloor + opening.floors;

//                Debug.Log("CHECK IT " + openingTopFloor + " " + volume.name);
//                Debug.Log(volumeBaseFloor + " < " + openingTopFloor + " && " + openingBaseFloor + " < " + volumeTopFloor);

                if (volumeBaseFloor <= openingTopFloor && openingBaseFloor < volumeTopFloor)//opening and volume floors intersect
                {
//                    Debug.Log("opening " + openingTopFloor + " "+ volume.name);
                    FlatBounds volumeBounds = new FlatBounds(volume.bounds);
                    volumeBounds.Expand(VerticalOpening.WALL_THICKNESS);
                    Vector2[]  openingPoints = opening.PointsRotated();
                    FlatBounds openingBounds = new FlatBounds(openingPoints);


//                    if(volume.name == "Roof Exit")
//                    {
//                        Debug.Log(volumeBounds.Overlaps(openingBounds, true));
//                        Debug.Log(openingBounds.Overlaps(volumeBounds, true));
//                        volumeBounds.DrawDebug(Color.red);
//                        openingBounds.DrawDebug(Color.green);
//                    }

                    if (openingBounds.Overlaps(volumeBounds, true))// opening is within the AABB bounds of the volume
                    {
                        output.Add(opening);
//                        Debug.Log("opening bounds " + openingTopFloor + " " + volume.name);
                    }
                    else
                    {
//                        Debug.Log("opening NOT " + openingTopFloor + " " + volume.name);
                    }
                }
//                Debug.Log("=================================");
            }
            return(output.ToArray());
        }
예제 #5
0
        public VerticalOpening[] GetOpenings(IVolume volume, IFloorplan inPlan)
        {
            List <VerticalOpening> output = new List <VerticalOpening>();
            int count     = _openings.Count;
            int planFloor = volume.Floor(inPlan);

            for (int i = 0; i < count; i++)
            {
                VerticalOpening opening   = _openings[i];
                int             baseFloor = opening.baseFloor;
                int             topFloor  = baseFloor + opening.floors;
                if (planFloor >= baseFloor && planFloor <= topFloor)
                {
                    output.Add(opening);
                }
            }
            return(output.ToArray());
        }
예제 #6
0
        public bool[] GetOpenings(IVolume volume, IFloorplan inPlan, int offset)
        {
            List <bool> output      = new List <bool>();
            int         count       = _openings.Count;
            int         planFloor   = volume.Floor(inPlan);
            int         offsetFloor = planFloor + offset;

            for (int i = 0; i < count; i++)
            {
                VerticalOpening opening   = _openings[i];
                int             baseFloor = opening.baseFloor;
                int             topFloor  = baseFloor + opening.floors;
                if (planFloor >= baseFloor && planFloor <= topFloor)
                {
                    bool isOpen = offsetFloor >= baseFloor && offsetFloor <= topFloor;
                    output.Add(isOpen);
                }
            }
            return(output.ToArray());
        }
예제 #7
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);
        }
예제 #8
0
 public void RemoveOpening(VerticalOpening opening)
 {
     _openings.Remove(opening);
 }
예제 #9
0
        public static void GenerateRoofAccess(BuildRMesh mesh, VerticalOpening opening, Vector3 basePosition, float height, int floor, int wallSubmesh = -1, BuildRCollider collider = null)
        {
            //            bool stepped = true;//todo
            float minimumWidth = 0.9f;            //UK standard
//			float maximumWidth = 2.0f;
            //            float stepHeight = 0.22f;
            float wallThickness = VerticalOpening.WALL_THICKNESS;

            float stairWidth = 0.70f;            //todo / calculate
            float doorWidth  = 1.3f;
            float doorHeight = 2.04f;

            bool generateColldier = collider != null;

            float minimumRunLength   = 0.25f;
            float maximumRiserHeight = 0.2f;

            SubmeshLibrary submeshLibrary       = mesh.submeshLibrary;
            int            externalWallSubmesh  = submeshLibrary.SubmeshAdd(opening.surfaceA);
            int            internalWallSubmesh  = submeshLibrary.SubmeshAdd(opening.surfaceB);
            int            doorFrameSubmesh     = submeshLibrary.SubmeshAdd(opening.surfaceC);
            int            internalFloorSubmesh = submeshLibrary.SubmeshAdd(opening.surfaceD);

            //base positions
            Quaternion rotation    = Quaternion.Euler(0, opening.rotation, 0);
            Vector2Int openingSize = opening.size;
            Vector3    b0          = basePosition + rotation * new Vector3(-opening.size.vx * 0.5f, height, -opening.size.vy * 0.5f);
            Vector3    b1          = basePosition + rotation * new Vector3(opening.size.vx * 0.5f, height, -opening.size.vy * 0.5f);
            Vector3    b2          = basePosition + rotation * new Vector3(-opening.size.vx * 0.5f, height, opening.size.vy * 0.5f);
            Vector3    b3          = basePosition + rotation * new Vector3(opening.size.vx * 0.5f, height, opening.size.vy * 0.5f);

            //inner points
            Vector3 b0i = b0 + rotation * new Vector3(1, 0, 1) * wallThickness;
            Vector3 b1i = b1 + rotation * new Vector3(-1, 0, 1) * wallThickness;
            Vector3 b2i = b2 + rotation * new Vector3(1, 0, -1) * wallThickness;
            Vector3 b3i = b3 + rotation * new Vector3(-1, 0, -1) * wallThickness;

            Vector2 internalSize    = new Vector2(openingSize.vx - wallThickness * 2, openingSize.vy - wallThickness * 2);
            float   stairWidthFromX = internalSize.x * 0.5f;
            float   stairWidthFromY = internalSize.y - Mathf.Ceil(height / maximumRiserHeight) * minimumRunLength;

            float useLandingWidth = (stairWidthFromX + stairWidthFromY) * 0.5f;

            useLandingWidth = Mathf.Clamp(useLandingWidth, minimumWidth, opening.stairWidth);

            Vector3 escalationFlatDir = (b2i - b0i).normalized;

            Vector3 landingDrop = Vector3.down * wallThickness;

            //landing
            Vector3 l0 = b0i;
            Vector3 l1 = b1i;
            Vector3 l2 = b0i + escalationFlatDir * useLandingWidth;
            Vector3 l3 = b1i + escalationFlatDir * useLandingWidth;

            //top
            mesh.AddPlane(l0, l1, l2, l3, internalFloorSubmesh);
            //bottom
            mesh.AddPlane(l1 + landingDrop, l0 + landingDrop, l3 + landingDrop, l2 + landingDrop, internalWallSubmesh);
            //front
            mesh.AddPlane(l2, l3, l2 + landingDrop, l3 + landingDrop, internalWallSubmesh);

            if (generateColldier)
            {
                collider.mesh.AddPlane(l0, l1, l2, l3, 0);
                collider.mesh.AddPlane(l1 + landingDrop, l0 + landingDrop, l3 + landingDrop, l2 + landingDrop, 0);
                collider.mesh.AddPlane(l2, l3, l2 + landingDrop, l3 + landingDrop, 0);
            }

            //internal walls
            Vector3 wallUp = Vector3.up * height;

            wallUp.y += -wallThickness * 0.5f;
            Vector3 wallUpI = Vector3.up * (height - wallThickness);

            mesh.AddPlane(b0i, b2i, b0i + wallUpI, b2i + wallUpI, internalWallSubmesh);
            mesh.AddPlane(b2i, b3i, b2i + wallUpI, b3i + wallUpI, internalWallSubmesh);
            mesh.AddPlane(b3i, b1i, b3i + wallUpI, b1i + wallUpI, internalWallSubmesh);
            mesh.AddPlane(b1i + wallUpI, b0i + wallUpI, b3i + wallUpI, b2i + wallUpI, internalWallSubmesh);

            //external walls
            mesh.AddPlane(b2, b0, b2 + wallUp, b0 + wallUp, externalWallSubmesh);
            mesh.AddPlane(b3, b2, b3 + wallUp, b2 + wallUp, externalWallSubmesh);
            mesh.AddPlane(b1, b3, b1 + wallUp, b3 + wallUp, externalWallSubmesh);
            mesh.AddPlane(b0 + wallUp, b1 + wallUp, b2 + wallUp, b3 + wallUp, internalWallSubmesh);

            if (generateColldier)
            {
                collider.AddPlane(b2, b0, b2 + wallUp, b0 + wallUp);
                collider.AddPlane(b3, b2, b3 + wallUp, b2 + wallUp);
                collider.AddPlane(b1, b3, b1 + wallUp, b3 + wallUp);
                collider.mesh.AddPlane(b1i + wallUpI, b0i + wallUpI, b3i + wallUpI, b2i + wallUpI, 0);
                collider.mesh.AddPlane(b0 + wallUp, b1 + wallUp, b2 + wallUp, b3 + wallUp, 0);

                if (!collider.usingPrimitives)
                {
                    collider.mesh.AddPlane(b0i, b2i, b0i + wallUpI, b2i + wallUpI, 0);
                    collider.mesh.AddPlane(b2i, b3i, b2i + wallUpI, b3i + wallUpI, 0);
                    collider.mesh.AddPlane(b3i, b1i, b3i + wallUpI, b1i + wallUpI, 0);
                }
            }


            //door wall
            //internal
            float internalWallLength = openingSize.vx - (wallThickness * 2f);
            float lerpA = Mathf.Max(stairWidth - doorWidth, 0.05f) / internalWallLength;
            float lerpB = (Mathf.Max(stairWidth - doorWidth, 0.05f) + doorWidth) / internalWallLength;

            Vector3 bd0i = Vector3.Lerp(b0i, b1i, lerpA);
            Vector3 bd1i = Vector3.Lerp(b0i, b1i, lerpB);

            Vector3 doorUp = Vector3.up * doorHeight;

            //Right side
            mesh.AddPlane(bd0i, b0i, bd0i + doorUp, b0i + doorUp, internalWallSubmesh);
            //left side
            mesh.AddPlane(b1i, bd1i, b1i + doorUp, bd1i + doorUp, internalWallSubmesh);
            //top
            mesh.AddPlane(b1i + doorUp, b0i + doorUp, b1i + wallUpI, b0i + wallUpI, internalWallSubmesh);

            //external
            Vector3 doorOut = -escalationFlatDir * wallThickness;

            //left
            mesh.AddPlane(b0, bd0i + doorOut, b0 + doorUp, bd0i + doorOut + doorUp, externalWallSubmesh);
            //right
            mesh.AddPlane(bd1i + doorOut, b1, bd1i + doorOut + doorUp, b1 + doorUp, externalWallSubmesh);
            //top
            mesh.AddPlane(b0 + doorUp, b1 + doorUp, b0 + wallUp, b1 + wallUp, externalWallSubmesh);

            //frame
            //floor
            mesh.AddPlane(bd1i, bd0i, bd1i + doorOut, bd0i + doorOut, externalWallSubmesh);
            //left
            mesh.AddPlane(bd0i + doorOut, bd0i, bd0i + doorOut + doorUp, bd0i + doorUp, doorFrameSubmesh);
            //right
            mesh.AddPlane(bd1i, bd1i + doorOut, bd1i + doorUp, bd1i + doorOut + doorUp, doorFrameSubmesh);
            //top
            mesh.AddPlane(bd0i + doorUp, bd1i + doorUp, bd0i + doorOut + doorUp, bd1i + doorOut + doorUp, doorFrameSubmesh);

            if (generateColldier)
            {
                collider.AddPlane(b0, bd0i + doorOut, b0 + doorUp, bd0i + doorOut + doorUp);
                collider.AddPlane(bd1i + doorOut, b1, bd1i + doorOut + doorUp, b1 + doorUp);
                collider.AddPlane(b0 + doorUp, b1 + doorUp, b0 + wallUp, b1 + wallUp);

                if (!collider.usingPrimitives)
                {
                    collider.mesh.AddPlane(bd0i, b0i, bd0i + doorUp, b0i + doorUp, 0);
                    collider.mesh.AddPlane(b1i, bd1i, b1i + doorUp, bd1i + doorUp, 0);
                    collider.mesh.AddPlane(b1i + doorUp, b0i + doorUp, b1i + wallUpI, b0i + wallUpI, 0);

                    collider.mesh.AddPlane(bd1i, bd0i, bd1i + doorOut, bd0i + doorOut, 0);
                    collider.mesh.AddPlane(bd0i + doorOut, bd0i, bd0i + doorOut + doorUp, bd0i + doorUp, 0);
                    collider.mesh.AddPlane(bd1i, bd1i + doorOut, bd1i + doorUp, bd1i + doorOut + doorUp, 0);
                    collider.mesh.AddPlane(bd0i + doorUp, bd1i + doorUp, bd0i + doorOut + doorUp, bd1i + doorOut + doorUp, 0);
                }
            }
        }
예제 #10
0
        public static void GenerateWall(BuildRMesh mesh, VerticalOpening opening, Vector3 basePosition, float height, int wallSubmesh = -1, BuildRCollider collider = null)
        {
            float stairWidth       = 0.70f;      //todo / calculate
            float wallThickness    = VerticalOpening.WALL_THICKNESS;
            float doorWidth        = 1.3f;
            float doorHeight       = 2.04f;
            bool  generateColldier = collider != null;
            //            bool generateMeshCollider = generateColldier && !collider.usingPrimitives;

            SubmeshLibrary submeshLibrary      = mesh.submeshLibrary;
            int            externalWallSubmesh = submeshLibrary.SubmeshAdd(opening.surfaceA);
            int            internalWallSubmesh = submeshLibrary.SubmeshAdd(opening.surfaceB);
            int            doorFrameSubmesh    = submeshLibrary.SubmeshAdd(opening.surfaceC);

            //base positions
            Quaternion rotation    = Quaternion.Euler(0, opening.rotation, 0);
            Vector2Int openingSize = opening.size;
            Vector3    b0          = basePosition + rotation * new Vector3(-opening.size.vx * 0.5f, 0, -opening.size.vy * 0.5f);
            Vector3    b1          = basePosition + rotation * new Vector3(opening.size.vx * 0.5f, 0, -opening.size.vy * 0.5f);
            Vector3    b2          = basePosition + rotation * new Vector3(-opening.size.vx * 0.5f, 0, opening.size.vy * 0.5f);
            Vector3    b3          = basePosition + rotation * new Vector3(opening.size.vx * 0.5f, 0, opening.size.vy * 0.5f);

            //inner points
            Vector3 b0i = b0 + rotation * new Vector3(1, 0, 1) * wallThickness;
            Vector3 b1i = b1 + rotation * new Vector3(-1, 0, 1) * wallThickness;
            Vector3 b2i = b2 + rotation * new Vector3(1, 0, -1) * wallThickness;
            Vector3 b3i = b3 + rotation * new Vector3(-1, 0, -1) * wallThickness;

            Vector3 escalationFlatDir = (b2i - b0i).normalized;
            Vector3 wallUp            = Vector3.up * height;

            //external walls
            Vector2 uv20_min  = new Vector2(0, 0);
            Vector2 uv20_max  = new Vector2(opening.size.vy, height);
            Vector3 normal02  = rotation * Vector3.left;
            Vector4 tangent02 = BuildRMesh.CalculateTangent((b0 - b2).normalized);

            mesh.AddPlane(b2, b0, b2 + wallUp, b0 + wallUp, uv20_min, uv20_max, normal02, tangent02, externalWallSubmesh, opening.surfaceA);

            Vector2 uv32_min  = new Vector2(0, 0);
            Vector2 uv32_max  = new Vector2(opening.size.vx, height);
            Vector3 normal32  = rotation * Vector3.forward;
            Vector4 tangent32 = BuildRMesh.CalculateTangent((b2 - b3).normalized);

            mesh.AddPlane(b3, b2, b3 + wallUp, b2 + wallUp, uv32_min, uv32_max, normal32, tangent32, externalWallSubmesh, opening.surfaceA);

            Vector2 uv13_min  = new Vector2(0, 0);
            Vector2 uv13_max  = new Vector2(opening.size.vy, height);
            Vector3 normal13  = rotation * Vector3.right;
            Vector4 tangent13 = BuildRMesh.CalculateTangent((b3 - b1).normalized);

            mesh.AddPlane(b1, b3, b1 + wallUp, b3 + wallUp, uv13_min, uv13_max, normal13, tangent13, externalWallSubmesh, opening.surfaceA);

            //internal walls
            Vector2 uv20i_min  = new Vector2(wallThickness, 0);
            Vector2 uv20i_max  = new Vector2(opening.size.vy - wallThickness, height);
            Vector3 normal02i  = rotation * Vector3.right;
            Vector4 tangent02i = BuildRMesh.CalculateTangent((b2 - b0).normalized);

            mesh.AddPlane(b0i, b2i, b0i + wallUp, b2i + wallUp, uv20i_min, uv20i_max, normal02i, tangent02i, internalWallSubmesh, opening.surfaceB);

            Vector2 uv32i_min  = new Vector2(0, 0);
            Vector2 uv32i_max  = new Vector2(opening.size.vx - wallThickness, height);
            Vector3 normal32i  = rotation * Vector3.back;
            Vector4 tangent32i = BuildRMesh.CalculateTangent((b3 - b2).normalized);

            mesh.AddPlane(b2i, b3i, b2i + wallUp, b3i + wallUp, uv32i_min, uv32i_max, normal32i, tangent32i, internalWallSubmesh, opening.surfaceB);

            Vector2 uv13i_min  = new Vector2(0, 0);
            Vector2 uv13i_max  = new Vector2(opening.size.vy - wallThickness, height);
            Vector3 normal13i  = rotation * Vector3.left;
            Vector4 tangent13i = BuildRMesh.CalculateTangent((b1 - b3).normalized);

            mesh.AddPlane(b3i, b1i, b3i + wallUp, b1i + wallUp, uv13i_min, uv13i_max, normal13i, tangent13i, internalWallSubmesh, opening.surfaceB);

            if (generateColldier)
            {
                collider.AddPlane(b2, b0, b2 + wallUp, b0 + wallUp);
                collider.AddPlane(b3, b2, b3 + wallUp, b2 + wallUp);
                collider.AddPlane(b1, b3, b1 + wallUp, b3 + wallUp);

                if (!collider.usingPrimitives)
                {
                    collider.mesh.AddPlane(b0i, b2i, b0i + wallUp, b2i + wallUp, 0);
                    collider.mesh.AddPlane(b2i, b3i, b2i + wallUp, b3i + wallUp, 0);
                    collider.mesh.AddPlane(b3i, b1i, b3i + wallUp, b1i + wallUp, 0);
                }
            }


            //door wall

            float internalWallLength = openingSize.vx - (wallThickness * 2f);
            float lerpA = Mathf.Max(stairWidth - doorWidth, 0.05f) / internalWallLength;
            float lerpB = (Mathf.Max(stairWidth - doorWidth, 0.05f) + doorWidth) / internalWallLength;

            Vector2 uvd_b0 = new Vector2(0, 0);
            Vector2 uvd_b1 = new Vector2(opening.size.vx * lerpA, 0);
            Vector2 uvd_b2 = new Vector2(opening.size.vx * lerpB, 0);
            Vector2 uvd_b3 = new Vector2(opening.size.vx, 0);
            Vector2 uvd_m0 = new Vector2(uvd_b0.x, doorHeight);
            Vector2 uvd_m1 = new Vector2(uvd_b1.x, doorHeight);
            Vector2 uvd_m3 = new Vector2(uvd_b3.x, doorHeight);
            Vector2 uvd_t0 = new Vector2(0, height);
            Vector2 uvd_t3 = new Vector2(opening.size.vx, height);

            //internal

            Vector3 bd0i       = Vector3.Lerp(b0i, b1i, lerpA);
            Vector3 bd1i       = Vector3.Lerp(b0i, b1i, lerpB);
            Vector3 normal01i  = rotation * Vector3.forward;
            Vector4 tangent01i = BuildRMesh.CalculateTangent((b0 - b1).normalized);

            Vector3 doorUp = Vector3.up * doorHeight;

            //Right side
            mesh.AddPlane(bd0i, b0i, bd0i + doorUp, b0i + doorUp, uvd_b0, uvd_m1, normal01i, tangent01i, internalWallSubmesh, opening.surfaceB);
            //left side
            mesh.AddPlane(b1i, bd1i, b1i + doorUp, bd1i + doorUp, uvd_b2, uvd_m3, normal01i, tangent01i, internalWallSubmesh, opening.surfaceB);
            //top
            mesh.AddPlane(b1i + doorUp, b0i + doorUp, b1i + wallUp, b0i + wallUp, uvd_m3, uvd_t0, normal01i, tangent01i, internalWallSubmesh, opening.surfaceB);

            //external
            Vector3 doorOut   = -escalationFlatDir * wallThickness;
            Vector3 normal01  = rotation * Vector3.back;
            Vector4 tangent01 = BuildRMesh.CalculateTangent((b1 - b0).normalized);

            //left
            mesh.AddPlane(b0, bd0i + doorOut, b0 + doorUp, bd0i + doorOut + doorUp, uvd_b0, uvd_m1, normal01, tangent01, externalWallSubmesh, opening.surfaceA);
            //right
            mesh.AddPlane(bd1i + doorOut, b1, bd1i + doorOut + doorUp, b1 + doorUp, uvd_b2, uvd_m3, normal01, tangent01, externalWallSubmesh, opening.surfaceA);
            //top
            mesh.AddPlane(b0 + doorUp, b1 + doorUp, b0 + wallUp, b1 + wallUp, uvd_m0, uvd_t3, normal01, tangent01, externalWallSubmesh, opening.surfaceA);

            //frame
            //floor
            mesh.AddPlane(bd1i, bd0i, bd1i + doorOut, bd0i + doorOut, externalWallSubmesh);
            //left
            mesh.AddPlane(bd0i + doorOut, bd0i, bd0i + doorOut + doorUp, bd0i + doorUp, doorFrameSubmesh);
            //right
            mesh.AddPlane(bd1i, bd1i + doorOut, bd1i + doorUp, bd1i + doorOut + doorUp, doorFrameSubmesh);
            //top
            mesh.AddPlane(bd0i + doorUp, bd1i + doorUp, bd0i + doorOut + doorUp, bd1i + doorOut + doorUp, doorFrameSubmesh);

            if (generateColldier)
            {
                collider.AddPlane(b0, bd0i + doorOut, b0 + doorUp, bd0i + doorOut + doorUp);
                collider.AddPlane(bd1i + doorOut, b1, bd1i + doorOut + doorUp, b1 + doorUp);
                collider.AddPlane(b0 + doorUp, b1 + doorUp, b0 + wallUp, b1 + wallUp);

                if (!collider.usingPrimitives)
                {
                    collider.mesh.AddPlane(bd0i, b0i, bd0i + doorUp, b0i + doorUp, 0);
                    collider.mesh.AddPlane(b1i, bd1i, b1i + doorUp, bd1i + doorUp, 0);
                    collider.mesh.AddPlane(b1i + doorUp, b0i + doorUp, b1i + wallUp, b0i + wallUp, 0);

                    collider.mesh.AddPlane(bd1i, bd0i, bd1i + doorOut, bd0i + doorOut, 0);
                    collider.mesh.AddPlane(bd0i + doorOut, bd0i, bd0i + doorOut + doorUp, bd0i + doorUp, 0);
                    collider.mesh.AddPlane(bd1i, bd1i + doorOut, bd1i + doorUp, bd1i + doorOut + doorUp, 0);
                    collider.mesh.AddPlane(bd0i + doorUp, bd1i + doorUp, bd0i + doorOut + doorUp, bd1i + doorOut + doorUp, 0);
                }
            }
        }
예제 #11
0
        public static void GenerateStairs(BuildRMesh mesh, VerticalOpening opening, Vector3 basePosition, float height, int floor, int wallSubmesh = -1, BuildRCollider collider = null)
        {
            bool  stepped          = true;  //todo
            float minimumWidth     = 0.9f;  //UK standard
            float stepHeight       = 0.22f;
            float wallThickness    = VerticalOpening.WALL_THICKNESS;
            bool  generateColldier = collider != null;

            float minimumRunLength   = 0.25f;
            float maximumRiserHeight = 0.2f;

            int internalWallSubmesh  = mesh.submeshLibrary.SubmeshAdd(opening.surfaceB);
            int internalFloorSubmesh = mesh.submeshLibrary.SubmeshAdd(opening.surfaceD);

            bool isBottomFloor = opening.baseFloor == floor;
            bool isTopFloor    = opening.baseFloor + opening.floors == floor;
            //            Debug.Log((opening.baseFloor + opening.floors - 1) +" "+ floor);

            //base positions
            Quaternion rotation    = Quaternion.Euler(0, opening.rotation, 0);
            Vector2Int openingSize = opening.size;
            Vector3    b0          = basePosition + rotation * new Vector3(-opening.size.vx * 0.5f, 0, -opening.size.vy * 0.5f);
            Vector3    b1          = basePosition + rotation * new Vector3(opening.size.vx * 0.5f, 0, -opening.size.vy * 0.5f);
            Vector3    b2          = basePosition + rotation * new Vector3(-opening.size.vx * 0.5f, 0, opening.size.vy * 0.5f);
            Vector3    b3          = basePosition + rotation * new Vector3(opening.size.vx * 0.5f, 0, opening.size.vy * 0.5f);

            //inner points
            Vector3 b0i = b0 + rotation * new Vector3(1, 0, 1) * wallThickness;
            Vector3 b1i = b1 + rotation * new Vector3(-1, 0, 1) * wallThickness;
            Vector3 b2i = b2 + rotation * new Vector3(1, 0, -1) * wallThickness;
            Vector3 b3i = b3 + rotation * new Vector3(-1, 0, -1) * wallThickness;

            Vector2 internalSize    = new Vector2(openingSize.vx - wallThickness * 2, openingSize.vy - wallThickness * 2);
            float   stairWidthFromX = internalSize.x * 0.5f;
            float   stairWidthFromY = internalSize.y - Mathf.Ceil(height / maximumRiserHeight) * minimumRunLength;

            float useLandingWidth = (stairWidthFromX + stairWidthFromY) * 0.5f;

            useLandingWidth = Mathf.Clamp(useLandingWidth, minimumWidth, opening.stairWidth);            //Mathf.Max(stairWidth, internalSize.x * 0.5f));
            float useStairWidth = Mathf.Clamp(opening.stairWidth, minimumWidth, stairWidthFromX);


            float stairRun = internalSize.y - (useLandingWidth * 2);


            Vector3 escalationFlatDir    = (b2i - b0i).normalized;
            Vector3 escalationRight      = (b1i - b0i).normalized;
            Vector3 escalationVector     = new Vector3(stairRun * escalationFlatDir.x, height * 0.5f, stairRun * escalationFlatDir.z);
            Vector3 escalationDirection  = escalationVector.normalized;
            float   escalationHypotenuse = escalationVector.magnitude;
            int     numberOfSteps        = Mathf.CeilToInt((height) / stepHeight);

            Vector3 escalationVectorB    = new Vector3(stairRun * -escalationFlatDir.x, height * 0.5f, stairRun * -escalationFlatDir.z);
            Vector3 escalationDirectionB = escalationVectorB.normalized;

            Vector3 landingDrop  = Vector3.down * wallThickness;
            Vector4 rightTangent = BuildRMesh.CalculateTangent(escalationRight);

            //lower landing
            if (!isBottomFloor)
            {
                Vector3 l0 = b0i;
                Vector3 l1 = b1i;
                Vector3 l2 = b0i + escalationFlatDir * useLandingWidth;
                Vector3 l3 = b1i + escalationFlatDir * useLandingWidth;

                Vector2 maxUVTop  = new Vector2(internalSize.x, useLandingWidth);
                Vector2 maxUVSide = new Vector2(internalSize.x, stepHeight);
                //top
                mesh.AddPlane(l0, l1, l2, l3, Vector3.zero, maxUVTop, Vector3.up, rightTangent, internalFloorSubmesh, opening.surfaceD);
                //bottom
                mesh.AddPlane(l1 + landingDrop, l0 + landingDrop, l3 + landingDrop, l2 + landingDrop, Vector3.zero, maxUVTop, Vector3.down, rightTangent, internalWallSubmesh, opening.surfaceB);
                //front
                mesh.AddPlane(l2, l3, l2 + landingDrop, l3 + landingDrop, escalationFlatDir, maxUVSide, Vector3.up, rightTangent, internalWallSubmesh, opening.surfaceB);

                if (generateColldier)
                {
                    collider.mesh.AddPlane(l0, l1, l2, l3, 0);
                    collider.mesh.AddPlane(l1 + landingDrop, l0 + landingDrop, l3 + landingDrop, l2 + landingDrop, 0);
                    collider.mesh.AddPlane(l2, l3, l2 + landingDrop, l3 + landingDrop, 0);
                }
            }

            if (!isTopFloor)
            {
                //mid landing

                if (true)                //half landed
                {
                    Vector3 up = Vector3.up * height * 0.5f;
                    Vector3 l0 = b2i - escalationFlatDir * useLandingWidth + up;
                    Vector3 l1 = b3i - escalationFlatDir * useLandingWidth + up;
                    Vector3 l2 = b2i + up;
                    Vector3 l3 = b3i + up;

                    Vector2 maxUVTop  = new Vector2(internalSize.x, useLandingWidth);
                    Vector2 maxUVSide = new Vector2(internalSize.x, useLandingWidth);
                    //top
                    mesh.AddPlane(l0, l1, l2, l3, Vector3.zero, maxUVTop, Vector3.up, rightTangent, internalFloorSubmesh, opening.surfaceD);
                    //bottom
                    mesh.AddPlane(l1 + landingDrop, l0 + landingDrop, l3 + landingDrop, l2 + landingDrop, Vector3.zero, maxUVTop, Vector3.down, rightTangent, internalWallSubmesh, opening.surfaceB);
                    //front
                    mesh.AddPlane(l1, l0, l1 + landingDrop, l0 + landingDrop, Vector3.zero, maxUVSide, -escalationFlatDir, rightTangent, internalWallSubmesh, opening.surfaceB);

                    if (generateColldier)
                    {
                        collider.mesh.AddPlane(l0, l1, l2, l3, 0);
                        collider.mesh.AddPlane(l1 + landingDrop, l0 + landingDrop, l3 + landingDrop, l2 + landingDrop, 0);
                        collider.mesh.AddPlane(l1, l0, l1 + landingDrop, l0 + landingDrop, 0);
                    }
                }

                Vector3 flightABaseOutside = b0i + escalationFlatDir * useLandingWidth;
                Vector3 flightABaseInside  = flightABaseOutside + escalationRight * useStairWidth;
                Vector3 flightATopOutside  = flightABaseOutside + escalationDirection * escalationHypotenuse;
                Vector3 flightATopInside   = flightABaseInside + escalationDirection * escalationHypotenuse;
                float   dropThickness      = wallThickness;         //Mathf.Sin(Mathf.Atan2(height, stairRun)) * wallThickness;

                Vector3 flightABaseOutsideDrop = flightABaseOutside + Vector3.down * dropThickness;
                Vector3 flightABaseInsideDrop  = flightABaseInside + Vector3.down * dropThickness;
                Vector3 flightATopOutsideDrop  = flightATopOutside + Vector3.down * dropThickness;
                Vector3 flightATopInsideDrop   = flightATopInside + Vector3.down * dropThickness;

                Vector3 flightBBaseOutside = b3i - escalationFlatDir * useLandingWidth + Vector3.up * height * 0.5f;
                Vector3 flightBBaseInside  = flightBBaseOutside - escalationRight * useStairWidth;
                Vector3 flightBTopOutside  = flightBBaseOutside + escalationDirectionB * escalationHypotenuse;
                Vector3 flightBTopInside   = flightBBaseInside + escalationDirectionB * escalationHypotenuse;

                Vector3 flightBBaseOutsideDrop = flightBBaseOutside + Vector3.down * dropThickness;
                Vector3 flightBBaseInsideDrop  = flightBBaseInside + Vector3.down * dropThickness;
                Vector3 flightBTopOutsideDrop  = flightBTopOutside + Vector3.down * dropThickness;
                Vector3 flightBTopInsideDrop   = flightBTopInside + Vector3.down * dropThickness;

                if (generateColldier)
                {
                    collider.mesh.AddPlane(flightABaseOutside, flightABaseInside, flightATopOutside, flightATopInside, 0);
                    collider.mesh.AddPlane(flightABaseInsideDrop, flightATopInsideDrop, flightABaseInside, flightATopInside, 0);
                    collider.mesh.AddPlane(flightABaseInsideDrop, flightABaseOutsideDrop, flightATopInsideDrop, flightATopOutsideDrop, 0);
                    collider.mesh.AddPlane(flightBBaseOutside, flightBBaseInside, flightBTopOutside, flightBTopInside, 0);
                    collider.mesh.AddPlane(flightBBaseInsideDrop, flightBTopInsideDrop, flightBBaseInside, flightBTopInside, 0);
                    collider.mesh.AddPlane(flightBBaseInsideDrop, flightBBaseOutsideDrop, flightBTopInsideDrop, flightBTopOutsideDrop, 0);
                }

                if (stepped)                //todo, flat generation
                {
                    float stepDepth = stairRun / (numberOfSteps);
                    float skipStep  = (stepDepth / (numberOfSteps - 1));
                    stepDepth += skipStep;
                    float stepRiser = height / numberOfSteps / 2;

                    Vector2 stepUvTopMin  = new Vector2(0, 0);
                    Vector2 stepUvTopMax  = new Vector2(useStairWidth, stepDepth);
                    Vector2 stepUvSideMin = new Vector2(0, 0);
                    Vector2 stepUvSideMax = new Vector2(useStairWidth, stepRiser);

                    //flight one
                    float   lerpIncrement         = 1.0f / (numberOfSteps - 1);
                    Vector3 flightATopOutsideStep = flightATopOutside + Vector3.down * stepHeight * 0.5f;
                    Vector3 flightATopInsideStep  = flightATopInside + Vector3.down * stepHeight * 0.5f;
                    for (int s = 0; s < numberOfSteps - 1; s++)
                    {
                        float   lerpValueAA = lerpIncrement * s;
                        Vector3 s0          = Vector3.Lerp(flightABaseOutside, flightATopOutsideStep, lerpValueAA);
                        Vector3 s1          = Vector3.Lerp(flightABaseInside, flightATopInsideStep, lerpValueAA);
                        Vector3 s2          = s0 + Vector3.up * stepRiser;
                        Vector3 s3          = s1 + Vector3.up * stepRiser;
                        Vector3 s4          = s2 + escalationFlatDir.normalized * stepDepth;
                        Vector3 s5          = s3 + escalationFlatDir.normalized * stepDepth;

                        //front
                        mesh.AddPlane(s0, s1, s2, s3, stepUvSideMin, stepUvSideMax, -escalationFlatDir, rightTangent, internalWallSubmesh, opening.surfaceB);
                        //top
                        mesh.AddPlane(s2, s3, s4, s5, stepUvTopMin, stepUvTopMax, Vector3.up, rightTangent, internalFloorSubmesh, opening.surfaceD);
                        //sides

                        float     lerpValueB = lerpIncrement * s;
                        Vector3   normal = escalationRight;
                        Vector3[] normals = { normal, normal, normal, normal };
                        Vector4   tangent = BuildRMesh.CalculateTangent(escalationFlatDir);
                        Vector4[] tangents = { tangent, tangent, tangent, tangent };
                        Vector3   s8 = Vector3.Lerp(flightABaseInsideDrop, flightATopInsideDrop, lerpValueB);
                        Vector3   s9 = Vector3.Lerp(flightABaseInsideDrop, flightATopInsideDrop, lerpValueB + lerpIncrement);
                        Vector2   uv5, uv3, uv8, uv9;
                        if (opening.surfaceB != null)
                        {
                            uv5 = opening.surfaceB.CalculateUV(new Vector2(s5.z, s5.y));
                            uv3 = opening.surfaceB.CalculateUV(new Vector2(s3.z, s3.y));
                            uv8 = opening.surfaceB.CalculateUV(new Vector2(s8.z, s8.y));
                            uv9 = opening.surfaceB.CalculateUV(new Vector2(s9.z, s9.y));
                        }
                        else
                        {
                            uv5 = new Vector2();
                            uv3 = new Vector2();
                            uv8 = new Vector2();
                            uv9 = new Vector2();
                        }

                        mesh.AddData(new[] { s3, s5, s8, s9 }, new[] { uv3, uv5, uv8, uv9 }, new[] { 0, 1, 2, 2, 1, 3 }, normals, tangents, internalWallSubmesh);

                        if (opening.surfaceB.tiled)
                        {
                            stepUvSideMin.x += 0.11f;
                            stepUvSideMin.y += 0.37f;
                            stepUvSideMax.x += 0.11f;
                            stepUvSideMax.y += 0.37f;
                        }
                        if (opening.surfaceD.tiled)
                        {
                            stepUvTopMin.x += 0.23f;
                            stepUvTopMin.y += 0.13f;
                            stepUvTopMax.x += 0.23f;
                            stepUvTopMax.y += 0.13f;
                        }
                    }
                    mesh.AddPlane(flightABaseInsideDrop, flightABaseOutsideDrop, flightATopInsideDrop, flightATopOutsideDrop, internalWallSubmesh);                    //underside

                    //flight two
                    Vector3 flightBTopOutsideStep = flightBTopOutside + Vector3.down * stepHeight * 0.5f;
                    Vector3 flightBTopInsideStep  = flightBTopInside + Vector3.down * stepHeight * 0.5f;
                    for (int s = 0; s < numberOfSteps - 1; s++)
                    {
                        float   lerpValue = lerpIncrement * s;
                        Vector3 s0        = Vector3.Lerp(flightBBaseOutside, flightBTopOutsideStep, lerpValue);
                        Vector3 s1        = Vector3.Lerp(flightBBaseInside, flightBTopInsideStep, lerpValue);
                        Vector3 s2        = s0 + Vector3.up * stepRiser;
                        Vector3 s3        = s1 + Vector3.up * stepRiser;
                        Vector3 s4        = s2 - escalationFlatDir.normalized * stepDepth;
                        Vector3 s5        = s3 - escalationFlatDir.normalized * stepDepth;
                        //front
                        mesh.AddPlane(s0, s1, s2, s3, stepUvSideMin, stepUvSideMax, escalationFlatDir, rightTangent, internalWallSubmesh, opening.surfaceB);
                        //top
                        mesh.AddPlane(s2, s3, s4, s5, stepUvTopMin, stepUvTopMax, Vector3.up, rightTangent, internalFloorSubmesh, opening.surfaceD);

                        //sides
                        float     lerpValueB = lerpIncrement * s;
                        Vector3   normal = escalationRight;
                        Vector3[] normals = { normal, normal, normal, normal };
                        Vector4   tangent = BuildRMesh.CalculateTangent(escalationFlatDir);
                        Vector4[] tangents = { tangent, tangent, tangent, tangent };
                        Vector3   s8 = Vector3.Lerp(flightBBaseInsideDrop, flightBTopInsideDrop, lerpValueB);
                        Vector3   s9 = Vector3.Lerp(flightBBaseInsideDrop, flightBTopInsideDrop, lerpValueB + lerpIncrement);
                        Vector2   uv5, uv3, uv8, uv9;
                        if (opening.surfaceB != null)
                        {
                            uv5 = opening.surfaceB.CalculateUV(new Vector2(s5.z, s5.y));
                            uv3 = opening.surfaceB.CalculateUV(new Vector2(s3.z, s3.y));
                            uv8 = opening.surfaceB.CalculateUV(new Vector2(s8.z, s8.y));
                            uv9 = opening.surfaceB.CalculateUV(new Vector2(s9.z, s9.y));
                        }
                        else
                        {
                            uv5 = new Vector2();
                            uv3 = new Vector2();
                            uv8 = new Vector2();
                            uv9 = new Vector2();
                        }

                        mesh.AddData(new[] { s3, s5, s8, s9 }, new[] { uv3, uv5, uv8, uv9 }, new[] { 0, 1, 2, 2, 1, 3 }, normals, tangents, internalWallSubmesh);
                    }
                    mesh.AddPlane(flightBBaseInsideDrop, flightBBaseOutsideDrop, flightBTopInsideDrop, flightBTopOutsideDrop, internalWallSubmesh);                    //underside
                }
            }
        }
예제 #12
0
        public static void Generate(IBuilding building, IVolume volume, IFloorplan floorplan, int volumeFloor, VerticalOpening[] openings, BuildRMesh mesh, BuildRCollider collider)
        {
            SubmeshLibrary submeshLibrary = mesh.submeshLibrary;

            bool           generateColliders     = building.colliderType != BuildingColliderTypes.None;
            bool           generateMeshColliders = building.colliderType != BuildingColliderTypes.Primitive && generateColliders;
            BuildRCollider sendCollider          = (generateColliders) ? collider : null;

            collider.thickness = volume.wallThickness;
            if (!generateMeshColliders)
            {
                collider = null;
            }

            float   wallThickness = volume.wallThickness;
            float   wallUp        = volume.floorHeight - wallThickness;
            Vector3 wallUpV       = Vector3.up * wallUp;
            Vector3 floorBaseV    = Vector3.up * volume.baseHeight;

            int roomCount = floorplan.RoomCount;

            int actualFloor  = building.VolumeBaseFloor(volume) + volumeFloor;
            int openingCount = openings.Length;

            bool[]       openingBelow           = new bool[openingCount];
            bool[]       openingAbove           = new bool[openingCount];
            FlatBounds[] openingBounds          = new FlatBounds[openingCount];
            Vector2[][]  openingShapes          = new Vector2[openingCount][];
            bool[]       openingUsedInThisFloor = new bool[openingCount];
            for (int o = 0; o < openingCount; o++)
            {
                VerticalOpening opening = openings[o];
                if (!openings[o].FloorIsIncluded(actualFloor))
                {
                    continue;
                }
                openingBelow[o]  = opening.FloorIsIncluded(actualFloor - 1);
                openingAbove[o]  = opening.FloorIsIncluded(actualFloor + 1);
                openingShapes[o] = opening.PointsRotated();
                openingBounds[o] = new FlatBounds(openingShapes[o]);

                submeshLibrary.Add(opening.surfaceA);
                submeshLibrary.Add(opening.surfaceB);
                submeshLibrary.Add(opening.surfaceC);
                submeshLibrary.Add(opening.surfaceD);
            }

            Dictionary <int, List <Vector2Int> > externalWallAnchors = volume.facadeWallAnchors;

            Room[] rooms = floorplan.AllRooms();
            for (int r = 0; r < roomCount; r++)
            {
                Room room       = rooms[r];
                int  pointCount = room.numberOfPoints;

                Surface floorSurface   = null;
                Surface wallSurface    = null;
                Surface ceilingSurface = null;

                if (room.style != null)
                {
                    RoomStyle style = room.style;
                    floorSurface   = style.floorSurface;
                    wallSurface    = style.wallSurface;
                    ceilingSurface = style.ceilingSurface;
                }

                int floorSubmesh   = submeshLibrary.SubmeshAdd(floorSurface);
                int wallSubmesh    = submeshLibrary.SubmeshAdd(wallSurface);
                int ceilingSubmesh = submeshLibrary.SubmeshAdd(ceilingSurface);

                FloorplanUtil.RoomWall[] walls = FloorplanUtil.CalculatePoints(room, volume);
                Vector2[] roomArchorPoints     = FloorplanUtil.RoomArchorPoints(walls);

                Vector4 tangent = BuildRMesh.CalculateTangent(Vector3.right);

                Vector2[] offsetRoomAnchorPoints = QuickPolyOffset.Execute(roomArchorPoints, wallThickness);

                FlatBounds             roomBounds   = new FlatBounds(offsetRoomAnchorPoints);
                List <Vector2[]>       floorCuts    = new List <Vector2[]>();
                List <Vector2[]>       ceilingCuts  = new List <Vector2[]>();
                List <VerticalOpening> roomOpenings = new List <VerticalOpening>();
                for (int o = 0; o < openingCount; o++)
                {
                    if (openings[o].FloorIsIncluded(actualFloor))
                    {
                        if (roomBounds.Overlaps(openingBounds[o]))
                        {
                            if (CheckShapeWithinRoom(offsetRoomAnchorPoints, openingShapes[o]))
                            {
                                if (openingBelow[o])
                                {
                                    floorCuts.Add(openingShapes[o]);
                                }
                                if (openingAbove[o])
                                {
                                    ceilingCuts.Add(openingShapes[o]);
                                }
                                if (openingAbove[o] || openingBelow[o])
                                {
                                    roomOpenings.Add(openings[o]);
                                    openingUsedInThisFloor[o] = true;
                                }
                            }
                        }
                    }
                }

                int offsetPointBase = 0;
                for (int p = 0; p < pointCount; p++)//generate room walls
                {
                    FloorplanUtil.RoomWall wall = walls[p];
                    int wallPointCount          = wall.offsetPoints.Length;

                    List <RoomPortal> wallPortals = floorplan.GetWallPortals(room, p);
                    int wallPortalCount           = wallPortals.Count;

                    if (!wall.isExternal)
                    {
                        int     indexA    = offsetPointBase;
                        int     indexB    = (offsetPointBase + 1) % roomArchorPoints.Length;
                        Vector2 origBaseA = roomArchorPoints[indexA];
                        Vector2 origBaseB = roomArchorPoints[indexB];
                        Vector2 baseA     = offsetRoomAnchorPoints[indexA];
                        Vector2 baseB     = offsetRoomAnchorPoints[indexB];
                        Vector3 v0        = new Vector3(origBaseA.x, 0, origBaseA.y) + floorBaseV;
                        Vector3 v1        = new Vector3(origBaseB.x, 0, origBaseB.y) + floorBaseV;
                        Vector3 vOffset0  = new Vector3(baseA.x, 0, baseA.y) + floorBaseV;
                        Vector3 vOffset1  = new Vector3(baseB.x, 0, baseB.y) + floorBaseV;
                        if (wallPortalCount == 0)  //just draw the wall - no portals to cut

                        {
                            Vector3 v2 = vOffset1 + wallUpV;
                            Vector3 v3 = vOffset0 + wallUpV;

                            Vector2 minUV = Vector2.zero;
                            Vector2 maxUV = new Vector2(Vector2.Distance(baseA, baseB), wallUp);
                            if (wallSurface != null)
                            {
                                maxUV = wallSurface.CalculateUV(maxUV);
                            }
                            Vector3 wallDir     = (vOffset0 - vOffset1).normalized;
                            Vector3 wallNormal  = Vector3.Cross(Vector3.up, wallDir);
                            Vector4 wallTangent = BuildRMesh.CalculateTangent(wallDir);
                            mesh.AddPlane(vOffset1, vOffset0, v2, v3, minUV, maxUV, wallNormal, wallTangent, wallSubmesh, wallSurface);

                            if (generateColliders)
                            {
                                collider.AddPlane(vOffset1, vOffset0, v2, v3);
                            }
                        }
                        else
                        {
                            List <float> useLaterals = new List <float>();
                            List <bool>  hasPortals  = new List <bool>();
                            for (int wp = 0; wp < wallPortalCount; wp++)
                            {
                                RoomPortal portal    = wallPortals[wp];
                                bool       hasPortal = room.HasPortal(portal);
                                hasPortals.Add(hasPortal);
                                if (hasPortal)
                                {
                                    useLaterals.Add(portal.lateralPosition);
                                }
                                else
                                {
                                    useLaterals.Add(1 - portal.lateralPosition);//portal from other wall - wall orientation is flipped
                                }
                            }

                            Vector3 wallVector               = vOffset1 - vOffset0;
                            Vector3 wallDirection            = wallVector.normalized;
                            Vector3 wallStart                = vOffset0;
                            Vector4 wallTangent              = BuildRMesh.CalculateTangent(wallDirection);
                            Vector3 wallNormal               = Vector3.Cross(Vector3.up, wallDirection);
                            Vector4 wallNormalTangent        = BuildRMesh.CalculateTangent(wallNormal);
                            Vector4 wallNormalTangentReverse = BuildRMesh.CalculateTangent(-wallNormal);

                            while (wallPortalCount > 0)
                            {
                                int        portalIndex = 0;
                                RoomPortal usePortal   = wallPortals[0];
                                float      lowestLat   = useLaterals[0];
                                for (int wp = 1; wp < wallPortalCount; wp++)
                                {
                                    if (useLaterals[wp] < lowestLat)
                                    {
                                        portalIndex = wp;
                                        usePortal   = wallPortals[wp];
                                        lowestLat   = useLaterals[wp];
                                    }
                                }

                                wallPortals.RemoveAt(portalIndex);
                                useLaterals.RemoveAt(portalIndex);
                                wallPortalCount--;

                                Vector3 vl0 = v0 + (-wallNormal + wallDirection) * wallThickness;
                                Vector3 vl1 = v1 + (-wallNormal - wallDirection) * wallThickness;

                                Vector3 portalCenter     = Vector3.Lerp(vl0, vl1, lowestLat);
                                Vector3 portalHalfvector = wallDirection * (usePortal.width * 0.5f);
                                Vector3 portalBase       = Vector3.up * (volume.floorHeight - usePortal.height) * usePortal.verticalPosition;
                                Vector3 portalUp         = portalBase + Vector3.up * usePortal.height;
                                Vector3 portalStart      = portalCenter - portalHalfvector;
                                Vector3 portalEnd        = portalCenter + portalHalfvector;

                                Vector2 initalWallUVMin = new Vector2(Vector3.Dot(portalStart, wallDirection), 0);
                                Vector2 initalWallUVMax = new Vector2(Vector3.Dot(wallStart, wallDirection), wallUp);
                                mesh.AddPlane(portalStart, wallStart, portalStart + wallUpV, wallStart + wallUpV, initalWallUVMin, initalWallUVMax, wallNormal, wallTangent, wallSubmesh, wallSurface);//initial wall
                                if (generateColliders)
                                {
                                    collider.AddPlane(portalStart, wallStart, portalStart + wallUpV, wallStart + wallUpV);
                                }
                                if (usePortal.verticalPosition > 0)
                                {
                                    Vector2 portalBaseUVMin = new Vector2(Vector3.Dot(portalEnd, wallDirection), 0);
                                    Vector2 portalBaseUVMax = new Vector2(Vector3.Dot(portalStart, wallDirection), portalBase.y);
                                    mesh.AddPlane(portalEnd, portalStart, portalEnd + portalBase, portalStart + portalBase, portalBaseUVMin, portalBaseUVMax, wallNormal, wallTangent, wallSubmesh, wallSurface);//bottom
                                    if (generateColliders)
                                    {
                                        collider.AddPlane(portalEnd, portalStart, portalEnd + portalBase, portalStart + portalBase);
                                    }
                                }
                                if (usePortal.verticalPosition < 1)
                                {
                                    Vector2 portalBaseUVMin = new Vector2(Vector3.Dot(portalEnd, wallDirection), portalUp.y);
                                    Vector2 portalBaseUVMax = new Vector2(Vector3.Dot(portalStart, wallDirection), wallUp);
                                    mesh.AddPlane(portalEnd + portalUp, portalStart + portalUp, portalEnd + wallUpV, portalStart + wallUpV, portalBaseUVMin, portalBaseUVMax, wallNormal, wallTangent, wallSubmesh, wallSurface);//top
                                    if (generateColliders)
                                    {
                                        collider.AddPlane(portalEnd + portalUp, portalStart + portalUp, portalEnd + wallUpV, portalStart + wallUpV);
                                    }
                                }

                                if (hasPortals[portalIndex])//only do this once - from the room it's attached to
                                {
                                    //portal interior frame
                                    Vector3 portalDepth = wallNormal * wallThickness * 2;

                                    //sides
                                    mesh.AddPlane(portalStart + portalDepth + portalBase, portalStart + portalBase, portalStart + portalDepth + portalUp, portalStart + portalUp, wallDirection, wallNormalTangentReverse, wallSubmesh);
                                    mesh.AddPlane(portalEnd + portalBase, portalEnd + portalDepth + portalBase, portalEnd + portalUp, portalEnd + portalDepth + portalUp, -wallDirection, wallNormalTangent, wallSubmesh);

                                    if (generateMeshColliders)
                                    {
                                        collider.AddPlane(portalStart + portalDepth + portalBase, portalStart + portalBase, portalStart + portalDepth + portalUp, portalStart + portalUp);
                                        collider.AddPlane(portalEnd + portalBase, portalEnd + portalDepth + portalBase, portalEnd + portalUp, portalEnd + portalDepth + portalUp);
                                    }

                                    //floor
                                    Vector2 minFloorUv = new Vector2((portalEnd + portalBase).z, (portalEnd + portalBase).x);
                                    Vector2 maxFloorUv = minFloorUv + new Vector2(wallThickness, usePortal.width);
                                    mesh.AddPlane(portalStart + portalBase, portalStart + portalDepth + portalBase, portalEnd + portalBase, portalEnd + portalDepth + portalBase, minFloorUv, maxFloorUv, Vector3.up, wallTangent, floorSubmesh, floorSurface);
                                    if (generateMeshColliders)
                                    {
                                        collider.AddPlane(portalStart + portalBase, portalStart + portalDepth + portalBase, portalEnd + portalBase, portalEnd + portalDepth + portalBase);
                                    }

                                    //ceiling
                                    mesh.AddPlane(portalEnd + portalUp, portalEnd + portalDepth + portalUp, portalStart + portalUp, portalStart + portalDepth + portalUp, Vector3.down, wallTangent, wallSubmesh);
                                    if (generateMeshColliders)
                                    {
                                        collider.AddPlane(portalEnd + portalUp, portalEnd + portalDepth + portalUp, portalStart + portalUp, portalStart + portalDepth + portalUp);
                                    }
                                }

                                wallStart = portalEnd;//move the start for the next calculation
                            }

                            Vector2 finalWallUVMin = new Vector2(Vector3.Dot(vOffset1, wallDirection), 0);
                            Vector2 finalWallUVMax = new Vector2(Vector3.Dot(wallStart, wallDirection), wallUp);
                            mesh.AddPlane(vOffset1, wallStart, vOffset1 + wallUpV, wallStart + wallUpV, finalWallUVMin, finalWallUVMax, wallNormal, wallTangent, wallSubmesh, wallSurface);//final wall section
                            if (generateColliders)
                            {
                                collider.AddPlane(vOffset1, wallStart, vOffset1 + wallUpV, wallStart + wallUpV);
                            }
                        }
                        offsetPointBase += 1;
                    }
                    else//external anchored wall
                    {
                        int    facadeIndex  = wall.facadeIndex;
                        Facade facadeDesign = volume.GetFacade(facadeIndex);
                        int    currentFacadeWallSectionLength = externalWallAnchors[facadeIndex].Count - 1;
                        int    currentWallSectionIndex        = wall.offsetPointWallSection[0];
                        int    wallOffsetPoints = wall.offsetPoints.Length;
                        for (int w = 0; w < wallOffsetPoints - 1; w++)
                        {
                            int     roomPointIndex   = offsetPointBase + w;
                            Vector2 baseA            = offsetRoomAnchorPoints[roomPointIndex];
                            int     offsetIndexB     = (roomPointIndex + 1) % offsetRoomAnchorPoints.Length;
                            Vector2 baseB            = offsetRoomAnchorPoints[offsetIndexB];
                            Vector3 v0               = new Vector3(baseA.x, 0, baseA.y) + floorBaseV;
                            Vector3 v1               = new Vector3(baseB.x, 0, baseB.y) + floorBaseV;
                            int     wallSectionIndex = wall.offsetPointWallSection[w];

                            bool canGenerateWallSection = facadeDesign != null;

                            Vector3 wallVector = v0 - v1;
                            Vector3 wallDir    = wallVector.normalized;
                            float   wallLength = wallVector.magnitude;

                            if (!canGenerateWallSection)
                            {
                                if (wallSurface != null)
                                {
                                    submeshLibrary.Add(wallSurface);
                                }

                                Vector3 v2 = v1 + wallUpV;
                                Vector3 v3 = v0 + wallUpV;

                                Vector2 minUV       = Vector2.zero;
                                Vector2 maxUV       = new Vector2(Vector2.Distance(baseA, baseB), wallUp);
                                Vector3 wallNormal  = Vector3.Cross(Vector3.up, wallDir);
                                Vector4 wallTangent = BuildRMesh.CalculateTangent(wallDir);
                                mesh.AddPlane(v1, v0, v2, v3, minUV, maxUV, wallNormal, wallTangent, wallSubmesh, wallSurface);

                                if (generateMeshColliders)
                                {
                                    collider.AddPlane(v1, v0, v2, v3);
                                }
                            }
                            else
                            {
                                WallSection section = facadeDesign.GetWallSection(wallSectionIndex, volumeFloor, currentFacadeWallSectionLength, volume.floors);
                                if (section.model != null)
                                {
                                    continue;//cannot account for custom meshes assume custom mesh does include interior mesh or if does - will be generated with the exterior
                                }
                                GenerationOutput generatedSection = GenerationOutput.CreateRawOutput();
                                Vector2          wallSectionSize  = new Vector2(wallLength, wallUp + wallThickness);
                                bool             cullOpening      = building.cullDoors && section.isDoor;
                                SubmeshLibrary   sectionLib       = new SubmeshLibrary();

                                if (wallSurface != null)
                                {
                                    sectionLib.Add(wallSurface);//add interior wall surface
                                    submeshLibrary.Add(wallSurface);
                                }

                                sectionLib.Add(section.openingSurface);//add windows - the only surface we'll use in the interior room
                                submeshLibrary.Add(section.openingSurface);

                                float offset = 0;
                                if (w == 0)
                                {
                                    offset = wallThickness;
                                }
                                if (w == wallOffsetPoints - 2)
                                {
                                    offset = -wallThickness;
                                }
                                WallSectionGenerator.Generate(section, generatedSection, wallSectionSize, true, wallThickness, cullOpening, null, sectionLib, offset);
                                int[]   mapping     = submeshLibrary.MapSubmeshes(generatedSection.raw.materials);
                                Vector3 curveNormal = Vector3.Cross(wallDir, Vector3.up);

                                Quaternion meshRot = Quaternion.LookRotation(curveNormal, Vector3.up);
                                Vector3    meshPos = new Vector3(v1.x, volume.baseHeight, v1.z) + wallDir * wallSectionSize.x + Vector3.up * wallSectionSize.y;
                                meshPos += meshRot * -new Vector3(wallSectionSize.x, wallSectionSize.y, 0) * 0.5f;
                                mesh.AddData(generatedSection.raw, mapping, meshPos, meshRot, Vector3.one);
                            }


                            currentWallSectionIndex++;
                            if (currentWallSectionIndex >= currentFacadeWallSectionLength)
                            {
                                //reached the end of the facade - move to the next one and continue
                                currentFacadeWallSectionLength = externalWallAnchors[facadeIndex].Count;
                                currentWallSectionIndex        = 0;
                            }
                        }

                        offsetPointBase += wallPointCount - 1;
                    }
                }

                //FLOOR
                Vector2[]   mainShape      = offsetRoomAnchorPoints;
                Vector2[][] floorCutPoints = floorCuts.ToArray();
                int         floorVertCount = mainShape.Length;
                for (int flc = 0; flc < floorCutPoints.Length; flc++)
                {
                    floorVertCount += floorCutPoints[flc].Length;
                }

                Vector2[] allFloorPoints  = new Vector2[floorVertCount];
                int       mainShapeLength = mainShape.Length;
                for (int ms = 0; ms < mainShapeLength; ms++)
                {
                    allFloorPoints[ms] = mainShape[ms];
                }
                int cutPointIterator = mainShapeLength;
                for (int flc = 0; flc < floorCutPoints.Length; flc++)
                {
                    for (int flcp = 0; flcp < floorCutPoints[flc].Length; flcp++)
                    {
                        allFloorPoints[cutPointIterator] = floorCutPoints[flc][flcp];
                        cutPointIterator++;
                    }
                }

                Vector3[] floorPoints   = new Vector3[floorVertCount];
                Vector2[] floorUvs      = new Vector2[floorVertCount];
                Vector3[] floorNorms    = new Vector3[floorVertCount];
                Vector4[] floorTangents = new Vector4[floorVertCount];
                for (int rp = 0; rp < floorVertCount; rp++)
                {
                    floorPoints[rp] = new Vector3(allFloorPoints[rp].x, 0, allFloorPoints[rp].y) + floorBaseV;
                    Vector2 uv = allFloorPoints[rp];
                    if (floorSurface != null)
                    {
                        uv = floorSurface.CalculateUV(uv);
                    }
                    floorUvs[rp]      = uv;
                    floorNorms[rp]    = Vector3.up;
                    floorTangents[rp] = tangent;
                }

                int[] tris = Poly2TriWrapper.Triangulate(mainShape, true, floorCutPoints);

                mesh.AddData(floorPoints, floorUvs, tris, floorNorms, floorTangents, floorSubmesh);
                if (generateColliders)
                {
                    collider.mesh.AddData(floorPoints, floorUvs, tris, floorNorms, floorTangents, 0);
                }

                //CEILING!
                Vector2[][] ceilingCutPoints = ceilingCuts.ToArray();
                int         ceilingVertCount = mainShape.Length;
                for (int flc = 0; flc < ceilingCutPoints.Length; flc++)
                {
                    ceilingVertCount += ceilingCutPoints[flc].Length;
                }

                Vector2[] allCeilingPoints = new Vector2[ceilingVertCount];
                for (int ms = 0; ms < mainShapeLength; ms++)
                {
                    allCeilingPoints[ms] = mainShape[ms];
                }
                cutPointIterator = mainShapeLength;
                for (int flc = 0; flc < ceilingCutPoints.Length; flc++)
                {
                    for (int flcp = 0; flcp < ceilingCutPoints[flc].Length; flcp++)
                    {
                        allCeilingPoints[cutPointIterator] = ceilingCutPoints[flc][flcp];
                        cutPointIterator++;
                    }
                }

                Vector3[] ceilingPoints   = new Vector3[ceilingVertCount];
                Vector2[] ceilingUvs      = new Vector2[ceilingVertCount];
                Vector3[] ceilingNorms    = new Vector3[ceilingVertCount];
                Vector4[] ceilingTangents = new Vector4[ceilingVertCount];
                for (int rp = 0; rp < ceilingVertCount; rp++)
                {
                    ceilingPoints[rp] = new Vector3(allCeilingPoints[rp].x, wallUp, allCeilingPoints[rp].y) + floorBaseV;
                    Vector2 uv = allCeilingPoints[rp];
                    if (floorSurface != null)
                    {
                        uv = ceilingSurface.CalculateUV(uv);
                    }
                    ceilingUvs[rp]      = uv;
                    ceilingNorms[rp]    = Vector3.down;
                    ceilingTangents[rp] = tangent;
                }

                tris = Poly2TriWrapper.Triangulate(mainShape, false, ceilingCutPoints);
                mesh.AddData(ceilingPoints, ceilingUvs, tris, ceilingNorms, ceilingTangents, ceilingSubmesh);
                if (generateColliders)
                {
                    collider.mesh.AddData(ceilingPoints, ceilingUvs, tris, ceilingNorms, ceilingTangents, 0);
                }

                for (int ob = 0; ob < openingCount; ob++)
                {
                    VerticalOpening opening      = openings[ob];
                    int             openingIndex = Array.IndexOf(openings, opening);
                    Vector3         basePosition = openingBounds[openingIndex].center;
                    basePosition.z = basePosition.y;
                    basePosition.y = volume.baseHeight;

                    if (roomOpenings.Contains(opening))//opening used in this floorplan
                    {
                        int externalWallSubmesh = wallSubmesh != -1 ? wallSubmesh : -1;
                        switch (opening.usage)
                        {
                        case VerticalOpening.Usages.Space:
                            if (ceilingCutPoints.Length <= ob)
                            {
                                continue;
                            }
                            Vector3   ceilingCutUpV = Vector3.up * wallThickness;
                            Vector2[] ceilingCut    = ceilingCutPoints[ob];
                            int       custSize      = ceilingCut.Length;
                            for (int cp = 0; cp < custSize; cp++)
                            {
                                int     indexA = (cp + 1) % custSize;
                                int     indexB = cp;
                                Vector3 cp0    = new Vector3(ceilingCut[indexA].x, wallUp, ceilingCut[indexA].y) + floorBaseV;
                                Vector3 cp1    = new Vector3(ceilingCut[indexB].x, wallUp, ceilingCut[indexB].y) + floorBaseV;
                                Vector3 cp2    = cp0 + ceilingCutUpV;
                                Vector3 cp3    = cp1 + ceilingCutUpV;
                                mesh.AddPlane(cp0, cp1, cp2, cp3, ceilingSubmesh);
                                if (generateColliders)
                                {
                                    collider.AddPlane(cp0, cp1, cp2, cp3);
                                }
                            }
                            break;

                        case VerticalOpening.Usages.Stairwell:
                            StaircaseGenerator.Generate(mesh, opening, basePosition, volume.floorHeight, actualFloor, externalWallSubmesh, sendCollider);
                            if (volumeFloor == volume.floors - 1 && opening.baseFloor + opening.floors > building.VolumeBaseFloor(volume) + volume.floors - 1 && volume.abovePlanCount == 0)
                            {
                                StaircaseGenerator.GenerateRoofAccess(mesh, opening, basePosition, volume.floorHeight, actualFloor, externalWallSubmesh, sendCollider);
                            }
                            break;

                        case VerticalOpening.Usages.Elevator:
                            ElevatorShaftGenerator.Generate(ref mesh, opening, actualFloor, basePosition, volume.floorHeight, externalWallSubmesh, sendCollider);
                            break;
                        }
                    }
                }
            }

            for (int ob = 0; ob < openingCount; ob++)
            {
                Vector2[] openingShape = openingShapes[ob];
                if (openingShape == null)
                {
                    continue;                      //opening not used by this floorplan
                }
                if (openingUsedInThisFloor[ob])
                {
                    continue;                            //opening already generated
                }
                //seal this opening from the void
                VerticalOpening opening      = openings[ob];
                int             openingIndex = Array.IndexOf(openings, opening);
                Vector3         basePosition = openingBounds[openingIndex].center;
                basePosition.z = basePosition.y;
                basePosition.y = 0;

                int       cutSize            = openingShape.Length;
                Vector3   sealingWallUpV     = Vector3.up * volume.floorHeight;
                int       sealWallSubmesh    = submeshLibrary.SubmeshAdd(opening.surfaceB);
                Vector2[] offsetOpeningShape = QuickPolyOffset.Execute(openingShape, wallThickness);
                for (int cp = 0; cp < cutSize; cp++)
                {
                    int     indexA = (cp + 1) % cutSize;
                    int     indexB = cp;
                    Vector2 p0     = opening.usage == VerticalOpening.Usages.Space ? openingShape[indexA] : offsetOpeningShape[indexA];
                    Vector2 p1     = opening.usage == VerticalOpening.Usages.Space ? openingShape[indexB] : offsetOpeningShape[indexB];
                    Vector3 cp0    = new Vector3(p0.x, 0, p0.y) + floorBaseV;
                    Vector3 cp1    = new Vector3(p1.x, 0, p1.y) + floorBaseV;
                    Vector3 cp2    = cp0 + sealingWallUpV;
                    Vector3 cp3    = cp1 + sealingWallUpV;
                    mesh.AddPlane(cp0, cp1, cp2, cp3, sealWallSubmesh);
                    if (generateColliders)
                    {
                        collider.AddPlane(cp0, cp1, cp2, cp3);
                    }
                }

                switch (opening.usage)
                {
                case VerticalOpening.Usages.Space:
                    //nothing to implement
                    break;

                case VerticalOpening.Usages.Stairwell:
                    //need stairs to connect used floors
                    StaircaseGenerator.GenerateStairs(mesh, opening, basePosition, volume.floorHeight, actualFloor, -1, sendCollider);
                    if (volumeFloor == volume.floors - 1)
                    {
                        StaircaseGenerator.GenerateRoofAccess(mesh, opening, basePosition, volume.floorHeight, actualFloor, -1, sendCollider);
                    }
                    break;

                case VerticalOpening.Usages.Elevator:
                    //nothing to implement
                    break;
                }
            }
        }
예제 #13
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));
                            }
                        }
                    }
                }
            }
        }
예제 #14
0
        public static void Generate(ref BuildRMesh mesh, VerticalOpening opening, int actualFloor, Vector3 basePosition, float height, int wallSubmesh = -1, BuildRCollider collider = null)
        {
            //            bool lowerLanding = true;
            //            float wallDepth = 0.5f;//todo
            bool  generateColldier = collider != null;
            float wallThickness    = VerticalOpening.WALL_THICKNESS;

            if (collider != null)
            {
                collider.thickness = VerticalOpening.WALL_THICKNESS;
            }
//            bool generateMeshCollider = generateColldier && !collider.usingPrimitives;

            SubmeshLibrary submeshLibrary      = mesh.submeshLibrary;
            int            externalWallSubmesh = submeshLibrary.SubmeshAdd(opening.surfaceA);
            int            internalWallSubmesh = submeshLibrary.SubmeshAdd(opening.surfaceB);
            int            doorFrameSubmesh    = submeshLibrary.SubmeshAdd(opening.surfaceC);

            if (wallSubmesh != -1)
            {
                externalWallSubmesh = wallSubmesh;
            }
            if (externalWallSubmesh == -1)
            {
                externalWallSubmesh = 0;
            }
            if (internalWallSubmesh == -1)
            {
                internalWallSubmesh = 0;
            }
            if (doorFrameSubmesh == -1)
            {
                doorFrameSubmesh = 0;
            }

            //base positions
            Quaternion rotation = Quaternion.Euler(0, opening.rotation, 0);
//            Vector2Int openingSize = opening.size;
            Vector3 b0 = basePosition + rotation * new Vector3(-opening.size.vx * 0.5f, 0, -opening.size.vy * 0.5f);
            Vector3 b1 = basePosition + rotation * new Vector3(opening.size.vx * 0.5f, 0, -opening.size.vy * 0.5f);
            Vector3 b2 = basePosition + rotation * new Vector3(-opening.size.vx * 0.5f, 0, opening.size.vy * 0.5f);
            Vector3 b3 = basePosition + rotation * new Vector3(opening.size.vx * 0.5f, 0, opening.size.vy * 0.5f);

            //inner points
            Vector3 b0i = b0 + rotation * new Vector3(1, 0, 1) * wallThickness;
            Vector3 b1i = b1 + rotation * new Vector3(-1, 0, 1) * wallThickness;
            Vector3 b2i = b2 + rotation * new Vector3(1, 0, -1) * wallThickness;
            Vector3 b3i = b3 + rotation * new Vector3(-1, 0, -1) * wallThickness;

            //walls
            Vector3 wallUpInternal = Vector3.up * height;
            Vector3 wallUpExternal = Vector3.up * height;

            wallUpExternal.y += -wallThickness * 0.5f;
            //external
            mesh.AddPlane(b2, b0, b2 + wallUpExternal, b0 + wallUpExternal, externalWallSubmesh);
            mesh.AddPlane(b3, b2, b3 + wallUpExternal, b2 + wallUpExternal, externalWallSubmesh);
            mesh.AddPlane(b1, b3, b1 + wallUpExternal, b3 + wallUpExternal, externalWallSubmesh);
            //internal
            mesh.AddPlane(b0i, b2i, b0i + wallUpInternal, b2i + wallUpInternal, internalWallSubmesh);
            mesh.AddPlane(b2i, b3i, b2i + wallUpInternal, b3i + wallUpInternal, internalWallSubmesh);
            mesh.AddPlane(b3i, b1i, b3i + wallUpInternal, b1i + wallUpInternal, internalWallSubmesh);

            //door
            Vector3 b0d    = b0 + rotation * (Vector3.right * opening.size.vx * 0.15f);
            Vector3 b1d    = b1 + rotation * (Vector3.left * opening.size.vx * 0.15f);
            Vector3 doorUp = wallUpInternal * 0.85f;

            //external
            mesh.AddPlane(b0, b0d, b0 + doorUp, b0d + doorUp, externalWallSubmesh);
            mesh.AddPlane(b1d, b1, b1d + doorUp, b1 + doorUp, externalWallSubmesh);
            mesh.AddPlane(b0 + doorUp, b1 + doorUp, b0 + wallUpExternal, b1 + wallUpExternal, externalWallSubmesh);
            //internal
            Vector3 doorFrameV = rotation * new Vector3(0, 0, 1) * wallThickness;

            mesh.AddPlane(b1i, b1d + doorFrameV, b1i + doorUp, b1d + doorFrameV + doorUp, internalWallSubmesh);
            mesh.AddPlane(b0d + doorFrameV, b0i, b0d + doorFrameV + doorUp, b0i + doorUp, internalWallSubmesh);
            mesh.AddPlane(b1i + doorUp, b0i + doorUp, b1i + wallUpInternal, b0i + wallUpInternal, internalWallSubmesh);

            //door frame
            mesh.AddPlane(b0d, b1d, b0d + doorFrameV, b1d + doorFrameV, doorFrameSubmesh);
            mesh.AddPlane(b0d, b0d + doorFrameV, b0d + doorUp, b0d + doorFrameV + doorUp, doorFrameSubmesh);
            mesh.AddPlane(b1d + doorFrameV, b1d, b1d + doorFrameV + doorUp, b1d + doorUp, doorFrameSubmesh);
            mesh.AddPlane(b0d + doorFrameV + doorUp, b1d + doorFrameV + doorUp, b0d + doorUp, b1d + doorUp, doorFrameSubmesh);

            if (generateColldier)
            {
                collider.AddPlane(b2, b0, b2 + wallUpExternal, b0 + wallUpExternal);
                collider.AddPlane(b3, b2, b3 + wallUpExternal, b2 + wallUpExternal);
                collider.AddPlane(b1, b3, b1 + wallUpExternal, b3 + wallUpExternal);

                collider.AddPlane(b0, b0d, b0 + doorUp, b0d + doorUp);
                collider.AddPlane(b1d, b1, b1d + doorUp, b1 + doorUp);
                collider.AddPlane(b0 + doorUp, b1 + doorUp, b0 + wallUpExternal, b1 + wallUpExternal);

                if (!collider.usingPrimitives)
                {
                    collider.mesh.AddPlane(b0i, b2i, b0i + wallUpInternal, b2i + wallUpInternal, 0);
                    collider.mesh.AddPlane(b2i, b3i, b2i + wallUpInternal, b3i + wallUpInternal, 0);
                    collider.mesh.AddPlane(b3i, b1i, b3i + wallUpInternal, b1i + wallUpInternal, 0);

                    collider.mesh.AddPlane(b1i, b1d + doorFrameV, b1i + doorUp, b1d + doorFrameV + doorUp, 0);
                    collider.mesh.AddPlane(b0d + doorFrameV, b0i, b0d + doorFrameV + doorUp, b0i + doorUp, 0);
                    collider.mesh.AddPlane(b1i + doorUp, b0i + doorUp, b1i + wallUpInternal, b0i + wallUpInternal, 0);

                    collider.mesh.AddPlane(b0d, b1d, b0d + doorFrameV, b1d + doorFrameV, 0);
                    collider.mesh.AddPlane(b0d, b0d + doorFrameV, b0d + doorUp, b0d + doorFrameV + doorUp, 0);
                    collider.mesh.AddPlane(b1d + doorFrameV, b1d, b1d + doorFrameV + doorUp, b1d + doorUp, 0);
                    collider.mesh.AddPlane(b0d + doorFrameV + doorUp, b1d + doorFrameV + doorUp, b0d + doorUp, b1d + doorUp, 0);
                }
            }
        }
예제 #15
0
        public static VerticalOpening[] GetOpenings(Building building, Volume volume)
        {
            List <VerticalOpening> output = new List <VerticalOpening>();
            int count = building.openingCount;

            VerticalOpening[] openings = building.GetAllOpenings();

            int volumeBaseFloor = building.VolumeBaseFloor(volume);
            int volumeTopFloor  = volumeBaseFloor + volume.floors;

            for (int i = 0; i < count; i++)
            {
                VerticalOpening opening          = openings[i];
                int             openingBaseFloor = opening.baseFloor;
                int             openingTopFloor  = openingBaseFloor + opening.floors - 1;

                if (volumeBaseFloor < openingTopFloor && openingBaseFloor < volumeTopFloor)//opening and volume floors intersect
                {
                    FlatBounds volumeBounds  = new FlatBounds(volume.bounds);
                    Vector2[]  openingPoints = opening.PointsRotated();
                    FlatBounds openingBounds = new FlatBounds(openingPoints);

                    if (volumeBounds.Overlaps(openingBounds, true))// opening is within the AABB bounds of the volume
                    {
                        Vector2[] volumePoints      = volume.AllPointsV2();
                        int       volumePointCount  = volumePoints.Length;
                        int       openingPointCount = openingPoints.Length;
                        bool      openingIntersects = false;

                        for (int op = 0; op < openingPointCount; op++)
                        {
                            Vector2 opa = openingPoints[op];
                            Vector2 opb = openingPoints[(op + 1) % openingPointCount];

                            for (int vp = 0; vp < volumePointCount; vp++)
                            {
                                Vector2 vpa = volumePoints[vp];
                                Vector2 vpb = volumePoints[(vp + 1) % volumePointCount];

                                if (FastLineIntersection(opa, opb, vpa, vpb))
                                {
                                    openingIntersects = true;
                                }

                                if (openingIntersects)
                                {
                                    break;
                                }
                            }

                            if (openingIntersects)
                            {
                                break;
                            }
                        }

                        if (!openingIntersects)//check that the opening is within the volume shape
                        {
                            Vector2 opa           = openingPoints[0];
                            Vector2 opb           = openingPoints[1];
                            int     intersections = 0;//we should intersect an odd number of times
                            for (int vp = 0; vp < volumePointCount; vp++)
                            {
                                Vector2 vpa = volumePoints[vp];
                                Vector2 vpb = volumePoints[(vp + 1) % volumePointCount];

                                if (FastLineIntersection(opa, opb, vpa, vpb))
                                {
                                    intersections++;
                                }
                            }

                            if (intersections % 2 != 0)
                            {
                                output.Add(opening);
                            }
                        }
                    }
                }
            }
            return(output.ToArray());
        }