Surfaces?
Blitz3D Forums/Blitz3D Programming/Surfaces?
| ||
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? |
| ||
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? |
| ||
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. :/ |
| ||
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? |
| ||
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. |
| ||
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. |
| ||
AddMesh after creation. |
| ||
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). |
| ||
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. |
| ||
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. |
| ||
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. |
| ||
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? |
| ||
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. :) |
| ||
I cuncur with big10p - at least with anything i've done in the past. |
| ||
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? |
| ||
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. |
| ||
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. |
| ||
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).... |
| ||
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. |
| ||
@ Boiled ... that's potentially 400,000 polys ... it would slow down my machine anyway ;) |
| ||
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 ;-) |
| ||
so... is the real problem here the poly count? |
| ||
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) |
| ||
@ 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 |
| ||
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 |
| ||
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. |
| ||
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) |
| ||
@ 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 |
| ||
SO, even if you don't use any alpha, the 32+2 flags will draw the cubes in the order they were created? Dam... |
| ||
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) |
| ||
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? |
| ||
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... |
| ||
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. |
| ||
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. |
| ||
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. |
| ||
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... |
| ||
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... |
| ||
So, how many entites do you have? |
| ||
[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 |
| ||
That's alot of entities... |
| ||
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?! |
| ||
Stevie: each of his cubes has 3 surfaces, in order to get a different texture on the top, bottom and remaining sides. |
| ||
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: 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 |
| ||
Instead of 1 Mesh, there is the AddMesh command for example, that would combine the surfaces as well. |
| ||
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? |
| ||
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. |
| ||
Entity count |
| ||
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. |
| ||
. |
| ||
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 |
| ||
I really don't know but I;d love to find out... |