The BMesh primitive operators use a very differently than you might expect.
Instead of using the fact that the result is known and constant to their advantage,
they use operators like extrusion, removing doubles, and rotation.
Implementing the primitives directly with the Mesh data structure is much
more efficient, since it's very simple to fill the result data based on
the known inputs. It also allows also skip the conversion from Mesh to BMesh.
Speed matters a lot more for procedural operations than for the existing mesh
primitive operators accessible from the add menu, since they will be executed
for every evaluation rather than only once before a destructive workflow.
| Shape | Average Before (ms) | Average After (ms) | Speed Factor (x times faster) |
| -------- | ------------------- | ------------------ | ----------------------------- |
| Cylinder | 1.1676 | 0.31327 | 3.72 |
| Cone | 4.5890 | 0.17762 | 25.8 |
| Sphere | 64213.3 | 13.595 | 4720 |
The downside of this change is that there will be two implementations for
these three primitives, in these nodes and in `bmo_primitive.c`. One option
would be re-implementing the BMesh primitives in terms of this code, but that
would require `BMesh` to depend on `Mesh`, which isn't desired.
On the other hand, it will be easier to add new features to these nodes like
different fill types for the top and the bottom of a cylinder, rings for a cylinder,
and tagging the output with boolean attributes.
Another factor to consider is that the add mesh object operator could be implemented
with these nodes, just providing more benefit for a faster implementation.