Meshed Out!

Technical impact of meshes

This will certainly require much more than my humble perceptions to adequately qualify, and, as tests are being done on Aditi, and Linden lab continues to gather data from all viewers participating in the testing, I hope that they release some reports based on real data. Nevertheless, we can extrapolate from the theoretical impact, and it should be dramatically positive.

Why? Let’s not forget that Second Life is all about meshes (except for avatar impostors!). A prim is just a mesh. The difference is that the mesh is stored locally on the client, and the SL Viewer only gets its position coordinates as well as a series of parameters to apply to it. But SL’s rendering engine is a mesh engine, like all 3D engines. There is nothing but triangles, and that’s what’s processed by the engine and the graphics card.

A plywood cube can have as little as 12 triangles (2 for each face) and just one texture, replicated on all 6 external faces and one internal face. So it’s a very simple mesh and one that is rendered blazingly fast. But most items in SL aren’t plywood cubes. Instead, prim torture deforms the mesh, and, in most cases, keeps adding polygons to it. A mere resize will just make the triangles bigger; but path cut/taper/shear will add more triangles. Many, many triangles. And, of course, if you’re using a torus or a ring, the number of triangles in it will be huge (you can visually confirm this by selecting the Wireframe mode in the SL viewer), as the SL Viewer will create a mesh that fulfils the parameters set on the Build tool.

So the reasoning behind having prims instead of full meshes is not because of the rendering engine, which will just handle meshes anyway: it’s just a way to save bandwidth and storage costs, because SL doesn’t need to store all mesh vertex data (i.e. the triangle points): just the type of basic primitive and the transformations applied to it, which have a fixed amount of parameters and are common to all prims. This saves bandwidth when transmitting complex models, at the cost of some mathematical transformations on the rendering engine which has to convert all that compact information into the appropriate mesh.

Now, storage costs are really negligible these days. Bandwidth is another story: sending the “prim torture” parameters for a very twisted torus just requires a handful of bytes, while sending the whole set of vertex points for a mesh describing that same torus will require much more bandwidth. But… how much more? Right now, figuring out the exact amount is a bit mysterious. Remember that no matter how cool and how complex the mesh will be, there will be an upper limit on triangles to be sent: meshes will be converted to “prim equivalents” before upload, and there will still be an upper limit of 15,000 per sim. To make the calculations more complex, meshes will be uploaded at different levels of detail (LOD), which means that if you’re too far away to see the whole mesh, you’ll just get the “lightest” version first, which should download quickly — as your avatar comes nearer to the object, meshes with increasingly higher levels of detail will be downloaded. This naturally saves bandwidth and is a typical way to save not only bandwidth but also rendering time: it’s worthless to try to display 100,000 triangles on an object which will appear to be 5 x 5 pixels in your screen!

In general, though, I think it’s safe to assume that LL’s algorithms to calculate “prim equivalents” for a mesh will give similar results in bandwidth costs for a mesh than downloading the corresponding assets for the same amount of prims. Thus, a complex mesh with, say, 1,000 “prim equivalents” will take about the same time to download as the asset data (e.g. prim torture parameters) for 1,000 prims. I’m quite sure this will not be exactly the same, but, well, the order of magnitude will the same. Also, while a standard cube and a heavily tortured one have exactly the same bandwidth costs, the rendering costs are entirely another story (specially when they have an alpha’ed texture applied on them!); while a mesh is a mesh. Once you have the data for all the triangles, a mesh will require rendering time directly proportional to the number of triangles; while a heavily tortured torus or ring will take way longer to render than a 1x1x1 plywood cube, even though both will take exactly the same amount of bandwidth to transfer. Thus it’s a trade-off: rendering time and bandwidth requirements for a mesh depend ultimately on the size of the mesh (larger mesh = more triangles = more bandwidth costs = more rendering time), while for prims the bandwidth cost is exactly the same, but the rendering costs vary wildly depending on the level of prim torture (which creates far larger meshes for that prim).

But then there is a huge cost saving on complex objects. I’m sure that Linden Lab has some statistics saying how many prims, on average, an object has — if we look at prim hair and boots, I’m sure that 50-100 are average 🙂 Multi-prim objects, although taking the same amount of time to download as individual prims all added up together, are also differently dealt with. First, in terms of physics — and remember this doesn’t apply merely to the special effects enabled by the physics setting on the Build tool; when avatars walk over an object, even if it is not set to physical, this will require handling by the physics engine underneath (which has to validate, for instance, that the object hasn’t a “hole” for the avatar to fall through it). Secondly, in terms of occlusion. And thirdly, in terms of texturing.

The impact of the physics engine is hard to estimate, because physics are “approximated” by bounding boxes around objects on a broad scale for first calculations, and then, when needed, additional detail is brought into consideration. That’s why when you walk very quickly across a prim surface with lots of holes due to misaligned prims, your avatar might not immediately fall through — but if you walk very slowly, this might actually happen! (in some cases, the reverse might happen). This has mostly to do in the way the physics engine, to minimise calculations, might just use a “rough” bounding box collision calculation to give a preliminary result.

You might see this at work with sculpties. Some first-generation sculpty terrain elements (like rocks and such) had a very strange effect on avatars: they would simply “float” over it, as if the object was not really there, or far larger than in reality. Subsequent generations of sculpties have adequated the underlying physical model more closely to the actual surface of the sculpty, but in some cases, people simply set the sculpty to phantom, and add a regular prim on top of it with invisible faces: this will make the physics engine to forget about doing the math for the sculpties and just use the prim for calculating where the avatar is supposed to be moving.

With meshes, content creators have the option to define exactly where the bounding box is supposed to be. This might be used as an adavantage for, say, very detailed vehicle design: a reasonably “rough” sketch of the car can be uploaded separately of the highly detailed model to be rendered. This allows the physics engine (which runs on the simulator, and thus contributes to server-side lag) to make all the complex calculations for vehicle movement based on a very simple model, while leaving the rendering engines to deal with the complexities of the way the vehicle looks (which just causes client-side lag).

However, very complex prim-based models create an additional challenge, as prims can have holes or are just partially visible (prims inside prims, and so forth). The physics engine has to deal both with each prim individually, but also with the entire object — which is a pain and requires intense computation costs; that’s why LL has limited vehicles to merely 32 prims (each avatar sitting on it counts as one prim, so, the maximum number of usable prims is 31). Meshes will make these calculations much easier — the physics engine is supposed to be fine-tuned to deal with meshes, which is pretty much what every videogame uses 🙂

But even things that are not vehicles will certainly benefit from meshes. Consider a typical complex building: lots of prims are used to provide detail. Each prim is a solid with N faces, but only a few of those faces are visible. The remaining might be partially stuck inside other prims (the “walls”) and we expect them to be “invisible”. Yes, invisible to the user — but not to the rendering engine: for the SL Viewer, those “hidden prims” still consume precious triangles which have all to be accounted for — and then discarded because they’re not visible. Just because they’re not visible doesn’t mean that the rendering engine doesn’t see them! Rather the contrary: it takes more time to render something which is not visible to the user, because more calculations have to be applied to it to assert its visibility. This sounds to work against common sense, but it’s how it works… with an advantage, though. The advanced occlusion techniques of the recent versions of the SL Viewer deal with hidden objects much better (at least, when using opaque textures, that is, textures without alpha channels), and make a huge difference in the way objects are rendered.

The point is that with prims, the renderer has to account for all polygons for all faces, even if most of those faces will be actually hidden. And things become more complex with prim interpenetration: a prim sticking out of another prim has partially occluded triangles which have to be calculated separately.

Finally, even a cube that is sticking out of another prim and just has some of the faces visible will have textures for all faces (all needing to be downloaded separately). A common trick used by some content creators is to drop an invisible texture on the non-visible faces — that way, less textures are downloaded, and in theory, this should improve rendering time. I have my doubts about it, because the most commonly used “invisible texture” is actually a full-alpha texture, which will break occlusion and thus require far more rendering computation in order to be displayed — only to be dropped by the rendering pipeline, since that face is occluded. I really haven’t tried this out recently — at least, not since LL has introduced a new LSL parameter for invisible faces and adopted a “standard” invisible texture, which might not be a texture at all, but just a flag for the renderer to say “ignore this face, it won’t be displayed ever”. If that’s the case — and if a significant amount of content creators actually take the time to drop this “special texture” on all faces that will never be displayed — then, yes, this will improve the rendering time. I seriously suspect this not to be the case, though; content creators ought to get better results by painting the non-visible faces with a simple 32×32 “all white” texture instead. But… how many do make their buildings like that? Even professional 3D content creators often “forget” to paint the non-visible faces, they just apply the same texture — at full resolution and often with alpha channels — to all faces, no matter if they will be shown or not.

Meshes change all this. A meshed object in theory has just two conceptual “faces”: inside and outside. Of course, complex objects have multiple meshes and sub-meshes, but each, at least, has “nothing” inside — it’s just “outside” for all purposes. This will reduce rendering time dramatically. Of course, occlusion calculation will always be needed, to deal with objects moving in front of each other (and nothing prevents you to “stick” meshes inside other meshes or other prims!), but I can imagine that a lot of triangles will be saved that way. And I really mean a lot.

Consider a simple scenario. As said, a cube has 12 triangles. An object made of 8 cubes (i.e. a cube made of cubes) will have 96 triangles for the rendering engine to deal with — but the “outside” only has half of that, i.e. just 48 triangles. The “inside” triangles which will always be hidden are still going to be sent to the rendering pipeline, even though they will never be displayed at all. SO you’re wasting triangles and wasting computing time when rendering that object. A mesh would only need those 48 triangles (well, actually, it would use even less, since you’d just need to have a bigger cube — meshes can be at least 64 x 64 x 64 metres big), thus saving half the rendering time. You can easily see how this adds up — a 3 x 3 x 3 cube made from 27 prims stuck together would have 324 triangles, of which only 108 would be visible (just a third!). As objects get more and more complex, you can start to see how most of the triangles used by a prim-based object are all hidden and never displayed, even though they need to be calculated by the rendering engine! And this grows exponentially…

This, I think, is an area where meshes will have a huge impact over equivalent prim-based design. The more complex the object, the more likely it’s going to be way, way less costly to render it if it’s a mesh. At some point, the cost of sending those extra vortex data will compensate far more the additional rendering costs required by prim-based objects. Thus, the notion of “prim equivalents”, which will be based on the amount of data required to be sent will probably just reflect bandwidth costs, but, for meshes with a high number of “prim equivalents”, the actual rendering cost will be far lower than for the equivalent number of prims. This, at least, is what LL is expecting…

Extreme cases are, of course, avatar attachments like hair. In order to “simulate” the richness of real hair, designers have no other way but to get 100-250 heavily-tortured prims, all intersecting and interpenetrating each other, often mixing sculpted hair with flexiprims to achieve better, more realistic results — and that they certainly achieve! Even though the texture count is usually low (most designers I’ve bought from use 2-6 textures, at most; they just get cleverly applied), the sheer amount of triangles — most of them never visible — coming from all those tortured torii and rings have a huge impact on the rendering cost. Now all that can be replaced by a relatively sophisticated hair mesh, which can replicate much more closely the way hair is shaped and moves, and save all that massive amount of triangles. Perhaps with as little as 1000-5000 triangles you can get better results than with 250 heavily tortured prims — which can have, say, 50,000-100,000 triangles! (As a comparison, the whole SL avatar mesh just has merely 7,500 triangles, and, even so, it’s a considerable improvement over many popular games)

And finally we have textures… what has impressed me most on all those easily-downloadable Google 3D Warehouse models is how few textures they use. The trick, of course, is called UV mapping: you can “wrap” reasonably-detailed textures around the whole mesh, and “paint” the mesh directly with all details you wish, and save it to a “wrappable texture” which gets uploaded. This is pretty much what fashion creators (even amateur ones!) have been doing all the time using the clothing templates (which are simply UV maps of the avatar meshes). The advantage, of course, is that meshes (like sculpties, too) will consume far less textures than the equivalent amount of prims.

In terms of bandwidth costs, this is easily a huge advantage, which might more than compensate the additional bandwidth costs for downloading a complex mesh instead of a certain number of prims. But even rendering might be easier: applying textures to tortured prims is costly, too, and you can notice that when using the “planar” setting for textures on tortured torii or rings; even visually, it takes a bit more time for the texture to be applied! Now applying textures to very complex meshes should also take some time, it’s definitely not a walk in the park, but the good news is that your graphics card is supposed to know how to do that in hardware… and even be able to apply all sorts of special effects on top of it, too.

So this is the theory. In general, I believe that a mesh-only rendering of a scene will be way faster than the equivalent rendering of a prim-only scene. It will have far, far less triangles. It might take a bit longer to download all the models, but, on the other hand, it will use far less textures, and they will be applied faster anyway. Moving on top of those meshed objects will also be easier on the physics system, and meshed vehicles should respond better (and faster) while also look much nicer. This is what I expect to happen based on theory. In practice, of course… we don’t know yet 🙂 I’ve tried to walk in the “Mesh City” sim on the Aditi grid, and it certainly took a long, long time to load. But… there were also a lot of avatars around, and Aditi, well, is just a preview grid, running on older (and slower) hardware. It’s not supposed to be able to handle huge loads of users anyway. So how fair is the comparison?

Right now, there is really just one way to try it out: create a lot of models using heavily-tortured prims and the equivalent using meshes (there are some applications to convert between both) and experiment the differences 🙂 I’d be certainly interested to see how well they fare.

Notice, however, one technical caveat. Linden Lab is not going to port meshes for the “old” SL 1.23 viewer codebase: this is a 2.X development only, and will remain so. This means that adoption might be slower than LL might expect. The good news is that several third-party viewers are going to switch over to the 2.X codebase, while changing the UI to be more pleasing (that is, looking more like the 1.X UI). Of course this means some development time; Imprudence, which is currently showing off some early versions of version 1.4, after stabilising and releasing 1.3.0, has just planned to switch over to the 2.X codebase with version 1.5. Kirstens Viewer is currently the only third-party viewer fully supporting the 2.X codebase. We’ll have to see over time if the extra features of the 2.X codebase — Media-on-a-prim, alpha & tattoo layers for avatars, outfit support, meshes, Display Names — will be enough to convince third-party viewer developers to switch over to the 2.X codebase and tweak the UI (since it’s clear that Linden Lab will not change the UI much except for some minor details).

All in all, these are exciting days for Second Life, and I believe that the final barrier for massive adoption by content creators (not for the mainstream public!) has finally been lifted. For users, it just means far better and more realistic content, which might even relieve lag problems, and a Second Life that will look completely different in a few months — we’ll all be laughing at how ugly it looked in the “olden days” of 2010…

Print Friendly, PDF & Email
%d bloggers like this: