Yes, I did a test where each tile is a seperate mesh, so I ended up with several thousand meshes, that the reason why I'm now joining 100 tiles into one bigger mesh, to reduce surface-count.
I experimented with this dynamic loading and creation of meshes and it works pretty well.
I also have a field for each tile which states what surface to use for this tile (grass, concrete, sand, rock, ...).
I've created a texture which has all these parts in it (just a square of green pixels for now for grass) and while creating the vertices, I set the UV-coords to take that part of the texture and that works too.
Now I only need to review my entire structure for holding all data.
I had an array Map.Tile(1000,1000), where every index was filled with a Tile type-instance.
I've calculated that this array is 4Mb in size (1000x1000x4), as each index is a integer (4 bytes).
Then every tile holds 3 fields (and 2 invisible ones: prev and next, created by Blitz I presume, is this correct?).
This gives me a type-instance of 20 bytes, so the total memory-usage for the map is about 80Mb.
Now I've been thinking of using banks.
Each field of a tile only needs values from 0 to 255, so bytes will suffice.
So a bank of 1000x1000x3 (map = 1000x1000 and 3 bytes per tile) = 3Mb.
This is 26 times smaller than using types and holds the same amount of info.
And this way I can load my Terrain.dat file directly into a bank, without the need for extra processing when loading the game.
The way cars will be processed is not using collisions and stuff like that.
Once the car is out of range, the 3D-model disappears and I only process their coords mathematically.
So a certain car is on tile 128x145 (world-coord x=1280, z=1450) and is on it's way to tile 128x146 at a speed of 75kph for example.
I only keep track of their X and Z coords and each frame I update their coords based on their speed.
I also check on which tile they are currently, so they can check if they need to take another direction when they come on a T-junction.
When planning a route from one factory to another, the pathfinding will be done only once and will be attached to the car's type-instance.
It's just a linked-list of types that define which tiles must be passed to reach their destination.
The cars, truck, boats, ... need to transport goods from one location to another.
If they would just disappear into thin air, no goods will ever reach their destination, so I have to keep track of everything.
I realize this is a big project, but I like to play GTA and miss things like building your own factories, which can make additional money. In GTA you can buy (or be rewarded) certain buildings which produce some cash, but it's not the same as an entire trading-empire.
And this way I can learn very much about 3D-programming.
X2 and X3 (games released by Egosoft) do this too.
You're flying in one part of space, while the game keeps track of all the ships and factories, even when they are in a different part of space.
Outside your sector, there is no collision checking, the game only needs to know about current ship positions, speed etc.
You can also see my game as a 3D-version of transport tycoon, if anyone remembers this game.
This game also keeps track of all trains, boats, trucks, planes, ... even when not in view (in range).
You can also build your own factories there.
But my game will add GTA-like missions and a storyline (to which I've not payed attention yet).
This is some testing code to create a segment and apply the terrain-texture on it:
Const MapX = 500, MapZ = 500 ; Size of the map in tiles
Const HMul = 3 ; Height multiplier for mesh-creation
Const COLTERRAIN = 1
Const COLCAMERA = 2
Graphics3D 800, 600, 0, 2
AmbientLight 255, 255, 255
; Create an array that holds all tiles of the entire map
Dim Map.Tile(MapX, MapZ)
; Also create an array that holds all segments of the entire map (a segment is 10x10 tiles)
Dim LMap.Segment((MapX/10), (MapZ/10))
; Also create an array that holds True if there is a road present on a certain tile
Dim Roads(MapX, MapZ)
; Create a new player
Global Player.TPlayer = New TPlayer
Player\X = 1280
Player\Y = 20
Player\Z = 1280
Player\TileX = Player\X / 10
Player\TileZ = Player\Z / 10
Player\SegX = Player\TileX / 10
Player\SegZ = Player\TileZ / 10
Player\Obj = CreateCamera()
Type Tile
Field Y ; Holds the height-location of the tile (in steps of "HMul" BlitzUnits)
Field TerrainType ; Terrain-type model
Field TerrTex ; Type of terrain (0 = Concrete, 1 = Water, 2 = Grass, 3 = Sand)
End Type
Type Segment
Field Obj ; A pointer to the 3D-model
Field TerrainObj ; A pointer to the 3D-model of the terrain
Field RoadObj ; A pointer to the 3D-model of the roads
End Type
Type TPlayer
Field TileX ; The tile where the player is located in the X-direction
Field TileZ ; The tile where the player is located in the Z-direction
Field SegX ; The segment where the player is located in the X-direction
Field SegZ ; The segment where the player is located in the Z-direction
Field X ; The global X-direction of the player in the world
Field Y ; The global Y-direction of the player in the world
Field Z ; The global Z-direction of the player in the world
Field Obj ; Holds a pointer to the player's 3D-object
End Type
; Include all source-code
Include "DynamicLoading.bb"
; Fill the map-array
For z = 0 To MapZ-1
For x = 0 To MapX-1
; Create a new tile
Map(x,z) = New Tile
; Set the entire terrain to be flat
Map(x,z)\TerrainType = 1
Next
Next
For z = 0 To (MapZ-1)/10
For x = 0 To (MapX-1)/10
LMap(x,z) = New Segment
Next
Next
; Create a hill in the middle of flat terrain
Map(24,28)\TerrainType = 7
Map(25,28)\TerrainType = 4
Map(26,28)\TerrainType = 4
Map(27,28)\TerrainType = 4
Map(28,28)\TerrainType = 8
Map(24,27)\TerrainType = 3
Map(25,27)\TerrainType = 7
Map(26,27)\TerrainType = 4
Map(27,27)\TerrainType = 8
Map(28,27)\TerrainType = 5
Map(24,26)\TerrainType = 3
Map(25,26)\TerrainType = 3
Map(26,26)\TerrainType = 1
Map(27,26)\TerrainType = 5
Map(28,26)\TerrainType = 5
Map(24,25)\TerrainType = 3
Map(25,25)\TerrainType = 6
Map(26,25)\TerrainType = 2
Map(27,25)\TerrainType = 9
Map(28,25)\TerrainType = 5
Map(24,24)\TerrainType = 6
Map(25,24)\TerrainType = 2
Map(26,24)\TerrainType = 2
Map(27,24)\TerrainType = 2
Map(28,24)\TerrainType = 9
Map(25, 27)\Y = 1
Map(25, 27)\TerrTex = 3
Map(26, 27)\Y = 1
Map(26, 27)\TerrTex = 3
Map(27, 27)\Y = 1
Map(27, 27)\TerrTex = 3
Map(25, 26)\Y = 1
Map(25, 26)\TerrTex = 3
Map(26, 26)\Y = 2
Map(26, 26)\TerrTex = 2
Map(27, 26)\Y = 1
Map(27, 26)\TerrTex = 3
Map(25, 25)\Y = 1
Map(25, 25)\TerrTex = 3
Map(26, 25)\Y = 1
Map(26, 25)\TerrTex = 3
Map(27, 25)\Y = 1
Map(27, 25)\TerrTex = 3
Texture = LoadTexture("Textures\Terrain.bmp")
SetBuffer BackBuffer()
CreateTerrainSegment(2, 2)
EntityTexture LMap(2,2)\Obj, Texture
EntityType LMap(2,2)\Obj, COLTERRAIN
PositionEntity Player\Obj, 250, 20, 250
EntityType Player\Obj, COLCAMERA
EntityRadius Player\Obj, 3
Collisions COLCAMERA, COLTERRAIN, 2, 3
While Not KeyHit(1)
MoveEntity Player\Obj, 0, -0.1, 0
If KeyDown(200) Then MoveEntity Player\Obj, 0, 0, 0.1
If KeyDown(208) Then MoveEntity Player\Obj, 0, 0, -0.1
If KeyDown(203) Then TurnEntity Player\Obj, 0, 0.5, 0
If KeyDown(205) Then TurnEntity Player\Obj, 0, -0.5, 0
UpdateWorld
RenderWorld
VWait:Flip False
Wend
End
File DynamicLoading.bb:
Function CreateTerrainSegment(SegX, SegZ)
Local mesh = CreateMesh()
Local surf = CreateSurface(mesh)
PositionMesh mesh, (SegX*100)+50, 0, (SegZ*100)+50
TileXMin = (SegX*10) + 1
TileXMax = (SegX*10) + 10
TileZMin = (SegZ*10) + 1
TileZMax = (SegZ*10) + 10
For TileZ = TileZMin To TileZMax
For TileX = TileXMin To TileXMax
CreateTerrainTile(surf, TileX, TileZ)
Next
Next
; Store the reference to the segment-model in the LMap-array
LMap(SegX, SegZ)\Obj = mesh
End Function
Function CreateTerrainTile(surf, TileX, TileZ)
; This routine adds the required vertices and triangles of the required tile to the given surface, adding the tile to the segment's mesh
Select Map(TileX, TileZ)\TerrainType
Case 1 ; Flat tile
v0 = AddVertex(surf, (TileX*10)-5, (Map(TileX,TileZ)\Y*HMul), (TileZ*10)+5)
v1 = AddVertex(surf, (TileX*10)+5, (Map(TileX,TileZ)\Y*HMul), (TileZ*10)+5)
v2 = AddVertex(surf, (TileX*10)+5, (Map(TileX,TileZ)\Y*HMul), (TileZ*10)-5)
v3 = AddVertex(surf, (TileX*10)-5, (Map(TileX,TileZ)\Y*HMul), (TileZ*10)-5)
t0 = AddTriangle(surf, v0, v1, v3)
t1 = AddTriangle(surf, v1, v2, v3)
Case 2 ; Goes up to the top
v0 = AddVertex(surf, (TileX*10)-5, (Map(TileX,TileZ)\Y*HMul)+HMul, (TileZ*10)+5)
v1 = AddVertex(surf, (TileX*10)+5, (Map(TileX,TileZ)\Y*HMul)+HMul, (TileZ*10)+5)
v2 = AddVertex(surf, (TileX*10)+5, (Map(TileX,TileZ)\Y*HMul), (TileZ*10)-5)
v3 = AddVertex(surf, (TileX*10)-5, (Map(TileX,TileZ)\Y*HMul), (TileZ*10)-5)
t0 = AddTriangle(surf, v0, v1, v3)
t1 = AddTriangle(surf, v1, v2, v3)
Case 3 ; Goes up to the right
v0 = AddVertex(surf, (TileX*10)-5, (Map(TileX,TileZ)\Y*HMul), (TileZ*10)+5)
v1 = AddVertex(surf, (TileX*10)+5, (Map(TileX,TileZ)\Y*HMul)+HMul, (TileZ*10)+5)
v2 = AddVertex(surf, (TileX*10)+5, (Map(TileX,TileZ)\Y*HMul)+HMul, (TileZ*10)-5)
v3 = AddVertex(surf, (TileX*10)-5, (Map(TileX,TileZ)\Y*HMul), (TileZ*10)-5)
t0 = AddTriangle(surf, v0, v1, v3)
t1 = AddTriangle(surf, v1, v2, v3)
Case 4 ; Goes up to the bottom
v0 = AddVertex(surf, (TileX*10)-5, (Map(TileX,TileZ)\Y*HMul), (TileZ*10)+5)
v1 = AddVertex(surf, (TileX*10)+5, (Map(TileX,TileZ)\Y*HMul), (TileZ*10)+5)
v2 = AddVertex(surf, (TileX*10)+5, (Map(TileX,TileZ)\Y*HMul)+HMul, (TileZ*10)-5)
v3 = AddVertex(surf, (TileX*10)-5, (Map(TileX,TileZ)\Y*HMul)+HMul, (TileZ*10)-5)
t0 = AddTriangle(surf, v0, v1, v3)
t1 = AddTriangle(surf, v1, v2, v3)
Case 5 ; Goes up to the left
v0 = AddVertex(surf, (TileX*10)-5, (Map(TileX,TileZ)\Y*HMul)+HMul, (TileZ*10)+5)
v1 = AddVertex(surf, (TileX*10)+5, (Map(TileX,TileZ)\Y*HMul), (TileZ*10)+5)
v2 = AddVertex(surf, (TileX*10)+5, (Map(TileX,TileZ)\Y*HMul), (TileZ*10)-5)
v3 = AddVertex(surf, (TileX*10)-5, (Map(TileX,TileZ)\Y*HMul)+HMul, (TileZ*10)-5)
t0 = AddTriangle(surf, v0, v1, v3)
t1 = AddTriangle(surf, v1, v2, v3)
Case 6 ; Corner-up to the top-right
v0 = AddVertex(surf, (TileX*10)-5, (Map(TileX,TileZ)\Y*HMul), (TileZ*10)+5)
v1 = AddVertex(surf, (TileX*10)+5, (Map(TileX,TileZ)\Y*HMul)+HMul, (TileZ*10)+5)
v2 = AddVertex(surf, (TileX*10)+5, (Map(TileX,TileZ)\Y*HMul), (TileZ*10)-5)
v3 = AddVertex(surf, (TileX*10)-5, (Map(TileX,TileZ)\Y*HMul), (TileZ*10)-5)
t0 = AddTriangle(surf, v0, v1, v3)
t1 = AddTriangle(surf, v1, v2, v3)
; t0 = AddTriangle(surf, v0, v2, v3)
; t1 = AddTriangle(surf, v0, v1, v2)
Case 7 ; Corner-up to the right-bottom
v0 = AddVertex(surf, (TileX*10)-5, (Map(TileX,TileZ)\Y*HMul), (TileZ*10)+5)
v1 = AddVertex(surf, (TileX*10)+5, (Map(TileX,TileZ)\Y*HMul), (TileZ*10)+5)
v2 = AddVertex(surf, (TileX*10)+5, (Map(TileX,TileZ)\Y*HMul)+HMul, (TileZ*10)-5)
v3 = AddVertex(surf, (TileX*10)-5, (Map(TileX,TileZ)\Y*HMul), (TileZ*10)-5)
t0 = AddTriangle(surf, v0, v1, v3)
t1 = AddTriangle(surf, v1, v2, v3)
Case 8 ; Corner-up to the left-bottom
v0 = AddVertex(surf, (TileX*10)-5, (Map(TileX,TileZ)\Y*HMul), (TileZ*10)+5)
v1 = AddVertex(surf, (TileX*10)+5, (Map(TileX,TileZ)\Y*HMul), (TileZ*10)+5)
v2 = AddVertex(surf, (TileX*10)+5, (Map(TileX,TileZ)\Y*HMul), (TileZ*10)-5)
v3 = AddVertex(surf, (TileX*10)-5, (Map(TileX,TileZ)\Y*HMul)+HMul, (TileZ*10)-5)
t0 = AddTriangle(surf, v0, v2, v3)
t1 = AddTriangle(surf, v0, v1, v2)
Case 9 ; Corner up to the top-left
v0 = AddVertex(surf, (TileX*10)-5, (Map(TileX,TileZ)\Y*HMul)+HMul, (TileZ*10)+5)
v1 = AddVertex(surf, (TileX*10)+5, (Map(TileX,TileZ)\Y*HMul), (TileZ*10)+5)
v2 = AddVertex(surf, (TileX*10)+5, (Map(TileX,TileZ)\Y*HMul), (TileZ*10)-5)
v3 = AddVertex(surf, (TileX*10)-5, (Map(TileX,TileZ)\Y*HMul), (TileZ*10)-5)
t0 = AddTriangle(surf, v0, v1, v3)
t1 = AddTriangle(surf, v1, v2, v3)
End Select
Select Map(TileX, TileZ)\TerrTex
Case 0 ; Concrete
VertexTexCoords surf, v0, 0.0, 0.0
VertexTexCoords surf, v1, 0.497, 0.0
VertexTexCoords surf, v2, 0.497, 0.499
VertexTexCoords surf, v3, 0.0, 0.499
Case 1 ; Water
VertexTexCoords surf, v0, 0.499, 0.0
VertexTexCoords surf, v1, 1.0, 0.0
VertexTexCoords surf, v2, 1.0, 0.499
VertexTexCoords surf, v3, 0.499, 0.499
Case 2 ; Grass
VertexTexCoords surf, v0, 0.0, 0.501
VertexTexCoords surf, v1, 0.497, 0.501
VertexTexCoords surf, v2, 0.497, 1.0
VertexTexCoords surf, v3, 0.0, 1.0
Case 3 ; Sand
VertexTexCoords surf, v0, 0.499, 0.501
VertexTexCoords surf, v1, 1.0, 0.501
VertexTexCoords surf, v2, 1.0, 1.0
VertexTexCoords surf, v3, 0.499, 1.0
End Select
End Function
And this is the terrain texture I've used:
http://users.telenet.be/vge/downloads/Terrain.bmp