Legacy Mesh Data
From K-3D
General mesh structure
Note: this information is obsoleted by Array Based Mesh Design, which should be used for all new code.
Mesh format is defined in k3dsdk/mesh.h . k3d::mesh contains any point-based RenderMan primitives (specifically) like single points, polygons, patches as well as blobbies.
A basic k3d::mesh structure is described as:
class mesh :
public selectable
{
public:
mesh();
virtual ~mesh();
/// Defines a collection of points typedef std::vector<point*> points_t; /// Stores the set of points within the mesh that are shared among the rest of the mesh geometry points_t points; }
Every k3d::mesh primitive stores its points in the above 'points' list. Storing primitive positions using references to k3d::point make it possible to run them through any of our various transformations that operate on points (e.g. rotate, translate, scale, shear, sphereize, taper, twist, etc.) and get the expected outcome.
Polyhedra
In a nutshell, k3d::polyhedron, k3d::face, and k3d::split_edge collectively form what is known in the literature as "split edge" B-rep (boundary representation) data structures, which are very common.
There can be multiple polyhedra (or manifold surfaces) per mesh, while separate surfaces could share the same points. class k3d::mesh contains the following polyhedron list :
/// Defines a collection of manifold polyhedra typedef std::vector<polyhedron*> polyhedra_t; /// Stores a collection of manifold polyhedra polyhedra_t polyhedra;
The current design is a tradeoff among efficiency (time and space), flexibility, and ease-of-use. The downside is that there is little room for compile-time enforcement of the rules, which is why we have k3d::is_valid() to check polyhedra at runtime. Additionally, k3d::is_solid() checks whether a polyhedron is manifold.
A polyhedron is meant to be a manifold *surface*, if someone really wants to create just edges, they should use the k3d::linear_curve primitive. As a consequence, a k3d::face always points to a closed loop formed of at least three edges.
For more information, read the Polyhedron Data page.
Materials
You can assign a material to:
- point groups: k3d::point_group
- polygons: k3d::face
- curve groups: k3d::linear_curve_group, k3d::cubic_curve_group, k3d::nucurve_group
- patches: k3d::bilinear_patch, k3d::bicubic_patch, k3d::nupatch
- blobby groups: k3d::blobby
Polyhedra are allowed (encouraged, even!) to share points - in fact, any of the geometric types within a single mesh can share points. That allows you to, e.g. have a polygon abut a NURBS patch, and edit their points without introducing cracks (of course, they don't have to share points, if you don't want them to).
Note that materials are not necessarily equal to colors. A material represents a specific set of surface attributes within a specific shading model. You can assign different colors to geometry that shares a single material, using the tags mechanism (see below), although we don't preview it in the viewport.
Additional structure data: parameters
Those geometry structures don't provide out-of-the-box storage for say: texture coordinates.
This is not a missing feature, but something that has been thought about a lot, and unless we see a specific scenario where our generic variables deliver unacceptable performance, we will use them for texture coordinates. There is a very flexible mechanism, taken straight from RenderMan, for passing extra data around with geometry:
look at the point structure for example,
class point :
public selectable
{
public:
point(const vector3& Position);
point(const double X, const double Y, const double Z);
/// Stores the position of the point in 3D space vector3 position; /// Stores vertex data for the point parameters_t vertex_data; /// Stores tag (SDS) data for the point parameters_t tags; };
parameters_t is defined with:
typedef std::map<std::string, boost::any> parameters_t;
allowing to store any heterogeneous information as:
vertex_data["u_coordinate"] = 3.6; vertex_data["color"] = k3d::color(0, 0, 1);
K-3D was designed as a RenderMan engine, and as such, realtime texture preview is a dead end - it simply isn't possible to use textures in OpenGL to effectively preview the output of any but the simplest shaders. If someone wants to write a special-purpose preview engine (like a game-engine preview) that does textures, s/he can cache the coordinates for acceptable performance (this is trivial compared to the caching that happens for previewing SDS or Blobby objects). Of course, if we're just plain dead wrong, we can easily add new fields to our structures with minimal pain.
Updating whatever code had been written at that point would be as simple as replacing
point->vertex_data["s"] = s; point->vertex_data["t"] = t;
with
point->s = s; point->t = t;
We ran a few tests with adding texture coordinates to points using variables, and the change in performance was acceptable.
Note: For a given mesh, parameters must be consistent across datatypes, e.g. if you add a parameter "foo" to one point, you have to add it to every point. Same for edges, faces, curves, and what-have-you. Our data structures don't enforce this, but it's required further down the pipeline when we generate RIB. Although our code is robust if this rule is ignored, render engine behavior will be undefined.
What this means is that for any parameter-setting tool, you have to provide values for everything you touch. You can see an example of this in the TagColor plugin, where you have to specify two colors - one is the color you're setting, the other is the color for "everywhere else".
Manifold definition
A topology is manifold if and only if there are no more than two faces adjacent to every edge.
There are two flavors of "manifold", the more lenient of the two allows edges to have one-or-two adjacent polygons, while the stricter of the two requires exactly two polygons for every edge. A mesh that obeys this latter constraint will always be a solid.
Selection
All the following objects are selectable:
point point_group split_edge face polyhedron linear_curve linear_curve_group cubic_curve cubic_curve_group nucurve nucurve_group bilinear_patch bicubic_patch nupatch
to select an individual curve (even if it's part of a group): use "Select Edge", to select the entire group, use "Select Object".
The developer has to assign two variables:
- selection_weight : 0 means object isn't selected, any other value (even negative) is allowed. Usually, selection tools set a weight equal to 1.0 when selecting items.
- visible_selection : a boolean to switch on/off selection view, it's useful when multiple selections apply on the same mesh. Every selection plugin should provide a checkbox for visible_selection in the UI.
Groups
The groups are there because the RenderMan API dictates that some attributes (such as material) apply to a collection of curves. For example, the point of the curve groups provide efficiency to do hair, grass, etc.

