2

enter image description here I am trying to generate a race track in Vertex Shader(constraint) and only using B-Spline/Bezier/Hermite curves. My problem is that when i try to widen the obtained curve by translating another instance of it (lets say translate the x value), at certain turns, the road gets thinner.

As input, i can only have a certain number of control points/knots with which to generate a 2-degree closed(start point = end point) curve B-spline. The closed curve (translated on Z) is shown in the picture attached. The camera is positioned right above it. Every vertex from the curve has Y = 0, seeing how the track is flat without any height(no perspective view).

Is there any possible way to keep the road's width on all its sections?

Rowan
  • 23
  • 3
  • Can you be more specific? What is the specific implementation you are using (i.e., input data and code) and what is the expected, and actual, output? –  Oct 23 '14 at 22:21
  • I added info on input. The main problem is that, given a close curve, how can you generate from it a track that may have U turns, in which case, translating the vertices will not give it any width in those sections? – Rowan Oct 23 '14 at 22:34
  • Can you provide pictures? I'm still not clear what you are seeing as a problem. I also don't think it's possible to see how you're arriving at that problem without more information about your specific shader. –  Oct 23 '14 at 22:35
  • I have added a picture... it's the track as seen from exactly above it, y = 0 in every vertex. At the far left/right, the track gets thinner. I don't think it is a shader specific problem, more of an mathematical equation or so? – Rowan Oct 23 '14 at 22:49
  • That's not a perspective projection, I assume? What is the math you are using to "widen" the spline into vertices? It looks like you're just sampling the spline and widening it by adding +/- some offset to the Y coordinate, rather than trying to offset the split along the normal vector of the spline at the sample point? –  Oct 23 '14 at 22:54
  • Indeed, I am just adding +/- offset to Z (Y is 0, the track is on the floor), that's why it isn't working. Can you give me more details about the last part of your comment? – Rowan Oct 23 '14 at 23:00
  • Oh, now I understand your answer, but unfortunately I've never done this before. Can you tell me how to compute the normal vector in a certain vertex in the curve? – Rowan Oct 23 '14 at 23:13
  • Yes, when I get back to a real computer (on phone right now). Can you edit all the clarifying information you've provided in comments into your question? Then I can re-open it, and I (or somebody else) can provide you the answer. –  Oct 23 '14 at 23:14
  • (The short version is that you can compute the tangent and normal via derivatives, as described here). –  Oct 23 '14 at 23:21
  • You may want to use your original path as the track center, and create a left and right edge by adding two offset-curves. Then your original path is useful for the safe usable part of the track.

    If these are curves controlled by spline handles (cubic beziers, like Illustrator curves) you might need to fine tune their lengths by whatever proportion the two adjacent vertices' distance has changed. One last gotcha if you "thicken" the path too much, the curves might misbehave and cross themselves.

    – david van brink Oct 24 '14 at 01:18

2 Answers2

2

This is a known issue. One of the best and most suitable solution would be to use a library like this one Clipper

There are other known ways that are more complex and not open source yet.

http://www.angusj.com/delphi/clipper.php

Another solution would be to form the track as a spline from Béziers and then convert it to a rigid spline by sampling points along the path. You then use this point with the vector of their approximate direction of flow which could be computer by deducting the previous point from the next point on the road to compute where the left and right sides of the road need to be. To get a smoother result, apply a Bézier on the resulting borders like this: How do I generate a smooth random horizontal 2D tunnel? and add a bit of noise too.

enter image description here enter image description here

In this step you extend the sampled points on the spline into egdges by picking two points in a 90 degree angle from the direction of the spline.

enter image description here @Trilarion enter image description here

AturSams
  • 10,517
  • 1
  • 32
  • 58
  • Great answer! Now one would just need the math to create perpendicular lines of a spline. If I have time I will work it out. – NoDataDumpNoContribution Oct 24 '14 at 08:19
  • 1
    You take a point that is epsilon behind and epsilon ahead of the current one and then compute the angle between them, after that you rotate by 90 degree in each direction. In this case you could take the previously sampled point and the next one. – AturSams Oct 24 '14 at 08:23
  • @Trilarion pn+1 is the position of the next point (x, y) and pn-1 is the position of the previous one. :) – AturSams Oct 24 '14 at 08:35
  • Thanks for the formula. I wish I could upvote more than once. :) – NoDataDumpNoContribution Oct 24 '14 at 08:41
  • A good answer indeed, but on Vertex Shader, let's say I can compute the positions of Pn-1 and Pn+1 because i know their gl_VertexID, i compute atan2 and obtain the angle... and then I compute Pn+1 - Pn, i normalize the vector, rotate it by (angle +/- Pi/2) and that gives me the perpendicular position, right? – Rowan Oct 24 '14 at 11:34
  • I'm curious, is there a good way to deal with self-intersection problems when the curve is too narrow (a very quick 90 deg turn)? – Lake Nov 17 '16 at 17:42
  • Yes! There are good ways. Could you ask this as a separate question and link me to it? Generally, these are not caused by the 'quickness' of the turn but the amount of sample points. One trick would be using less sample points intentionally and then creating the smooth curve from a very rough low-sampled route. – AturSams Nov 30 '16 at 13:45
1

Instead of simple shift, you need to widen the track by calculating a perpendicular in every point and shifting the contours along it inside and/or outside.

enter image description here

Kromster
  • 10,643
  • 4
  • 53
  • 67