Jump to content
  • Advertisement
Sign in to follow this  
wurstbrot

3D Generating curved linear meshes through automatic joining of hand-made pieces

Recommended Posts

So...a couple of weeks ago, I restarted work on a long-term project of mine, a virtual model railway game. One cool feature I'd like to have in it is automatic generation of 3D models for structures along the tracks, like bridges, station platforms, catenary, and of course, the tracks themselves, based on short pieces manually modeled and textured by the artist. For example, if I want to have a stone arch bridge on a long, curved section of the track, I'd like to model one of the arches with a tool like Blender and automatically combine multiple instances of it in the game to generate the final bridge.

In the first prototypical version of the game, I solved this in a very primitive way by calculating the position, orientation and scaling of each part (and of course also the number of required parts in the first place) and adding them to the scene otherwise unmodified. This works okay-ish as a first approach if the curvature of the track is small and the pieces are short. However, with smaller curve radius, the ugly overlaps of the parts where they are (not) connected become very visible very quickly.

For the new version, I'd like to do this in a more fancy way and connect the pieces seamlessly. My first idea for this was to manually define just 2D cross-sections of the mesh and generate the full model from that. However, this would greatly limit the possibilities for geometric details (the exact same cross-section along the whole mesh, like from a Play-Doh extruder) and now allow texturing and preview with standard tools. So, my new idea is to use normal full-3D pieces and connect them by joining the vertices at their ends.With some rules/restrictions (vertices with same coordinates except for x on both ends, forming planar ends that can be matched easily), this shouldn't be too difficult. But is it also the best way to do this? Is there some sort of default/best-practice solution to this not too uncommon problem? Some idea better than mine?

Thanks in advance :).

Share this post


Link to post
Share on other sites
Advertisement

Sounds like you want something like this: 

Instead just extruding a shape, you could use orientations along the curve to 'skin' your mesh pieces. Using the same matrix skinning used for characters usually.

IIRC i have used a bezier spline in the example, and in the level editor the user would alter the control points of this curves together with the rotation at each knot. Models should fit seamless together if you make sure only the end knot matrix affects the end vertices.

 

Share this post


Link to post
Share on other sites

Yes, this comes pretty close :).

Two differences: First, instead of Bezier curves, I use circular/arc segments. But this doesn't change the general principle of course. Second, like I said, I don't want to be limited to extruding a 2D cross-section, but bend and seamlessly join full, manually created 3D models. To use the example of a stone arch bridge again: Such a bridge has pillars, and an arch between each pair of pillars. In the minimal case, the bridge consists of two pillars (one on each end) and one arch between them. The manually modeled piece would most probably be one such minimal bridge. Now, if the bridge gets longer, I'd like to be able to join multiple of these pieces together, forming a longer bridge with multiple pillars and arches. At the same time, I want to automatically bend the pieces to fit the (potential) curvature of the track (curved bridges are not very common, but they exist, and I'd like to use the system for many other track elements, too).

I'm not looking for a detailed implementation guide - I think I can do whatever solution I finally decide on. It's more a question about general concepts/ideas.

Edited by wurstbrot

Share this post


Link to post
Share on other sites
48 minutes ago, wurstbrot said:

I use circular/arc segments.

This makes it a lot easier. (Although bezier could do this as well - they can form circles.)

Would this be all you need?

And does just looking at it give the answer already? It's just measuring distance along up vector to the gizmo origin and using this distance as arc length for the the transformed vertices. The angle gives the center of the cylinder it bends around.

 

Edited by JoeJ

Share this post


Link to post
Share on other sites

Yes, I'll try it that way. The detail I spent the most thoughts on is how to actually join the pieces together by merging their respective end vertices. In order to do that, I need to make sure that both ends of a piece consist of vertices that each have a identifiable "twin" to merge with on the other end. This, too, is not really difficult, I can simply compare the vertex coordinates and match a pair if both have equal y and z values, or something similar. But it needs to be taken care of when creating the mesh pieces, and some coding to do the matching.

However, I can even do without this, at least for a first version. I need shared vertices to calculate vertex normals for smooth shading, but that's something I can still do later.

I'll now try to implement my solution. I'll keep you updated with progress!

 

P.S.:

Quote

Although bezier could do this as well - they can form circles.

Not really, as far is I know.

However, the main reason why I'm using circular segments is that Bezier curves are really bad to analyze mathematically. There are no easy, clean ways to determine their length, the partial length at a given x value (or vice versa), the direction or the curvature at a given offset. For all this, you need to discretize them and approximate the values numerically. For circular segments, all this is fast and easy with a tiny little bit of simple trigonometry.

Furthermode, fiddling around with control points to achieve the desired shapes (which, in my case, will always be circular segments anyway) is unnecessarily complicated from the end user's point of view as well. Working with circular segments directly just produces what I need in the most simple, straightforward way.

Edited by wurstbrot

Share this post


Link to post
Share on other sites
52 minutes ago, wurstbrot said:

Not really, as far is I know.

However, the main reason why I'm using circular segments is that Bezier curves are really bad to analyze mathematically. There are no easy, clean ways to determine their length, the partial length at a given x value (or vice versa), the direction or the curvature at a given offset

If you draw a vector circle in Adobe Illustrator or Photoshop, they are made of bezier splines with 4 knots (also all fonts are made from it, for example).

The direction can be calculated easily, i call it 'tangent' in my code.

For human editing they are very intuitive. To make it easier you could constrain the handles of adjacent segments to have opposite direction to enforce continuity (C2, if you also constrain the handle lengths to have equal length). In my code i did calculate all of this automatically and only the knot positions are given by data, IIRC.

So it would be very flexible, but if you are sure arcs do then of course it's easier, and stuff ends up really round (with my skinning suggestion you would need a lot of bones for this). Also self intersections can be prevented easier with arcs.

Arcs likely force you too keep all designs on the plane, so 2D. To overcome this you'd need to join many arc segments but curvature can't be set at will and intuitively then. (If you aim for 3D, this could be the major problem i guess)

 

 

Share this post


Link to post
Share on other sites
10 hours ago, JoeJ said:

If you draw a vector circle in Adobe Illustrator or Photoshop, they are made of bezier splines with 4 knots (also all fonts are made from it, for example).

Okay, I admit, I'm no mathematician ;). I only read the claim that Bezier curves can not represent real circular segments on a website about the topic which I consider very good ( https://www.redblobgames.com/articles/curved-paths/ ), so I believed it and just quoted it here. In addition to that, I can "confirm" it from my own subjective, visual observations, too, but that's no proof, of course :D. Whether or not the statement is true in a strict, mathematical sense, I don't know.

The thing is, circular segments are really a million times better for my use case. With circular segments, all the values that I need are easier and cleaner to represent and calculate, and they automatically result in the type of shapes that I need without any extra constraints. Bezier curves make no sense for me at all, with the much better alternative of circle arcs available. I know because I have tried Bezier curves before.

The limitation to a 2D plane is no problem at all. Like I said, I use them to describe railway tracks, and railway tracks are mostly flat, they don't go in wild loops through the air. Of course there is elevation, but I can simply represent that with a vertical axis offset in my segment end point / node coordinates and interpolate between the end node heights to get the height offset at arbitrary points along the track segment.

 

Edited by wurstbrot

Share this post


Link to post
Share on other sites
1 minute ago, wurstbrot said:

Okay, I admit, I'm no mathematician ;). I only read the claim that Bezier curves can not represent real circular segments on a website about the topic which I consider very good

I'm neither ;) But the webpage shows bezier curves with 3 control points, which are rarely useful because the middle controlpoint rarely can be aligned to the tangents at both ends, so you end up with restricted curve design or non smooth corners.

My code (and the adobe stuff) uses 4 control points, so you can align the connection at end points to adjacent curves without restrictions. (One can use as many control point as he wants, but 4 is sweet spot.)

I assume 3-beziers also can not form a circle, yes.

blah blah...

I suggest you play around with a vector design tool like Adobe or (i don't know freeware... Inkscape? Gimp?).

9 minutes ago, wurstbrot said:

The limitation to a 2D plane is no problem at all.

Then arcs is fine.

Bezier is still more flexible, and you might want to try it out without programming to be sure about the difference. But in no way i want to convince you to use it. (Catmull Rom is another option - easier to grasp but in the end still harder for manual design because there is no direct tangent control.)

The pro of arcs is the perfect geometry you'll get without much math work.

Share this post


Link to post
Share on other sites

I used Bezier curves with four control points in the first version of the game, because Bezier curves were my first idea for this. In the end, they were number three on my list of the major pain points why I abandoned the entire code base and restarted from scratch with better ideas for many things. Backed by two years of railway game dev experience.

'nuff said, I guess 😆

Let's get back to the original topic 🙂

Share this post


Link to post
Share on other sites

Here is my first result, the arch bridge use case I was talking about, in a "slightly" unrealistic way 😀

Since the new version of the game has no 3D interface yet, I exported this generated mesh from the game to a Wavefront .obj file and rendered it with Blender. The mesh is generated from a hand-made straight bridge model piece with one arch and a half-pillar on each end (see second screenshot below). That piece is repeated and curved to follow the track. The mesh is not just rotated as a whole, its vertices are displaced to "bend" the mesh, fitting the curvature of the track- that's not very well visible in that image).

bridge.thumb.jpg.9a3b059ec76def45e424b305d9cee53f.jpgarch.thumb.png.0544f9aac747f6976f54f6abc9ab9058.png

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!