Reusing / sharing vertices

I’m constructing a class that uses custom meshes. In use I found I frequently want to use the same vertices multiple times for adjacent polys (go figure). Originally each vertex was created fresh on the spot as it was needed, but then I thought ‘couldn’t I just reuse the same vertex?’ This would let me save on RAM by reusing already existing objects instead of instantiating more.

Now for the sake of argument lets say the mesh is mostly static, as in its shape will change over time from the addition / removal of polys, but it won’t be animated. Once a surface is added it doesn’t move, it remains statically in place until it’s no longer needed. Would sharing / reusing vertices be a good idea here?

Yeah, thats what the index buffer is for afaik.

Alright, thank you for the amazingly fast response :slight_smile:

I only ask because I’ve worked with a few different engines in the past (admittedly only briefly worked with them) and some of the literature on them strongly warned against this practice, usually because it slows down processing at runtime having to trace back through references to the actual object. But given this is Java that argument doesn’t sound like it’d hold up seeing as the array is a list of references to vertices anyway regardless of whether or not I share them.

Thanks again.

99% sure that GPUs love shared vertexes also. I can think of a few different ways that it would let them optimize rasterization.

Edit: and the reduced buffer sizes definitely help with bus bandwidth.

Most excellent, consider this optimization done. Thank you all for the input.

Hey new issue in regards to implementing this. Vector3f is mutable, which makes it less than ideal for use in an object pool / hashmap. Is there a immutable version of Vector3f? Should I implement my own?

Since efficiency doesn’t sound like it is an issue, you might as well use vector3f’s toString as your key.

That I could, excellent point. But what about clients utilizing the vectors. I can’t guard against them changing the internal state of the stored vectors. Using toString will allow for immutable keys so the hash will work, but because the stored values are shared it would be preferable to prevent them from changing. Is there a convenient way to accomplish this?

Who is using your utility? Just tell them not to change the vectors.

At some point, users will screw something up no matter what you do. You kind of have to draw a line and say “don’t do this” at some point.

S’ok. Was hoping I could extend vector to make it immutable (I know it’s an ugly pattern but does work) but sadly the class is final already. Alrighty then

You can’t extend it to make it immutable because the fields are public… making 99% of the rest of vector use much easier.

I think this is one of those cases where speed of execution and performance has trumped strict oo design.

No I see that. Especially in the case of rendering software and heavyweight 3d mathematical computing I can understand that advantages of forgoing strict control over data. I’m just fighting against my current instincts here because school is trying very hard to hit home the values of strict oo design. Alas real world application is always more intricate than academia would have you believe.

Well, you can rewrite some classes and then transfer data in and out of them… but then maybe the teacher wonders why you decided to write your own versions of working code. I’m not sure you can win in this case. :slight_smile:

Or maybe you show the teacher that you documented that the user should not modify the vectors and you can do some simple sanity checks during final mesh construction to make sure that the vectors still match their keys.

Defensive copies.

That’s actually the conclusion I came to. Assertions for the sanity check and defensive copies for safe-guarding. The design I’ve settled on is having each dynamic mesh object keep it’s own private pool of reusable vertices for its mesh. Upon requesting new polys added to the mesh, the dynamic mesh will utilize its vector pool to get the vertices it needs. The vector pool will either return a reference to an already existing vector in its pool (object reuse = RAM savings) or will create a defensive copy of the vector passed into, add it to the pool, and pass back a reference to the new vector.

Originally I was going to use a singleton vector pool, but because these dynamic meshes are being used for environment construction (rigidly subdivided into a grid for that matter too) these meshes will inherently never share any internal vertices. Only a marginal number of vertices along the adjacent edges of two meshes could ever be shared, and I’ll sacrifice that bit of memory in order to safeguard the vertices immutability. Because each dynamic mesh is the only class with access to its vertices I can ensure that they will never mutate their vertices, thus upholding my invariant. Woot for nipping bugs before they can happen :slight_smile:

Now my next concern is one of roundoff. I’m planning to use a weak reference hash table to back the vector pools. I know floating point calculations can produce slightly different results for what should be the same answer depending on how the math is done, and well… vectors are floats. In other words what should come out as the same vector could produce two different but nearly identical vertices depending oh how that coordinate was approached. And this could result in non-equality and different hashcodes.

Should I use some tiny threshold value to force 2 vertices that are almost identical to map to the same result? Is there a recommended value or some provided constant or method for this need?

I don’t know if your vertexes can have other attributes (like texture coordinates, normals, etc.) but if so then you will also want to key off of those, too. In the end, having a separate class to represent position, texture, normal, etc. might not be a bad idea… and you could make it mostly immutable, too.

Unless you are running on android or really thrashing with create/deletes then my understanding is that object pooling isn’t generally needed with modern JVMs.

@zarch said:
Unless you are running on android or really thrashing with create/deletes then my understanding is that object pooling isn't generally needed with modern JVMs.

You have missed the point of this thread, actually.

The pooling is so that he can construct a proper vertex buffer with a proper index buffer.

Sorry, having a blonde moment. I had read the start of the thread earlier but my brain seems to have frazzled since then. You are right, that’s not why he’s pooling.