The 3D grid
Blitz3D Forums/Blitz3D Programming/The 3D grid
| ||
Im trying to create a 3d grid but unfortunately I haven't found the brain power to pull it off yet. Each grid square needs the capability of being hidden/deleted/removed. Im not sure how I would create a 1000x1000 grid with each square being independently removable. Any Ideas? Here's my start, there's not much to it. Graphics3D 400,400,16,2 SetBuffer BackBuffer() ;;;;Grid Array//Determines how many squares in the grid Dim mapgrid(1000,1000) ;;;;The size of each square Global gridindex = 20 cam1 = CreateCamera() CameraViewport cam1,0,0,400,400 light1 = CreateLight() ;;;CreateGrid Function CreateGrid() While Not KeyHit(1) UpdateWorld RenderWorld FPS() Flip Cls Wend ;;;;;;Creates a map mesh grid Function CreateGrid() shroud = CreateMesh() s = CreateSurface(shroud) AddVertex s,-10,+10,+100:AddVertex s,+10,+10,+100 AddVertex s,-10,-10,+100:AddVertex s,+10,-10,+100 AddTriangle s,0,1,2:AddTriangle s,2,1,3 End Function ;;;;;;//FPS Global fpstime,fpscount,fps Function FPS() fpscount=fpscount+1 If MilliSecs()>fpstime Then fpstime=MilliSecs()+1000 fps=fpscount fpscount=0 EndIf Text 10,0,"FPS: "+fps End Function ;;;;;\\FPS |
| ||
Graphics3D 800,600,0,2 SetBuffer BackBuffer() Const MapX = 100 Const MapZ = 100 Const GridSize = 2 ;;;;Grid Array//Determines how many squares in the grid Dim mapgrid(MapX,MapZ) For z = 0 To MapZ-1 For x = 0 To MapX-1 mapgrid(x,z) = Rand(0,1) Next Next cam1 = CreateCamera() AmbientLight 255, 255, 255 PositionEntity cam1, 0, 20, 0 gridmesh = CreateGrid() While Not KeyHit(1) If KeyDown(200) Then MoveEntity cam1, 0, 0, 1 If KeyDown(208) Then MoveEntity cam1, 0, 0, -1 If KeyDown(203) Then TurnEntity cam1, 0, 1, 0 If KeyDown(205) Then TurnEntity cam1, 0, -1, 0 ; If you want to test mesh-generating speed, replace keyhit(57) by keydown(57), then every frame a new random mesh will be generated ; while holding down the spacebar If KeyHit(57) Then ; Create a random tiled map (place new random numbers in the array) For z = 0 To MapZ-1 For x = 0 To MapX-1 mapgrid(x,z) = Rand(0,1) Next Next ; Remove the mesh from memory FreeEntity gridmesh ; Re-create the mesh CreateGrid() EndIf UpdateWorld RenderWorld FPS() Text 10, 20, "Tris rendered: " + TrisRendered() Flip Cls Wend Function CreateGrid() Local mesh = CreateMesh() Local surf = CreateSurface(mesh) For z = 0 To MapZ-1 For X = 0 To MapX-1 If mapgrid(x,z) = 1 Then CreateTile(surf,x,z) EndIf Next Next Return mesh End Function Function CreateTile(surf, x, z) v0 = AddVertex(surf, (x*GridSize)+((GridSize/2)*(-1)), 0, (z*GridSize)+((GridSize/2))) v1 = AddVertex(surf, (x*GridSize)+((GridSize/2)), 0, (z*GridSize)+((GridSize/2))) v2 = AddVertex(surf, (x*GridSize)+((GridSize/2)), 0, (z*GridSize)+((GridSize/2)*(-1))) v3 = AddVertex(surf, (x*GridSize)+((GridSize/2)*(-1)), 0, (z*GridSize)+((GridSize/2)*(-1))) t0 = AddTriangle(surf, v0, v1, v3) t1 = AddTriangle(surf, v1, v2, v3) End Function ;;;;;;//FPS Global fpstime,fpscount,fps Function FPS() fpscount=fpscount+1 If MilliSecs()>fpstime Then fpstime=MilliSecs()+1000 fps=fpscount fpscount=0 EndIf Text 10,0,"FPS: "+fps End Function ;;;;;\\FPS This code generates a mesh with size 100x100 (1000x1000 creates a MAV, because meshes are limited to 65535 vertices) as one big mesh. It creates one mesh and adds vertices to it to generate the entire mesh, based on the value in the corresponding index in the array. First the code places random values (0 or 1) in the array. The the CreateGrid loops through the array and if it sees "1", it creates a tile in the big mesh. If it's 0, do nothing. You can move the camera using the up/down arrowkeys, and turn the camera using left/right arrowkeys. When you hit the spacebar, the program places new random values in the array, frees the current big mesh and re-creates the mesh. You will see that this works very fast, as continued hitting the spacebar doesn't even slow down. If you want to create a map of size 1000x1000, I suggest that you create 100 big meshes, each of size 100x100, and place them next to eachother. This way you reduce surface-count (this big mesh has only 1 surface). If you where to create 1000x1000 seperate meshes, then you would have 1000.000 meshes and thus 1000.000 surfaces and your computer will crawl while rendering that much surfaces. |
| ||
Thanks for the code, you must have been doing this for awhile. Some of the triangles appear backwards and show up black. I messed around for a few hours and managed to get what I was looking for. Something like this Graphics3D 400,400,16,2 SetBuffer BackBuffer() ;;;;The size of each square Global gridindex# = 20.0;;20.0 is the actual size, divided by 2 to represent the + side of the x/y axis and the - side of x/y Global gridsize = (gridindex#/2.0) Global gridx = 20,gridy = 10;;;;how many grid squares ;;;Use this to center the entire grid to the screen Global centerx = (gridx*gridsize)/2 Global centery = (gridy*gridsize)/2 ;;;;Grid Type Type grid Field mesh Field surface Field ispicked End Type ;;;;Grid Array//Determines how many squares in the grid Dim mapgrid(gridx,gridy) ;Environmental variables Global cam1,light1 ;setup camera and light cam1 = CreateCamera() CameraViewport cam1,0,0,400,400 light1 = CreateLight() ;;;CreateGrid Function CreateGrid(gridsize) While Not KeyHit(1) PickAndKill() UpdateWorld RenderWorld FPS() Flip Cls Wend ;;;;create grid according to dimensions Function CreateGrid(size) For x = 1 To (gridx - 1) For y = 1 To (gridy - 1) newgrid.grid = New Grid newgrid\mesh = CreateMesh() newgrid\surface = CreateSurface(newgrid\mesh) AddVertex newgrid\surface,-size,+size,+100:AddVertex newgrid\surface,+size,+size,+100 AddVertex newgrid\surface,-size,-size,+100:AddVertex newgrid\surface,+size,-size,+100 AddTriangle newgrid\surface,0,1,2:AddTriangle newgrid\surface,2,1,3 PositionEntity newgrid\mesh,(x*gridsize) - centerx,(y*gridsize) - centery,100 EntityPickMode newgrid\mesh,2 Next Next End Function ;;Click and kill each grid square Function PickAndKill() CameraPick(cam1,MouseX(),MouseY()) PickedEnt = PickedEntity() If MouseDown(1) If PickedEnt <> 0 For tile.grid = Each grid If PickedEnt = tile\mesh FreeEntity tile\mesh EndIf Next EndIf EndIf End Function ;;;;;;//FPS Global fpstime,fpscount,fps Function FPS() fpscount=fpscount+1 If MilliSecs()>fpstime Then fpstime=MilliSecs()+1000 fps=fpscount fpscount=0 EndIf Text 10,0,"FPS: "+fps End Function ;;;;;\\FPS Yours appears to render much faster then this code. I'm wondering if I could some how get the effect and visuals of this code with the speed of yours? |
| ||
Actually, I began with this just a week ago. :-) This code adds picking to the program. It creates an infinity plane which is pickable, but entityalpha is set to 0 to make in invisible. I did it this way to be able to add tiles to the big mesh too, instead of only removing them. Graphics3D 800,600,0,2 SetBuffer BackBuffer() Const MapX = 100 Const MapZ = 100 Const GridSize = 2 ;;;;Grid Array//Determines how many squares in the grid Dim mapgrid(MapX,MapZ) For z = 0 To MapZ-1 For x = 0 To MapX-1 mapgrid(x,z) = Rand(0,1) Next Next ; Create an endless plane (used to do the picking), move it down a bit, set a different color and set pickmode plane = CreatePlane() MoveEntity plane, 0, -0.1, 0 EntityColor plane, 255, 0, 0 EntityPickMode plane, 2 EntityAlpha plane, 0 ; Create camera and position it above the world cam1 = CreateCamera() AmbientLight 255, 255, 255 PositionEntity cam1, 100, 100, 100 TurnEntity cam1, 90, 0, 0 ; Create a big mesh where each tile is created based on the value in the array Global gridmesh = CreateGrid() Global texture = LoadTexture("texture.jpg") EntityTexture gridmesh, texture While Not KeyHit(1) If KeyDown(203) Then MoveEntity cam1, -1, 0, 0 If KeyDown(205) Then MoveEntity cam1, 1, 0, 0 If KeyDown(200) Then MoveEntity cam1, 0, 1, 0 If KeyDown(208) Then MoveEntity cam1, 0, -1, 0 If KeyDown(201) Then MoveEntity cam1, 0, 0, 1 If KeyDown(209) Then MoveEntity cam1, 0, 0, -1 If MouseHit(1) Then PickedEnt = CameraPick(cam1, MouseX(), MouseY()) ; Calculate which tile to be switched on/off x = PickedX() / GridSize z = PickedZ() / GridSize If (x>= 0) And (x<=MapX) And (z>=0) And (z<=MapZ) Then ; Toggle the tile on/off If mapgrid(x,z) = 1 Then mapgrid(x,z) = 0 Else mapgrid(x,z) = 1 ; Delete the big mesh FreeEntity gridmesh ; Re-create the big mesh gridmesh = CreateGrid() ; Apply the texture to it EntityTexture gridmesh, texture EndIf EndIf UpdateWorld RenderWorld FPS() Text 10, 20, "Tris rendered: " + TrisRendered() Flip Cls Wend Function CreateGrid() Local mesh = CreateMesh() Local surf = CreateSurface(mesh) For z = 0 To MapZ-1 For X = 0 To MapX-1 If mapgrid(x,z) = 1 Then CreateTile(surf,x,z) EndIf Next Next Return mesh End Function Function CreateTile(surf, x, z) v0 = AddVertex(surf, (x*GridSize)+((GridSize/2)*(-1)), 0, (z*GridSize)+((GridSize/2)), 0, 0) v1 = AddVertex(surf, (x*GridSize)+((GridSize/2)), 0, (z*GridSize)+((GridSize/2)), 1, 0) v2 = AddVertex(surf, (x*GridSize)+((GridSize/2)), 0, (z*GridSize)+((GridSize/2)*(-1)), 1, 1) v3 = AddVertex(surf, (x*GridSize)+((GridSize/2)*(-1)), 0, (z*GridSize)+((GridSize/2)*(-1)), 0, 1) t0 = AddTriangle(surf, v0, v1, v3) t1 = AddTriangle(surf, v1, v2, v3) End Function ;;;;;;//FPS Global fpstime,fpscount,fps Function FPS() fpscount=fpscount+1 If MilliSecs()>fpstime Then fpstime=MilliSecs()+1000 fps=fpscount fpscount=0 EndIf Text 10,0,"FPS: "+fps End Function ;;;;;\\FPS By a quick peek at your code, it seems that you create each tile as a seperate mesh, that's why your code renders slower, as it has much more seperate meshes and seperate surfaces. My code creates one big mesh, and each tile's vertices and triangles are added to it. It also adds UV coords to the vertices and applies a texture on the mesh. Now the camera floats above the mesh, looking down. Move the camera with up/down/left.right, and zoom in/out using pageup/pagedown. Clicking will toggle the tile on/off. |
| ||
This is excellent, its taking me awhile to read through and understand everything but this is exactly what I need. Out of curiosity, do you interpret code pretty quickly since you started coding? |
| ||
I programmed some stuff in Blitz3D and Visual Basic and I've been learning about programming since I was 8 years old (now 28). I didn't use all my free time to code though, but I learn stuff quickly that makes sense. Some things are chinese to me too, but after some testing, most of the time I start to grasp it. And I'm thinking of creating a game which requires the same stuff as I've posted here, but a bit more difficult than this. In my game, I need to generate the terrain while you play, same as the roads and buildings (dynamic loading like GTA does) as I hate loading screens. :-) Imagine a game where you drive through a city and suddenly you get a loading screen in front of you, that would be annoying, don't you think? When the loading has finished, the game goes on and you're momentarily distracted, that wouldn't make a good game I think. Last week, I've been searching some options about how to dynamically load my terrain, road-system and much more and creating test code. I've also been looking into pathfinding and came up with my own system to find a path via roads to my destination, but I need to convert the idea into code, which may take some time. I'm a technician in RL, so analysing problems and coming up with a solution is what I do. The same with programming. I started with code like yours (lots of different meshes) and my framerate was down from 999 fps (1 tile generated) to 30 (2500 seperate tiles). And then I only generated the terrain, no roads, buildings, trees or vehicles yet. I remembered something about keeping your surface-count as low as you can to increase framerate, so I began thinking of merging several tiles into one bigger mesh. My game also needs to give the player the ability to build new factories, which require and produce goods. Then you need trucks to transport those goods from one factory to another. The player must also be able to add/remove roads to connect the buildings to the existing roads. Building tunnels and bridges must also be possible. When you create a tunnel, then the terraintile where the tunnel entrance and exit are located, may not be generated, so I cannot create a map in a modelling package and just load it. While generating the terrain, I must keep track if there is a tunnel entrance or exit on that tile, and if so, don't create a tile, as the terrain has collisions and would block the tunnel entrance/exit. I have to have a system which holds the entire map into memory and create the models on-the-fly. I also did find a way to reduce memory requirements. I had an array: Map.Tile(1000,1000). After creating all type-instances to fill the array, the program required 46Mb RAM. This was only after creating the array and the type-instances, no 3D-stuff or anything else was created. The Tile type has only 3 fields which define each tile of the terrain, but only needs values from 0 - 200, so bytes would suffice. But Blitz doesn't have byte-variables, only integers, floats and strings. So for a map of size 1000x1000 and 3 bytes to define the tile, I tested memory-usage with banks, which I've never used before. The bank now has a size of 3.000.000 bytes, which is all I need to define all properties of each tile on the map. Now memory-usage was only 12Mb RAM, so I'll be using 34Mb RAM less than before and it holds exactly the same data. |
| ||
Thats very interesting. So basically your terrain and environment are all going to be produced by built in algorithms? The thought of building a GTA style like game cramps my brain. I can't imagine........ Have you ever considered programming in c++? Just out of curiosity, do you think Blitz is much much faster to work with then c++? |
| ||
Yes, my entire 3D-world will be generated while you play using built-in algorithms. Maybe that some buildings will be modelled in some modelling-tool, but I'm not sure about that yet. But I'm 100% sure about the terrain-generating and road-construction, they will be generated by algorithms, as they need to be modified frequently. If the game would not allow you to build your own roads, then I could load them from disk. But now, when you have a straight road and place a road tile next to it, that straight road needs to be transformed into a T-junction, so I can't have pre-made models. If you ever played Transport Tycoon, this is what I want to create, but in 3D where you can drive your own vehicle while other vehicles (that you own) transport goods from one factory to another. Plus you can do GTA-style missions and a lot more. It's actually a combination of Transport Tycoon, GTA and X2 (a spacesim from Egosoft). Not that you'll be able to fly your own spacecraft, but the trading system (dynamic prices for goods based on stock) and missions will be in my game. Those missions where given to you (in X2) in spacestations and required you to bring some goods (microchips for example) to another factory because of a computer-malfunction or something similar. Or they wanted you to get some goods, because their stock is low. They paid you the maximum price per unit you delivered plus some bonus if you delivered the goods within the timelimit. Something like that. I've seen a bit about C++ on highschool, but the syntax is quite complex for me. Once on this forum I read that you need several pages of code in C++ just to generate a 3D-capable fullscreen engine, where Blitz only needs 1 command. And that loading 3D-models is a lot more code too, unless you search the web for some finished code to do what you want. If that's true, I don't know, but I know that C++ is something too complex for me. A while back, they did some speed-comparisons between C++ and Blitz (like counting to 1.000.000) and the results where about the same, so I guess Blitz3D is fast enough and easy to use. For me, working with Blitz is faster than c++, because I know a lot about Blitz3D and almost nothing about C++. Converting to C++ would require me to learn another programming-style and syntax, while I'm already working with 2 programming environments (Blitz and Visual Basic). |
| ||
Thats cool. Our interests sound similar. I've actually been working quite a bit with Visual Basic Express 2005 lately. Do you spend a lot of time pondering about problem solving and algorithms? Have you started writing this game or are you in the planning stage? I'm writing an rts engine thats completely customizable from a windows gui, which will be created in visual basic. One thing I've been planning is..... Visual Basic will write to a text file which will then be read by the engine. But I'd like to make something more "tamper proof." For instance create my own type of encryption. Or even better, create a file format thats encrypted. Any ideas? If I were to change the extension to a text file, for example.. to .rts, would blitz still be able to read it as a text file??? |
| ||
I spend a lot of time about problem solving, that's correct. Even at work, when I'm doing my job, I'm busy thinking about how to do things in my game (and still being able to do my job good too). My game is still in the planning stage, but I've started already with writing some test-code to see if the things I need can be done. For now, everything I've tested works perfectly. I've written some database programs within VB6, but they just use plain ASCII-text files, no encryption (yet), because all these programs will be used by myself only, so I can't help you with encryption algorithms. Even if you removed the extension from a file, Blitz can read it as a normal text-file. Blitz can read any file, just as long as you know how data is stored in the file to read it properly, otherwise you get some strange results (wrong data). If you would write an integer to a file in binary, you write 4 bytes. If you were to read it as plain text, then your data is screwed up. When writing data to a file, write it in binary. When people see some strange stuff in your file (not plain readable text), most people don't touch that file. They would like to change some things when the file was a plain ASCII-file that can be read using Notepad and see how it impacts the game/program. Image a game where you need money to buy stuff and you save the game as a plain text-file like this: LocationX = 2569 LocationY = 4888 LocationZ = 471 Money = 19 Here most people will change the Money value to some greater value, load their game and say: hey, I've got lots of money now, easy. But if you write the values in binary mode, then they would need a Hex-editor to figure out where the money-value is stored, how it's stored (most significant bit first or last) and then change the value in hex. That's a lot more difficult, so most people don't even try it, because they need to do a lot of work, just to figure out IF they can change their money in the game. |
| ||
This is very interesting I also have been looking for code like this. I was wondering if this could be used to make a 3D terrain system to make heightmaps.. If so could you make a example I have been trying to do this for weeks!!! |