RTC_GEOMETRY_TYPE_SUBDIVISION(3embree3)

πŸ“¦ version 3.13.5, in epel 9, fedora 43, fedora 44

πŸ’– RTC_GEOMETRY_TYPE_SUBDIVISION πŸ’–

okay bestie, welcome to the RTC_GEOMETRY_TYPE_SUBDIVISION page, straight out of the Embree Ray Tracing Kernels 3 manual ✨ this one's all about subdivision geometry and honestly? it's giving smooth surfaces and main character energy πŸ¦‹


✨ NAME ✨

RTC_GEOMETRY_TYPE_SUBDIVISION β€” the subdivision geometry type, no cap πŸ’…


🌸 SYNOPSIS 🌸

#include <embree3/rtcore.h>

RTCGeometry geometry =
  rtcNewGeometry(device, RTC_GEOMETRY_TYPE_SUBDIVISION);

πŸ’œ DESCRIPTION πŸ’œ

Catmull-Clark subdivision meshes are supported, and she does NOT come to play β€” we're talking support for edge creases, vertex creases, holes, non-manifold geometry, and face-varying interpolation πŸŽ€ The number of vertices per face can be anywhere in the range of 3 to 15 vertices (triangles, quadrilaterals, pentagons, etc.).

Subdivision meshes get created by passing RTC_GEOMETRY_TYPE_SUBDIVISION to the rtcNewGeometry function. Then your app has to set up a bunch of buffers to actually build the mesh β€” peep rtcSetGeometryBuffer and rtcSetSharedGeometryBuffer for the deets on buffer setting πŸ“‹

  • Face buffer β€” type RTC_BUFFER_TYPE_FACE, format RTC_FORMAT_UINT. Holds the number of edges/indices of each face (3 to 15), and the number of faces is inferred from the size of this buffer. she counts herself, iconic πŸ’…
  • Index buffer β€” type RTC_BUFFER_TYPE_INDEX. Holds multiple (3 to 15) 32-bit vertex indices (RTC_FORMAT_UINT) for each face, and the number of edges is inferred from the size of this buffer.
  • Vertex buffer β€” type RTC_BUFFER_TYPE_VERTEX. Stores an array of single precision x, y, z floating point coordinates (RTC_FORMAT_FLOAT3), and the number of vertices is inferred from the size of this buffer ✨

Optionally, your app can set additional index buffers using different buffer slots if multiple topologies are required for face-varying interpolation. The standard vertex buffers (RTC_BUFFER_TYPE_VERTEX) are always bound to the geometry topology (topology 0), so they use RTC_BUFFER_TYPE_INDEX with buffer slot 0. User vertex data interpolation may use different topologies, which we get into later πŸ‘€

Optionally, your app can set up the hole buffer (RTC_BUFFER_TYPE_HOLE), which contains an array of 32-bit indices (RTC_FORMAT_UINT) of faces that should be considered non-existing in all topologies. The number of holes is inferred from the size of this buffer πŸ•³οΈ

Optionally, your app can fill the level buffer (RTC_BUFFER_TYPE_LEVEL) with a tessellation rate for each of the edges of each face. This buffer must have the same size as the index buffer. The tessellation level is a positive floating point value (RTC_FORMAT_FLOAT) that says how many quads along the edge should be generated during tessellation. If no level buffer is specified, a level of 1 is used. The maximally supported edge level is 4096, and larger levels get clamped to that value. Note that edges may be shared between (typically 2) faces β€” and to guarantee a watertight tessellation, the level of these shared edges should be identical πŸ”₯ A uniform tessellation rate for an entire subdivision mesh can be set by using the rtcSetGeometryTessellationRate function. The existence of a level buffer has precedence over the uniform tessellation rate, periodt.

Optionally, your app can fill the sparse edge crease buffers to make edges appear sharper 😳 The edge crease index buffer (RTC_BUFFER_TYPE_EDGE_CREASE_INDEX) contains an array of pairs of 32-bit vertex indices (RTC_FORMAT_UINT2) that specify unoriented edges in the geometry topology. The edge crease weight buffer (RTC_BUFFER_TYPE_EDGE_CREASE_WEIGHT) stores, for each of these crease edges, a positive floating point weight (RTC_FORMAT_FLOAT). The number of edge creases is inferred from the size of these buffers, which has to be identical. The larger a weight, the sharper the edge ✨ Specifying a weight of infinity is supported and marks an edge as infinitely sharp.

bestie listen β€” storing an edge multiple times with the same crease weight is allowed, but has lower performance. Storing an edge multiple times with different crease weights results in undefined behavior πŸ’€ do not do it.

For a stored edge (i,j), the reverse direction edges (j,i) do not have to be stored, because both are considered the same unoriented edge. Edge crease features are shared between all topologies 🫢

Optionally, your app can fill the sparse vertex crease buffers to make vertices appear sharper πŸ’… The vertex crease index buffer (RTC_BUFFER_TYPE_VERTEX_CREASE_INDEX) contains an array of 32-bit vertex indices (RTC_FORMAT_UINT) to specify a set of vertices from the geometry topology. The vertex crease weight buffer (RTC_BUFFER_TYPE_VERTEX_CREASE_WEIGHT) specifies, for each of these vertices, a positive floating point weight (RTC_FORMAT_FLOAT). The number of vertex creases is inferred from the size of these buffers, and has to be identical. The larger a weight, the sharper the vertex ✨ Specifying a weight of infinity is supported and makes the vertex infinitely sharp.

again, fr fr: storing a vertex multiple times with the same crease weight is allowed, but has lower performance. Storing a vertex multiple times with different crease weights results in undefined behavior 😭

Vertex crease features are shared between all topologies 🌈

Subdivision modes can be used to force linear interpolation for parts of the subdivision mesh β€” see rtcSetGeometrySubdivisionMode for more details.

For multi-segment motion blur, the number of time steps must first be specified using the rtcSetGeometryTimeStepCount call. Then a vertex buffer for each time step can be set using different buffer slots, and all these buffers have to have the same stride and size ⏱️

Also, peep the tutorial [Subdivision Geometry] for an example of how to create subdivision surfaces, iykyk πŸŽ€


πŸ¦‹ Parametrization πŸ¦‹

The parametrization for subdivision faces is different for quadrilaterals and non-quadrilateral faces, so pay attention bestie πŸ‘‘

The parametrization of a quadrilateral face uses the first vertex p0 as base point, and the vector p1 - p0 as u-direction and p3 - p0 as v-direction.

The parametrization for all other face types (with number of vertices not equal 4) has a special parametrization where the subpatch ID n (of the n-th quadrilateral that would be obtained by a single subdivision step) and the local hit location inside this quadrilateral are encoded in the UV coordinates. The following code extracts the sub-patch ID i and local UVs of this subpatch:

unsigned int l = floorf(0.5f*U);
unsigned int h = floorf(0.5f*V);
unsigned int i = 4*h+l;
float u = 2.0f*fracf(0.5f*U)-0.5f;
float v = 2.0f*fracf(0.5f*V)-0.5f;

This encoding allows local subpatch UVs to be in the range [-0.5,1.5[ β€” so yes, negative subpatch UVs can be passed to rtcInterpolate to sample subpatches slightly out of bounds 😌 This can be useful to calculate derivatives using finite differences if required. The encoding further has the property that you can just move the value u (or v) on a subpatch by adding du (or dv) to the special UV encoding, as long as it does not fall out of the [-0.5,1.5[ range ✨

To smoothly interpolate vertex attributes over the subdivision surface, we recommend using the rtcInterpolate function, which will apply the standard subdivision rules for interpolation and automatically takes care of the special UV encoding for non-quadrilaterals. she's got it all handled πŸ’…


πŸŽ€ Face-Varying Data πŸŽ€

Face-varying interpolation is supported through multiple topologies per subdivision mesh, and binding such topologies to vertex attribute buffers to interpolate. This way, texture coordinates may use a different topology with additional boundaries to construct separate UV regions inside one subdivision mesh 🌸

Each such topology i has a separate index buffer (specified using RTC_BUFFER_TYPE_INDEX with buffer slot i) and separate subdivision mode that can be set using rtcSetGeometrySubdivisionMode. A vertex attribute buffer RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE bound to a buffer slot j can be assigned to use a topology for interpolation using the rtcSetGeometryVertexAttributeTopology call 🫢

The face buffer (RTC_BUFFER_TYPE_FACE type) is shared between all topologies, which means that the n-th primitive always has the same number of vertices (e.g. being a triangle or a quad) for each topology. However, the indices of the topologies themselves may be different πŸ‘€


πŸ’€ EXIT STATUS πŸ’€

On failure NULL is returned and an error code is set that can be queried using rtcGetDeviceError. so like, always check your errors bestie, don't just assume she worked 😭


🌈 SEE ALSO 🌈

  • [rtcNewGeometry]

and that's the whole page, bestie πŸ’– this was RTC_GEOMETRY_TYPE_SUBDIVISION(3) from the Embree Ray Tracing Kernels 3 manual β€” go build something gorgeous with it, slay πŸ‘‘βœ¨πŸŽ€

πŸ“¦ where this page comes from