Surfaces?

Blitz3D Forums/Blitz3D Programming/Surfaces?

Boiled Sweets(Posted 2006) [#1]
Hi,

I understand that it's important to keep the number of surfaces down so...

If I create a cube then copymesh it they both share the same surface but I can texture them differently right?

Also is there a way to show how many surfaces have been created?


Damien Sturdy(Posted 2006) [#2]
I think two different cubes cretes two different surfaces.

I also thought each object of one surface will use the same texture....

I could be wrong, I don't think I am, but i could be. Any other takers?


big10p(Posted 2006) [#3]
Well, yeah, CopyMesh creates a completely new mesh/surface(s). However, CopyEntity shares the mesh with the enitity being copied. The thing is, you can change the texture of the CopyEntity'd mesh, so it must be using a different surface, right? I'm feeling a bit under the weather so my brain probably isn't working. :P

There's no easy way to get an overall surface count, AFAIK. You'll have to manually count them yourself.

[edit]Hmm, I guess if you change the texture on a copy of an entity, it just gets asigned a new surface 'brush', but still shares the actual mesh data with the original? Uh, I dunno... I'm ill. :/


Boiled Sweets(Posted 2006) [#4]
The reason I ask is this...

I have a flare mesh - I load it with load mesh

Then copy it using copymesh 32 times. Have I now got 32 surfaces?????

If so this is bad. How can I have 32 flares that are efficient i.e. share a surface?


big10p(Posted 2006) [#5]
Then copy it using copymesh 32 times. Have I now got 32 surfaces?????
Yes, assuming the flare is only 1 surface to begin with.

If so this is bad. How can I have 32 flares that are efficient i.e. share a surface?
Use CopyEntity instead of CopyMesh.


Shambler(Posted 2006) [#6]
If the flare meshes do not move/animate then a simple solution would be to create an empty mesh and then position and 'addmesh' your flare to the empty mesh 32 times.

This way you only use a single surface and you end up with a single entity rather than 32 of them.


_PJ_(Posted 2006) [#7]
AddMesh after creation.


jfk EO-11110(Posted 2006) [#8]
Using AddMEsh requires not to use Entity-manipulation commands, but only Mesh-manipulation commands. So don't use PositionEntity, EntityTexture etc. but PositionMesh, PaintMesh etc. instead (you need to use Brushes).


RifRaf(Posted 2006) [#9]
Use copy entity, have one large (512x512) texture with smaller 64x64? images on that texture for each flare graphic.. then you can use the same texure, and reassign UV coordinates for each flare, and will use one surface for all of them.

i would just make a function to autoassign UVs depending on wich image on the large texture you want assigned to the flare.. Flaretexture(mainimage, subsection).. somthign like that.


Boiled Sweets(Posted 2006) [#10]
big10p,

I thought copy entity copies everything including the surface?

It says in the manual CopyMesh is identical to addmesh
but CopyMesh does a deep copy - so that sounds like it copies the surface to.

Sorry RifRaf you have lost me completely!

ARRGHH! Confused now.


octothorpe(Posted 2006) [#11]
Meshes are collections of surfaces, which are collections of triangles. Entities use meshes, but don't own them; a single mesh can be shared by multiple entities. When you copy an entity, you are not copying the mesh. Theoretically, it should be faster to render multiple instances of the same geometry (i.e. mesh) because the vertices only need to be sent once.


Jams(Posted 2006) [#12]
Say you make x number of instances of a mesh with CopyEntity(), what happens when you free the original entity? Does each instance become unique, or is Blitz smart enough to keep the data in memory until all the instances are freed aswell?


big10p(Posted 2006) [#13]
Yeah, I believe B3D is smart enough. :)

As I understand it (correct me if I'm wrong), an 'entity' is simply an instance of a data structure - like a type. In that structure, there's a pointer/handle to the mesh data, assuming the entity is a mesh type entity (e.g. pivot entities don't have meshes).

Now, when you use CopyEntity, it creates a new instance of the 'entity' data structure and sets it's mesh data pointer/handle to to match that of the entity being copied. Therefore, both entities are referencing the same mesh data.

Now, if you free the original entity, I assume blitz has a method (linked list, simple counter, whatever) that indicates how many entities are referencing the freed entity's mesh data. If other entities are using that mesh data, then blitz simply deletes the 'entity structure' instance, and removes itself from the linked list (or reduces the counter by 1) of entities tied to that mesh. If it's the only entity referencing the mesh, then it deletes the mesh, also.

Well, that's my guess, anyways. :)


Stevie G(Posted 2006) [#14]
I cuncur with big10p - at least with anything i've done in the past.


Boiled Sweets(Posted 2006) [#15]
OK pls answer this (if you can)....

I create a cube like this...

Function map_create_brick_template()

	brush_wall    = LoadBrush(Pak(g_game_textures[1]\texture$),49 ) 
	brush_ceiling = LoadBrush(Pak(g_game_textures[1]\texture$),49 ) 
	brush_floor   = LoadBrush(Pak(g_game_textures[1]\texture$),49 ) 
		
	; Prepare the mesh
	mesh = CreateMesh() 	
	surf = CreateSurface(mesh,brush_wall) 
	;front face 
	v0 = AddVertex(surf,-1,+1,-1,0,0)
	v1 = AddVertex(surf,+1,+1,-1,1,0)
	v2 = AddVertex(surf,+1,-1,-1,1,1)
	v3 = AddVertex(surf,-1,-1,-1,0,1) 
	AddTriangle surf,v0,v1,v2
	AddTriangle surf,v0,v2,v3 

	;right face 
	v0 = AddVertex(surf,+1,+1,-1,0,0)
	v1 = AddVertex(surf,+1,+1,+1,1,0) 
	v2 = AddVertex(surf,+1,-1,+1,1,1)
	v3 = AddVertex(surf,+1,-1,-1,0,1)
	AddTriangle surf,v0,v1,v2
	AddTriangle surf,v0,v2,v3 

	;back face 
	v0 = AddVertex(surf,+1,+1,+1,0,0)
	v1 = AddVertex(surf,-1,+1,+1,1,0) 
	v2 = AddVertex(surf,-1,-1,+1,1,1)
	v3 = AddVertex(surf,+1,-1,+1,0,1) 
	AddTriangle surf,v0,v1,v2
	AddTriangle surf,v0,v2,v3 

	;left face 
	v0 = AddVertex(surf,-1,+1,+1,0,0)
	v1 = AddVertex(surf,-1,+1,-1,1,0) 
	v2 = AddVertex(surf,-1,-1,-1,1,1)
	v3 = AddVertex(surf,-1,-1,+1,0,1) 
	AddTriangle surf,v0,v1,v2
	AddTriangle surf,v0,v2,v3 

	surf1 = CreateSurface(mesh,brush_floor) 

	;bottom face 
	v0 = AddVertex(surf1,-1,+1,+1,0,1)
	v1 = AddVertex(surf1,+1,+1,+1,0,0) 
	v2 = AddVertex(surf1,+1,+1,-1,1,0)
	v3 = AddVertex(surf1,-1,+1,-1,1,1) 
	AddTriangle surf1,v0,v1,v2
	AddTriangle surf1,v0,v2,v3 

	surf2 = CreateSurface(mesh,brush_ceiling) 

	;top face 
	v0 = AddVertex(surf2,-1,-1,-1,1,0)
	v1 = AddVertex(surf2,+1,-1,-1,1,1) 
	v2 = AddVertex(surf2,+1,-1,+1,0,1)
	v3 = AddVertex(surf2,-1,-1,+1,0,0) 
	AddTriangle surf2,v0,v1,v2
	AddTriangle surf2,v0,v2,v3 
  
   ; free up the brushes
   FreeBrush brush_floor
   FreeBrush brush_ceiling
   FreeBrush brush_wall
	
   UpdateNormals mesh	
	Return mesh

End Function


Then I do this...

brick_template=map_create_brick_template()

	ScaleEntity brick_template,2,2,2
	EntityBox brick_template, -2, -2, -2, 4, 4, 4
	EntityPickMode brick_template,2
	EntityFX brick_template, 1
	
	; Now lets create the maze structure...
	For x = 1 To g_game_mazesize
		For y = 1 To g_game_mazesize
			For z = 1 To g_game_mazesize
				maze(x, y, z)\entity = CopyEntity(brick_template)
        		EntityType maze(x, y, z)\entity,g_game_collision_type_brick
		  		HideEntity maze(x, y, z)\entity	
				PositionEntity maze(x, y, z)\entity,x*4,y*4,z*4
	  		Next
 		Next
	Next
  
	FreeEntity brick_template


Now, if I create a map of 22*22*22 blocks all is fine the FPS is great however at 25*25*25 the FPS goes to 1!

So the question is what is causing the slow down and how to prevent it?

How many surfaces do I have it I create a map of 5*5*5 say based on the above code and how many meshes are there? If copyentity doesn't copy the surface then a map of 5*5*5 would have 1 mesh, 3 surfaces and 625 entities.

I don't think it's the tris count thats causing the probem but the number of surfaces but perhaps it is the number of entities.

Each 'cube' should share a texture for the floor, wall and ceiling so in essence all i really need is 3 surfaces right?

How can I do this? I wonder what the entity limit is with blitz?


Ross C(Posted 2006) [#16]
I'm sure copyentity doesn't keep the one surface... Dx has a thing where it processes a certain amount of triangles. If you go over this, there is a verrry small delay, whilst the rest of the triangles aobve this limit get processed or sent.

Now, i've never really held much faith with the copyentity thing. Why not try and combine all your cubes into the one surface? If you never need to move you cubes, it should make it very simple. Create a function, like the one you use to create your initial cube. Let it pass across a texture number, and your function will set the UV co-ords so the cube displays the correct texture.

Now, you will need to combine all the textures, onto one texture. Depending on the different textures, the different blocks will use, it could work. It would mean, your entire cube structure, will be the one surface, without doubt.


Boiled Sweets(Posted 2006) [#17]
Well yes I need to hide and show them as this is the qoob editor...

The game creates the structure im a far more efficient manner.

I just need to be able to manipulate a world created of 32*32*32 cubes for my editor.


Jams(Posted 2006) [#18]
While we're on the subject of surfaces, what's the deal with the LoadAnimTexture command? I seem to recall reading that each frame was a seperate surface in memory? Is there any way to accomplish the same with a single surface? ( i assume it would require UV coord adjustments)....


Stevie G(Posted 2006) [#19]
Yes, you could create one larger tile texture and simply adjust the uv's for each tilemesh so that it's correctly textured. This would be ok for static meshes but if you have , say 20 vehicles they'd each have to have a separate mesh (&surface) with different uv coords so it would kind of defeat the purpose. In this respect I would stick with an animtexture and copyentity.


Stevie G(Posted 2006) [#20]
@ Boiled ... that's potentially 400,000 polys ... it would slow down my machine anyway ;)


Dreamora(Posted 2006) [#21]
Naw, 400'00 this way work even with Pentium M 4 1,6Ghz on a GeForce 4 MX
But you would not be able to do much other stuff ;-)


Boiled Sweets(Posted 2006) [#22]
so...

is the real problem here the poly count?


Ross C(Posted 2006) [#23]
Use vertex alpha to hide the cubes. Hold the start vertex in a type field. To alpha the cube, just grab the index of the first vertex, held within the type field, then apply the alpha, via the VertexColor command, for the next 12 vertices. Well, 12 including the one held in the type field. Easy :o)


Stevie G(Posted 2006) [#24]
@ Ross C ... yeah, but you'll get alot of z-order issues doing that ... at least I do :( as it renders the polys in the order they are created if using flag 32+2.

You'd also need to ensure that the 32,000 + poly per surface limit was not exceeded.

Stevie


Dreamora(Posted 2006) [#25]
32k poly is not existant on new hardware anymore (you can get up to 64k, then it MAVs). But you must respect the 64k vertex limit, as this will simply mav if broken


Stevie G(Posted 2006) [#26]

32k poly is not existant on new hardware anymore (you can get up to 64k, then it MAVs). But you must respect the 64k vertex limit, as this will simply mav if broken



Didn't know that .. cheers.


Ross C(Posted 2006) [#27]
You won't get Z-order issues, if you completely alpha a vertex. If you are hiding a cube, then set all the vertices to have 0 alpha :o)


Stevie G(Posted 2006) [#28]
@ Ross C, I'd assume you were still going down the singlesurface route in which case you WILL get z-order problems on all the other cubes. Otherwise .. why use vertexalpha at all?

As soon as you set the +32flag, z-ordering is disabled.

Stevie


Ross C(Posted 2006) [#29]
SO, even if you don't use any alpha, the 32+2 flags will draw the cubes in the order they were created? Dam...


Ross C(Posted 2006) [#30]
Only other think i could think of, is having a list of cubes, then deleting the tri's from the surface to hide, then adding them to show again. Depending on the size of the structure, could be do-able. You'd have to rebuild your surface each time though. Thanks for pointing that point out Stevie, about the z buffer issue :o)


Boiled Sweets(Posted 2006) [#31]
So maybe I'm hitting the 32000 polys per surface limit?

I have 3 surfaces (floor, ceiling, wall) per cube and then copyentity the cube. So thats 1 poly for the floor, 1 poly for the ceiling and 4 polys for the walls per cube.

If I then copyentity the cube I'm sharing surfaces so 2 cubes will result in 2 polys on the ceiling surface, 2 polys on the floor surface and 8 polys on the WALL surface, right?

So I guess I hitting 32000+ polys on the wall surface?

If I break it down to 4 surfaces then I might be OK?


Boiled Sweets(Posted 2006) [#32]
Nope - made the cube have 6 surfaces so with 25*25*25 cubes which is 15625 entities, 93750 polys shared on 6 surfaces which is 15625 polys per surface still causes the slow down.

So there is a 32000 poly limit per surface, it's not that so what other limits are there...


TomToad(Posted 2006) [#33]
If I'm not mistaken, in DirectX, all polygons are triangles, so to have a square polygon, you need to use two triange polygons. So in your example, there would actually be 31250 polygons per surface. Still less than 32000, though.


Dreamora(Posted 2006) [#34]
do you form the quads of seperate vertices? Because in that case you hit the 64k (65536 as k = 1024) border for vertices which will lead to MAVs for sure (on polygons its a little GPU dependant. Can be 32768 or 65536).

And yes the restriction would be per surface.


jfk EO-11110(Posted 2006) [#35]
your vram. if you use more than what you got there, DX is forced to use ram as vram AFAIK. this will lead to bus problems, slowing down everything.

Check AvailVidMem() if there is something left.


Boiled Sweets(Posted 2006) [#36]
jfk - its not the vram its reporting 14k used of 56k or so., so it's not that.

Dreamora, you tell me! See the above code - am i, I have no idea...

TomToad ah! But maybe I'm getting so close it, it's slowing down for some reason. I'll try and create 2 different cubes, i.e. cubes the first 7500 entities will use 1 cube and the others will use a different one - that will prove that its not polys per surface...


big10p(Posted 2006) [#37]
See the above code - am i, I have no idea...
Yes, you are. This is the correct way to do cubes, though, otherwise they can't be lit correctly (flat-shaded). Anyway, verts can't be shared across surfaces...


Ross C(Posted 2006) [#38]
So, how many entites do you have?


Boiled Sweets(Posted 2006) [#39]
[quote]
Nope - made the cube have 6 surfaces so with 25*25*25 cubes which is 15625 entities, 93750 polys shared on 6 surfaces which is 15625 polys per surface still causes the slow down.
[quote]

But potentially 32*32*32


Ross C(Posted 2006) [#40]
That's alot of entities...


Stevie G(Posted 2006) [#41]
I think your figures are wrong ...

If you're cube is created using createcube then that's 1 surface , 12 polys and 24 verts so ...

15625 entities will be 15625 surfaces, 187,500 polys and 375,000 vertices.

Unless your cube has 6 surfaces ( e.g. each face has a different brush / texture?!


big10p(Posted 2006) [#42]
Stevie: each of his cubes has 3 surfaces, in order to get a different texture on the top, bottom and remaining sides.


Ross C(Posted 2006) [#43]
What you should think about doing, is creating, this may be difficult (i think there is code in the archives to do this), one mesh. Do this by create a mesh, from the cubes stuck together. Like some sort of CSG mesh addition. You end up with one mesh.

Or, what about a massive hiding/showing operation. Have a 3d grid, and work out which cubes are visible. Or set up portals, to show/hide parts of the level, the player can't see.


Stevie G(Posted 2006) [#44]

Stevie: each of his cubes has 3 surfaces, in order to get a different texture on the top, bottom and remaining sides.



Oops .. didn't notice that. apologies.

Stevie


Dreamora(Posted 2006) [#45]
Instead of 1 Mesh, there is the AddMesh command for example, that would combine the surfaces as well.


Boiled Sweets(Posted 2006) [#46]
I wish people would read the bloody thread b4 adding their opinion!

Yes there are a lot of entities - it's for a reason.

Yes we do culling based upon location ofthe camera etc. THIS IS FOR AN EDITOR NOT A REAL GAME WORLD!

The game runs fine but we need to edit the world based on potentially 32*32*32 entities...

YES I NEED THAT NUMBER OF ENTITIES

YES IT'S A LOT

YES I DO CULLING

AS FAR AS I'M AWARE THERE ARE ONLY 6 SURFACES

-------------------

So what is causing the slowdown?


Dreamora(Posted 2006) [#47]
If there are 6 surfaces you could combine them. Culling is surface based, not object base. 1 vertex in view field -> all surface drawn. (surfaces are sent to graphic card as whole, you can't send parts of it. Thats the reason why they are used to optimize stuff singlesurface at all)

Then you definitely need a better way to do it I fear.
If you split them to more surfaces and use the cube approach (entityalpha 0.0) that was mentioned above, you could fake a OctTree like scene handing. IE: If the cube is not in view, ALL "minicubes" that have this cube as parent are discarded as well.

The reason it might get this slow: Whenever new vertices are added to a surface, the surface has to be retransfered, as if you did a clearsurface and readded everything. So dynamically adding cubes will definitely become slower and slower the more cubes you have, as long as you don't take care that the amount of vertices / triangles on the surface don't raise too far.

At best, you would use surfaces that are restricted to the above mentioned cubes. (they must not go out the cube border anyway) This way you have fast uploads of the dynamic data and fast drop of whole 3D room sections for rendering.


Wayne(Posted 2006) [#48]
Entity count


Boiled Sweets(Posted 2006) [#49]
Dreamora,

interesting. So let me get this straight, is this what you are suggesting...

imgaine 32*32*32 world. I break it into chunks of 8*8*8 cube sets and each of those cube sets share their own set of 6 surfaces (walls, floor ceiling).

Then do culling based on the larger cube sets, i.e player is a 1, 1, 1 therefore show the first 8*8*8 cubes but hide the other cube sets?

The thing is I still would have 32768 entities....

I'm starting to think a better way to do it would be create / destroy the section of map i'm in dymanically. For example pc handles maps of 20*20*20 so for example I break the map into 8 lots of 16*16 * 16 blocks and create the blocks in the section i'm currently in. As I move into another 16*16*16 block setup the blocks as described in the map data.


Ross C(Posted 2006) [#50]
.


Ross C(Posted 2006) [#51]
Well, surely if you copyentity a cube lots of times, your surface only has 12 tris in it and 8 vertices. Because they all share the same vertices. SO, is this a brush thing? Because, each different copy can have it's own different texture.

Graphics3D 800,600
SetBuffer BackBuffer()


Global cam = CreateCamera()

Global light = CreateLight()


Global c = CreateCube()
Global temp

For loop = 1 To 10

	temp = CopyEntity (c)
	PositionEntity temp,Rnd(-30,30),0,Rnd(-30,30)
	tex = CreateTexture(8,8)
	SetBuffer TextureBuffer(tex)
		For loop1 = 0 To 20
			Color Rnd(10,255),Rnd(10,255),Rnd(10,255)
			Rect Rnd(0,8),Rnd(0,8),1,1
		Next
	EntityTexture temp,tex	
Next

SetBuffer BackBuffer()

While Not KeyHit(1)


	If KeyDown(203) Then TurnEntity cam,0,1,0
	If KeyDown(205) Then TurnEntity cam,0,-1,0
	If KeyDown(200) Then MoveEntity cam,0,0,1
	If KeyDown(208) Then MoveEntity cam,0,0,-1
	
	
	UpdateWorld
	RenderWorld
	Color 0,0,0
	Rect 0,0,70,10
	Color 255,255,255
	Text 0,0,"tris = "+TrisRendered()
	Flip
Wend
End



Boiled Sweets(Posted 2006) [#52]
I really don't know but I;d love to find out...