About surfaces

Blitz3D Forums/Blitz3D Beginners Area/About surfaces

PowerPC603(Posted 2007) [#1]
Hi all,

If you have a mesh with 2 surfaces, where each surface holds the vertices to create 1 cube, is this the same as having 2 seperate cubes?

In this code, the mesh has 2 surfaces, each holding only 4 vertices and 2 triangles, making up on quad.
Is this the same as having 2 seperate meshes, where each mesh has one surface and holds the vertices and triangles for one quad?

Graphics3D 800, 600, 0, 2

SetBuffer BackBuffer()

camera = CreateCamera()
PositionEntity camera, 0, 0, -20

mesh = CreateMesh()
surf1 = CreateSurface(mesh)
surf2 = CreateSurface(mesh)

v0 = AddVertex(surf1, -15, 5, 0)
v1 = AddVertex(surf1, -5, 5, 0)
v2 = AddVertex(surf1, -5, -5, 0)
v3 = AddVertex(surf1, -15, -5, 0)
t0 = AddTriangle(surf1, v0, v1, v3)
t1 = AddTriangle(surf1, v1, v2, v3)

v0 = AddVertex(surf2, 5, 5, 0)
v1 = AddVertex(surf2, 15, 5, 0)
v2 = AddVertex(surf2, 15, -5, 0)
v3 = AddVertex(surf2, 5, -5, 0)
t0 = AddTriangle(surf2, v0, v1, v3)
t1 = AddTriangle(surf2, v1, v2, v3)

While Not KeyHit(1)
	RenderWorld
	Flip
Wend
End


I don't seem to understand why someone would make 1 big mesh with several different surfaces, while several different meshes with only one surface is the same?
On top of that, seperate meshes can be moved individually while one big mesh moves everything.

Also, when you create a mesh with 2 surfaces, how do you apply the texture to the second surface?
Or does texturing apply the texture to all surfaces of the mesh?


Ross C(Posted 2007) [#2]
I'm not 100% sure how blitz treats this. It may render that little bit quickier, but don't hold me to that.

As for the reasons for doing this: It's so you can get textures to blend with each other. If you create many surfaces, you can have each surface with it's own properties, but still be part of the same mesh.

You can change individual surfaces with the PaintSurface command.

http://www.blitzbasic.com/b3ddocs/command.php?name=PaintSurface&ref=3d_a-z

You will need to create a brush first though.

TBH, i can't think of too many instances when creating another surface would be more useful, except for certain texturing purposes (using vertexalpha on a surface, to see through to the surface below, thus creating a nice texture blend, useful for say, terrains)

Just use another entity. It's easier to rotate and move and scale.


Dreamora(Posted 2007) [#3]
No it is not the same as 2 meshes.

If a single part of a mesh is in view, the whole mesh is sent to the GPU.
no mather if only surface 1 of 50 surfaces is in view or not.


Ross C(Posted 2007) [#4]
Good point. I'm rusty on this stuff now... Feel old.


PowerPC603(Posted 2007) [#5]
Ah ok, so it's better to use multiple meshes with only 1 surface.
I'm thinking about making a game where you can drive your vehicle (car, truck, bus, taxi, ...) through a city.
The entire map will be tile-based and needs to be created on-the-fly as you drive through the map.
Several tiles around you (withing range of sight) need to be created while playing.
I cannot have the map modelled in a 3D-package, as you need to have the ability to build new factories, create extra roads, tunnels and bridges (all in 3D).

If it was just a game like GTA, then I could divide the entire map into tiles and load them as you go, but now the game needs to check several things.
If there is a tunnel-entrance on a certain tile, that tile may not be created as part of the terrain, as it would block the tunnel-entrance for example.
When you add a road-tile next to a straight road, that straight road needs to be converted in a T-junction, if you know what I mean.

So my idea was to have tiles (which are 10x10 Blitz Units) and segments (which are 10x10 tiles).
A road-piece is just 1x1 tile, and a building can be 3x3 tiles.
A segment is one big mesh of 100x100 Blitz Units and is created based on the data for each tile which is in that segment.
I need this, because when too many tiles are created seperately (I had a range of sight of 250 Units around you), then I had 2500 seperate meshes, which slows down severely.
Now I only have 25 segments, which speeds up the rendering.

I create a mesh (segment) and create all vertices and triangles of each tile inside that segment and add it to that segment-mesh (all into one surface).

I want to do this like that, because I hate loading-screens, so the game must dynamically load everything in range (and unload everything outside this range).

It's a game like GTA, where you can drive through a city and do missions, but you can also build factories, buy vehicles and set them to work to transport the goods from one factory to another.
The game must process every vehicle on the map, even when not in range (like X2: The Threat and X3: Reunion).


Ross C(Posted 2007) [#6]
There's nothing wrong with you doing the tiles within the one surface. Just assign different texture co-ords. For instance split the texture up into different things, such as a road part, grass... etc etc, and assign the tiles to different parts of the same texture.

There is a balancing act in this though. Try and keep the surface count low-ish. The more surfaces (Meshes basically), the slower things will run. If you create your tiles out of the one surface, it will get rendered quicker.

I would suggest processing the cars within a certain range. Probably wouldn't be a great idea keeping tracking moving, checking collisions... etc, on everything in the city. The way GTA does it, is it keeps track of cars and people within a certain area. If they go out this area, they disappear.

Pretty ambitious project :o)


PowerPC603(Posted 2007) [#7]
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