random building placement
Blitz3D Forums/Blitz3D Beginners Area/random building placement
| ||
Hi Guys, Ive been wracking my head over this problem for what seems ages now. My program creates a random city map, a 64x64 grid, each block on the grid is either assigned to be a road segment or building. The system is working pretty well and produces some nice random cities, the problem is, there are too many buildings and i would like to place the buildings only around the perimeter of the roads. At present the buildings all have the same footprint size but im working on a random building generator that will create random building sizes, shapes and footprint sizes. I want to be able to generate a percentage of big, medium and small buildings and to scatter them around the map, but only place them at the road side. Hope this makes sense. If anyone has any ideas, let me know. Sorry forgot to mention, the map is stored in an array, with verticle roads, horizontal roads, crossroads, building etc all having a code. Thanks. |
| ||
I have thought about how to generate a random city with random buildings and random roads, and i think that using a grid to position the buildings can be a good appraoch but it is too easy ;) I think another approach is to first create the roads and then create the buildings around the roads. After having created the roads, it is possible to determine the empty space between some roads depending on the width and length of the roads. I have not done it yet but i think it could work. Concerning the procedural modeling of a building, i think that the more sensible approach is to know which possible parts to use and in which place depending on the building kind, and add the parts as if it was builders who were creating the structure. For example, pick randomly a part in a group of parts depending on the kind of the building. (residence, industry, shop, administration, school, etc...) It does not answer your question but it can give you some ideas about the subject. |
| ||
The way I see it, your problem is 2-fold. 1) Place buildings ONLY on locations that are adjacent to roads 2) Ensure building footprints do not overlap onto the road or each other Are all the roads the same width? And are all building footprints square?For now, I will assume they are and this should make things a lot easier. Const ARRAY_SIZE=64 Const EMPTY=0 Const BUILDING=1 Const ROAD=2 Const ROAD_HORIZONTAL=6 Const ROAD_VERTICAL=10 Const ROAD_CROSSROAD=18 ;Dim Array(ARRAY_SIZE,ARRAY_SIZE) Function PlaceBuilding() Local X Local Y Local Grid Local Placed=False While (Not(Placed)) ;Choose random location X=Rand(0,ARRAY_SIZE-1) Y=Rand(0,ARRAY_SIZE-1) Grid=Array(X,Y) Select (Grid) ;Only Select road locations, we can then place buildings at the edge fo these Case VERTICAL_ROAD: Placed=PlaceAtVertical(X,Y) Case HORIZONTAL_ROAD: Placed=PlaceAtHorizontal(X,Y) Case CROSSROAD: Placed=PlaceAtCrossroads(X,Y) End Select Wend End Function Function PlaceAtCrossroads(X,Y) ;Assume Crossroad corners should be available Local Grid For PY=Y-1 To Y+1 For PX=X-1 To X+1 If ((PX=X) And (PY=Y)) ;Skip central Crossroad location Else If (PX>0 and (PX<ARRAY_SIZE)) Grid=Array(PX,PY) If (Grid=EMPTY) PlaceBuilding(PX,PY) Return True End If End If End If Next Next End Function Function PlaceAtHorizontal(X,Y) ;Assume Y is either side of road Local Grid For PY=Y-1 To Y+1 If(PY=Y)) ;Skip Horizontal road Else If (PY>0 and (PY<ARRAY_SIZE)) Grid=Array(X,PY) If (Grid=EMPTY) PlaceBuilding(X,PY) Return True End If End If End If Next End Function Function PlaceAtVertical(X,Y) ;Assume X is either side of road Local Grid For PX=X-1 To X+1 If(PX=X)) ;Skip Vertical road Else If (PX>0 and (PX<ARRAY_SIZE)) Grid=Array(PX,Y) If (Grid=EMPTY) PlaceBuilding(PX,Y) Return True End If End If End If Next End Function Function PlaceBuilding(X,Y) Array(X,Y)=BUILDING End Function I think one of the 'problems' is that you wanted the buildings placed randomly, otherwise, one could iterate along the length of roads placing buildings at every available space on the way. |
| ||
Wouldnt a box sorting algorithm make it easier for each city block to fit buildings into it, wasted space at the end could just be pavement. |
| ||
Thanks for the quick reply guys. @ RemiD, your idea on procedural building creation was exactly what i had in mind. @ _PJ_ thanks for taking the time to write that code, i must confess i havent had time to have a good look at it yet, but i will do. All roads are the same width and at present all building footprints are square, but that is something that will definitely change. @ EdzUp[GD] ive read up a bit on box sorting, and it does look ideal for this situation, unfortunately im nowhere near the level of programmer required to code and implement this, but ill look at it again, it might be easier than i think. Heres a few screenshots of what i have so far - Random roads Whole city Underpass Underpass Street Level Street Level Roof Level The buildings are just placeholders for now until i code the procedural building code, but i would really like to get the placement sorted before i do that. Thanks again guys. |
| ||
That's all l.,ooking quite impressive already! I would agree that EdZupp's suggestion for box-sorting would be the way to go I think, but it's beyond me too I fear. The code I wrote above is pretty basic and can be time consuming as it iterates over and over until it finds a vacant spot - this will take longer and longer as the buildings fill up. This wont be suitable for different-sized buildings either. Whilst I htink about it, I reckon that identifying the areas between roads is what's required. These would be either four points or two points and a width/height or perhaps just two points at opposite corners (since all these areas will be rectangular) Once you have these regions defined (or per region as you go) - then you can place buildings along each of the four sides something like: Function BuildInRegion(XZ1,XZ2) ;START_X=Lowest X point of region XZ1 XZ2 ;START_Z=Lowest Z point of region XZ1 XZ2 ;END_X=Highest Z point of region XZ1 XZ2 ;END_Z=Highest Z point of region XZ1 XZ2 ;First do the Left-Hand sides For Z=START_Z To END_Z X=START_X BX=Rand(1,4);Random range of Building sizeX BZ=Rand(1,4);Random range of Building sizeZ If (Z+BZ>END_Z) BZ=END_Z-Z; Unless required to obtain a completely different building End If If (BZ);No zero-sized buildings! PlaceBuilding(X,Z,BX,BZ) End If Z=Z+BZ ; Make sure next building placed correctly Next ;Now the Right-Hand Side For Z=START_Z To END_Z X=END_X BX=Rand(1,4);Random range of Building sizeX BZ=Rand(1,4);Random range of Building sizeZ If (Z+BZ>END_Z) BZ=END_Z-Z; Unless required to obtain a completely different building End If If (BZ);No zero-sized buildings! PlaceBuilding(X-BX,Z,BX,BZ) End If Z=Z+BZ ; Make sure next building placed correctly Next ;Next, the North/Upper Edge For X=START_X To END_X Z=START_Z BX=Rand(1,4);Random range of Building sizeX BZ=Rand(1,4);Random range of Building sizeZ If (X+BX>END_X) BX=END_X-X; Unless required to obtain a completely different building End If If (BX);No zero-sized buildings! PlaceBuilding(X,Z,BX,BZ) End If X=X+BX ; Make sure next building placed correctly Next ;Finally, the South/Lower Edge For X=START_X To END_X Z=START_Z BX=Rand(1,4);Random range of Building sizeX BZ=Rand(1,4);Random range of Building sizeZ If (X+BX>END_X) BX=END_X-X; Unless required to obtain a completely different building End If If (BX);No zero-sized buildings! PlaceBuilding(X,Z-BZ,BX,BZ) End If X=X+BX ; Make sure next building placed correctly Next End Function Function PlaceBuilding(X,Z,BX,BZ) ; Places a Building at X,Z with Size BX * BZ End Function One potential problem I can forsee already with this method, though, is that each the corners will be processed twice (once whern doing the horiz then when doing the vertical), This might be alleviated if you make START and END smaller in magnitude by 'nX * nZ', and then place buildigns of nX * nZ at each corner etc. Hope that all makes sense. If I get time, and if you need it, I'll try and get something more concrete for you. |
| ||
CAn I be a resident of your city!? |