-
Notifications
You must be signed in to change notification settings - Fork 23
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Planetary collisions #1
Comments
Hello, thanks for your interest in this project. I thought about collisions briefly but didn't put too much time into it (yet). I don't know where the performance hit comes from, did you try to use the Godot profiler to find out what's using up cycles? |
I simply called mesh.create_trimesh_collision() for each generated face on its creation. The problem is that collision shapes contain too many vertices and therefore the collision calculation has to process a lot of data. The solution would be (I guess) to generate a multiple collision shapes for each face, which would allow for hierarchical search of close collision shapes (i.e. ship colliders and only nearby terrain colliders). Godot has a build-in function for that, unfortunately it not accessible via GDScript. Only from engine code. So the solution would be either implement a wrapper function into the GDScript to create the access to the method from the source. Or, one could create a c++ module and access it directly in the engine code. |
For general, inaccurate collisions, (think planet vs. planet) a sphere shape would suffice. Well if you create a collision trimesh for every generated chunk, that's a lot of high resolution colliders to check against. If you have a mesh resolution of 100, that's 100*100=10000 vertices or (99^2)*2=19602 triangles to check against for a single terrain patch! Also, you'll have to disable the colliders of invisible lower LOD meshes or you'll collide with those as well, which might be part of the innaccuracy and performance hit. So as you can see, a performant terrain collision system has to be thoroughly planned, I've thought about ways to implement it and it's definitely on my list. Help is welcome! I'll push some big changes in the next days by the way, many parts of the now-addon have been overhauled. |
Indeed. Maybe I don't understand the collision system correctly but I did a simple experiment. I set the generation of the collision shape only for the closest planetary face. Then in the editor, I created the ship collision shape using a "single convex collision sibling" made from its mesh and tried a collision of the ship and the planet face. I got barely a single fps. Then again in the editor, I changed it to "multiple convex collision siblings" and I got a dramatic performance gain - if the ship stayed inside the actual terrain face (no generation of the new ones) I got solid 50-60 fps. Therefore, I concluded that the collision detection is only performed between the closest collision shapes (which would make sense). If this is correct then when the faces are generated as multiple collision siblings as well, maybe the performance would increase even more. But I could be wrong of course. It is possible to use a build-in method for this as I stated in the comment before or maybe it could be done manually based on the generated face vertices that you already have. I also found a hint on the godot forum where they used PhysicsServer to set the faces of the collision shape manually but as I stated in my first comment, I didn't make it work. But yeah, you can always create the collision shape only for the closest planetary face and leave the global collisions to a single (planet sized) sphere collision shape - that would indeed be sufficient for a planet-planet collision while the player collision with the surface would be accurate enough. Another way would be to pre-generate both the vertices and collision shapes for each face LOD beforehand and only load those that are currently needed in run-time. That would even speed-up the performance of the whole planet as random generators are notorious performance eaters. Anyway, I am really looking forward to your planet overhaul! ;) |
The engine by default does a broad phase and a narrow phase, it should only check against nearby collision shapes anyway. I'll have to look into it soon. By the way, heightmap collision shapes just have been implemented for Godot Physics: https://twitter.com/PouleyKetchoup/status/1379603423398535174 Perhaps this could be beneficial? Though the terrain here is a curved mesh, so it won't be that easy. |
We can definitelly make some iterative experimentation here and try to find the best solution. I've created a planetary_collisions branch as a playground for this purpose. |
So I'm still working on a more robust multithreaded job system for better maintainability and performance. It's kind of functional now, but I'm still debugging some hard to narrow down issues with the threads (multithreading is a beast). |
I was struggling with the collisions lately. Don't have a valid solution the way we discussed it yet. Maybe I'll focus on something else and leave this one on you ;) |
Oh, you actually continued to work on it? Which route did you take, |
Well I created a separate scene with StaticBody and Collision shape and instantiated it for each TerrainPatch. Then I tried to inject the mesh data into CollisionShape but it didn't work and as I was in a separate thread I couldn't debug it directly. I did't even got to the PhysicsServer part. But I have a working example of PhysicsServer. I'll send it to you. |
Okay. In the old version of |
I created a skeleton of the solution using PhysicsServer but as before, it doesn't seem to work. I pushed the current state to the planet_collisions branch so you can have a look if you want. Maybe you'll see something I missed. If I somehow make it work, I'll let you know. |
I had a quick look at the code, it's looking good already, but yeah, apparently there are no collision shapes yet and it throws a lot of physics errors (also had it crash once). One problem is probably that it's not possible to instantiate and use any physics nodes from another thread as far as my research went. We'll have to use the I also think that we can't use a heightmap collision shape, because the vertices of a terrain patch only look like they're flat, but are in fact warped onto the planet sphere. Also, a heightmap may only be able to face upwards. A trimesh (convex collision shape) should work better, like you did before in your first version of this, it was rudimentary but collisions were there. By the way, you can either use the |
Alright, I built upon your work to create a physics shape (concave polygon shape) and body at runtime using Edit: Oh and also, after you restructured the |
Now that you mention it, I'm not quite sure whether setting the space is actually needed, I didn't test without it yet.
For 1. it may help to just limit the speed at low altitudes / when close to the planet, which makes sense anyway. Two other pending things are:
|
Okay, I implemented the collision toggles Actually, I reverted the merge because performance is not yet stable, also the multithreading crashes from #9 will have to be solved first, then we can properly take care of making physics better. |
Right. It's crucial feature. Let's not rush this. I'm sorry for not helping too much lately. I am really busy these days but as soon I can, I'll participate more often again. Btw look what I found: https://www.youtube.com/watch?v=KfphtLRoUB0 Maybe we could create another type of planets - Gas giants... |
Yes. In the latest commits I was able to fix the crashes that occured before, though I'm not quite sure how to best continue with physics, because these complex trimesh collision shapes tend to really tank performance. Perhaps scaling the planets up to a reasonable level (e.g. 1 GD unit = 1km given the single precision floats) will remediate some of the issues as colliders get less dense.
Hey that's not a problem at all, I'm not expecting anything but am happy about any help. |
Just out of curiosity, are you two programmers who work full time? I'm currently learning to program (I'm a beginner). I will try sharing this project with others who may find it interesting who can contribute to it. |
I work full time, but I'm not a programmer by definition, altough I do it a lot for work. Thanks for sharing the project, that's great! |
I also work full time and apart from other things I also do some programming. |
So I found that PhysicsServer is not completely multithreading-friendly in 3.x, but at least that should be fixed in 4.0: godotengine/godot#45852 The glitching (collider jumps below terrain trimesh) was also fixed by a higher collision margin, by the way. |
Making collision for whole terrain chunks is quite slow and gets trickier with bigger planets. Fast workaround could be to create collider object which follows the player/enemy/whatmeow, but also sticks to the planet surface and rotates to aproximate slopes as well as it can. Should also ignore all other objects to avoid strange collisions. Creating that for too many objects could of course be performance issue and I don't know what would be the answer for that (bullets for example). I've used that kind of collider in Unity with Space Graphics Toolkit with realistic sized planets (Earth, Mars) quite successfully. It's not perfect, but it does the job when the planet is big and the slopes aren't too steep or detailed. //Edit: Space Graphics Toolkit has feature which allows you to stick object to the planet surface and I think it uses heightmap data and noise to do that efficiently. Or whatever data is used to generate the planet. Seems pretty neat as that way you can calculate the position without generating the chunk as they are generated with the same data. It also samples the surrounding (I don't know how) within user specified distance and uses that for rotation, bigger distance gives smoother rotation, but if it's too big you might lose local accuracy. I use that maybe in a bit hacky way by first making the collider object copy the player position and then snappin it to the planet surface, could possibly be made better somehow. I have no idea how to actually implement any of that, but kind of an idea for a workaround with planetary collisions. |
Collisions need to be looked at again on 4.x. For now, collisions are disabled on the dev branch. I'll leave this issue open for that as well. |
Hey, nice to see that you are finding the library useful. in theory, setting the flag:
In practice, I haven't tested this yet on Godot 4. What did you try so far? |
Hi, thanks for taking the time to reply. |
Also, how can i make the normals on the mesh flat shaded ? like a low poly style type game. Thanks again, great project! |
Okay so I managed to fix my physics collisions by just adding my own static collision shape to the terrain patch scene by pulling the mesh data from the terrain patch mesharray after it generates. It works flawlessly now. Still would appreciate a how to for flat shaded normals. Thanks guys for making this project. It's by far the least bloated of the planet engines and it runs the fastest on mobile devices. |
Great to hear you could make collisions work on Godot 4. If you experience crashes you might want to try performing all operations on the
I thought the servers were thread safe but apparently they aren't yet. I ran into similar issues with crashes on Godot 3.x.
Apparently Godot supports a flat shading mode when passing The normals are calculated here. Each vertex normal is just the average of the edges leading to it:
|
Regarding the Physics server, i ended up ripping all the physics server stuff from the the code, as i did not understand how it works or even what the physics server is. I imagined it was meant for large scale planets or more complicated stuff and my game is more like a toy. I really only needed the physics to keep the units point down at the planet and once in a while ( every 60 frames more or less depending on the distance to the camera) check if they are floating to push them down to the surface. I added a collision shape to the terrain_patch as a child and the error i get is this: E 0:00:01:0785 terrain_job.gd:23 @ run(): This function in this node (CollisionShape3D) can only be accessed from either the main thread or a thread group. Use call_deferred() instead. I have no clue what any of that means. ( Only been using godot for like 2 months, came over from the Libgdx framework) ill read up on how to pass the flat keyword into the shader. Thanks! |
@VecterraSoft this means that the get_transform() function is being called from a thread which isn't allowed to read it just like that. Probably a change inside Godot's threading which affects how scripts can use threads while interacting with nodes, is my guess from this and the Godot 4 changelogs. I'll have to look at it in detail, but I'm not sure if I can reproduce it because I'd need a MVCE from you for that. |
OH! i see. Okay so limiting the worker threads to just a single one eliminated all crashes when generating terrain and the physics mesh. Usually when i play around it crashes within a 1 -2 minutes if moving around the planet. Now if i set _num_workers = 1 It has not crashed at all. Thanks! Also i was able to figure out how you store the verts so i could calculate my own flat normals! Haven't decided if i will stick with this look yet. Edit: For got to ask you. Would it be easy to have the patches saved and just hide them when not in use? To avoid re generating them again. For my small planets its not that many patches. The MAX_TREE_DEPTH is 4. So its probably a total of 380 patches. Patch detail is 16. I want to maybe preload some on start up. Since this game is for mobile devices. |
Any idea, how to implement fast enough collisions? I've managed to generate a convex collision shape from mesh, but it's slow and inaccurate. I am now trying to add a CollisionShape on runtime using PhysicsServer but with no luck so far?
The text was updated successfully, but these errors were encountered: