TheDuckCow / godot-road-generator

A godot plugin for creating 3D highways and streets.
MIT License
311 stars 15 forks source link

Flipped lanes made to appear connected #136

Closed TheDuckCow closed 2 weeks ago

TheDuckCow commented 7 months ago

See the demo below, where I have two road points which are facing the opposite way, ie the both have their "Prior Point Init" not yet set. This is between two different containers, but also happens for RP's within the same Road Container. Clearly, wherever we are doing the logic to match lanes on one side to the other, we need to check for flipped next/prior configuration.

The workaround: Avoid ever flipping the direction RoadPoints face. Not pictured here, but RoadLanes are also sufficiently messed up in these scenarios too.

https://github.com/TheDuckCow/godot-road-generator/assets/2958461/2d4494b6-8683-4ffd-85c5-e9b1d6cd0b99

TheDuckCow commented 7 months ago

Though I've identified the place the make the fixes here, the problem is posing to be a little more complicated - and requires putting some brain thought to actually figuring out the right changes to make. This is in a section of code that is already a stumbling ground for easy to make "off by 1" errors.

Created this test file in the meantime to make it easy to see all the issues. At least it's easy to see new changes take effect, as I can just press the refresh button on the Manager and see all roads update.

Screen Shot 2023-11-20 at 9 14 13 PM

I may not be able to solve this for v0.4.0 however.

TheDuckCow commented 7 months ago

I'm punting this one to v0.4.1 (at the earliest), as I don't want to delay the release any further. Though I've been playing with the function that should influence this, it's been resulting in even more distorted texturing. The design of the function may need to fundamentally change, which would be some work.

TheDuckCow commented 2 months ago

I'm making progress on this issue. The key issue I think has to do with this detail: the fact that we can have two road segments being the child of a single RoadPoint, if this is a RoadPoint that has occurred after a flip in direction. The issue is that the visual texture choices is driven by one RoadPoint, when really they need to be calculated separately... There's no simple workaround for this. So the main advice is to avoid ever having a change in the number or order of lanes between flipped direction RoadPoints.

https://github.com/TheDuckCow/godot-road-generator/assets/2958461/b521c5a0-9179-4396-90cb-e14fb4c1a61d

We could make a warning for this situation but still will be annoying for users to manage, and ripe for failure with the new bulk tools since road lanes will be added to one side but then flip and be added to the other. But, we'll still at least have an improvement. I still need to look into fixing the generated AI lanes, hoping it won't be too bad.

TheDuckCow commented 2 months ago

Nevermind! I realized that each RoadSegment manages itself in terms of added/removed lanes and so each one already does sampling from the source RoadPoint's lane order. The key was to reverse the index (i to -i) if we know the start rp was flipped. This has managed to resolve all texture cases! Still need to go on to fix the actual AI lanes:

Screen Shot 2024-04-28 at 10 35 31 AM
TheDuckCow commented 2 months ago

Ok the issue with RoadLanes is actually a little complicated too, along with the fun fact that there's multiple issues layered on top of each other.

First: Curves are overextending in the wrong direction on all RoadLanes, see how the bezier handle here over-extends the end of the curve itself.

Screen Shot 2024-04-28 at 2 24 35 PM

Second: Flipped connection orders when the end_point is reversed (this is the expected and more visually obvious issue).

Screen Shot 2024-04-28 at 2 28 27 PM
TheDuckCow commented 2 months ago

Though I've made some good progress, I'm still running into some edge/issue cases.

In this scenario, we have two RoadPoints pointed "away" from each other (ie the two Prior Pt's are the part connected to each other). The result is that one RoadPoint ends up being the parent for two RoadSegments. That itself would be fine, but, RoadLanes are now added as siblings to RoadLanes. Meaning one set of RoadLanes by name are attempting to be used for two different segments. In this case, we truly don't have any recourse and we'll just have a gap in RoadLanes created.

Screen Shot 2024-04-28 at 8 53 28 PM

I'm increasingly thinking that what we'd really want to do is create a utility which automatically "normalizes" connected RoadContainer points, so that they are always in one direction. We'd reduce a lot of this code complexity of having dual directions. Another option in this case is to create a duplicate overlapping RoadPoint at the same position at where two Priors overlap, so that we can know to safely skip one. But then we have to worry about keeping them in the same position etc.

Another short term solution would be to come up with another naming structure for the secondary RoadSegment of a RoadPoint, and use that to influence RoadLane names (though this then breaks all the rules that help pair RoadLanes together). Finally, last option would be to actually extend the length of the RoadLane, so there are effectively two points. That is also very complicated, as all logic so far is broken into per road segment. Likely not worth the effort.

TheDuckCow commented 1 month ago

Documenting this as I've needed to summarize it for myself several times, and what I'm planning to do with it:

As mentioned, half of the items above would be fixed with "normalization" where we go through and see which roadpoints are most commonly in one particular direction, and then flip the direction and connections of all other roadpoitns (physically rotating them 180º) so that everything is now going in order.

TheDuckCow commented 2 weeks ago

Logged this issue to represent the unfinished work here: https://github.com/TheDuckCow/godot-road-generator/issues/171