stim::mesh_reader class

RAII interface for reading mesh information from scene objects.

Example

Given a hypothetical dynamic_mesh type:

class dynamic_mesh
{
  public:
    void resize_indices(size_t);
    void resize_positions(size_t);
    void resize_normals(size_t);
    void resize_uvs(size_t);

    void clear()
    {
        resize_indices(0);
        resize_positions(0);
        resize_normals(0);
        resize_uvs(0);
    }

    unsigned* indices();
    vec3* positions();
    vec3* normals();
    vec2* uvs();
};

Updating it using a mesh_reader would look like this:

void update_mesh(dynamic_mesh& mesh, const stim::mesh_reader& reader)
{
    assert(reader);

    // mesh has no geometry - clear all the channels (make the mesh 'empty')
    if (reader.empty())
    {
        mesh.clear();
        return;
    }

    // force a full rebuild if there are any structural changes
    const bool full_rebuild =
        reader(stim::mesh_traits::topology | stim::mesh_traits::winding_order);

    // update indices
    if (reader(stim::mesh_traits::indices | stim::mesh_traits::index_count) || full_rebuild)
    {
        mesh.resize_indices(reader.index_count());
        if (reader.index_count())
        {
            auto result = reader.read_indices(mesh.indices());
            if (!result)
                log_error("oh noes:", result.error());
        }
    }

    // update vertex positions
    if (reader(stim::mesh_traits::positions | stim::mesh_traits::vertex_count) || full_rebuild)
    {
        mesh.resize_positions(reader.vertex_count());
        if (reader.vertex_count())
        {
            auto result = reader.read_positions(&mesh.positions()[0].x);
            if (!result)
                log_error("oh noes:", result.error());
        }
    }

    // update vertex normals
    if (reader(stim::mesh_traits::normals | stim::mesh_traits::vertex_count) || full_rebuild)
    {
        mesh.resize_normals(reader.vertex_count());
        if (reader.vertex_count())
        {
            auto result = reader.read_normals(&mesh.normals()[0].x);
            if (!result)
                log_error("oh noes:", result.error());
        }
    }

    // update vertex uvs
    if (!reader.has_uvs())
        mesh.resize_uvs(0);
    else if (reader(stim::mesh_traits::uvs | stim::mesh_traits::vertex_count) || full_rebuild)
    {
        mesh.resize_uvs(reader.vertex_count());
        if (reader.vertex_count())
        {
            auto result = reader.read_uvs(&mesh.uvs()[0].x);
            if (!result)
                log_error("oh noes:", result.error());
        }
    }
}

void update_mesh(dynamic_mesh& mesh, stim::soft_body_handle handle)
{
    assert(handle);

    auto reader = handle.mesh_reader();

    // mesh_reader() failed - the result object reported an error
    if (!reader)
    {
        log_error("oh noes:", reader.error());
        return;
    }

    update_mesh(mesh, *reader);
}

Constructors, destructors, conversion operators

mesh_reader() defaulted noexcept
Default-constructs a null reader.
mesh_reader(const mesh_reader& other) noexcept
Copy constructor.
mesh_reader(mesh_reader&& other) noexcept
Move constructor.
operator bool() const explicit noexcept
Returns true if this handle represents a valid mesh_reader (i.e is not null).
~mesh_reader() noexcept
Destructor.

Public functions

auto operator=(const mesh_reader& rhs) -> mesh_reader& noexcept
Copy-assignment operator.
auto operator=(mesh_reader&& rhs) -> mesh_reader& noexcept
Move-assignment operator.

Compatibility with UE4

auto read_normals(::FVector* dest) const -> result noexcept
Reads normals from the mesh into a vertex buffer.
auto read_positions(::FVector* dest) const -> result noexcept
Reads positions from the mesh into a vertex buffer.
auto read_uvs(::FVector2D* dest) const -> result noexcept
Reads UVs from the mesh into a vertex buffer.
auto read_uvs(::FVector2DHalf* dest) const -> result noexcept
Reads UVs from the mesh into a vertex buffer.

Indices

auto index_count() const -> size_t noexcept
The number of indices in the mesh.
auto max_index_count() const -> size_t noexcept
The maximum possible number of indices (i.e. internal capacity) in the mesh after any modification (e.g. cutting).
auto read_indices(void* dest, size_t bytes_between_indices, scalar_type type) const -> result noexcept
Reads indices from the mesh into an index buffer.
template<typename T>
auto read_indices(T* dest, size_t bytes_between_indices = sizeof(T)) const -> result noexcept
Reads indices from the mesh into an index buffer.
template<typename T>
auto read_indices(span<T> dest) const -> result noexcept
Reads indices from the mesh into an index buffer.

Traits

auto changes() const -> mesh_traits noexcept
Returns the cumulative set of mesh traits which have changed since the last time a mesh reader was created from the source object.
auto empty() const -> bool noexcept
Returns true if the mesh represented by this reader is completely empty (has no indices or vertices).
auto has_uvs() const -> bool noexcept
Returns true if the mesh vertices have a UV data channel.
auto operator()(mesh_traits traits) const -> bool noexcept
Returns true if the set of flags returned by changes() contains any of the given inputs.
auto topology() const -> mesh_flags noexcept
The topology of the mesh.
auto winding_order() const -> mesh_flags noexcept
The triangle winding order of the mesh.

Vertices

auto max_vertex_count() const -> size_t noexcept
The maximum possible number of vertices (i.e. internal capacity) in the mesh after any modification (e.g. cutting).
auto read_normals(void* dest, size_t bytes_between_vertices, scalar_type type) const -> result noexcept
Reads surface normals from the mesh into a vertex buffer.
template<typename T>
auto read_normals(T* dest, size_t bytes_between_vertices = sizeof(T)*3) const -> result noexcept
Reads surface normals from the mesh into a vertex buffer.
template<typename T>
auto read_normals(span<T> dest) const -> result noexcept
Reads normals from the mesh into a vertex buffer.
template<typename T>
auto read_normals(vector<T, 3>* dest) const -> result noexcept
Reads normals from the mesh into a vertex buffer.
template<typename T>
auto read_normals(span<vector<T, 3>> dest) const -> result noexcept
Reads normals from the mesh into a vertex buffer.
auto read_positions(void* dest, size_t bytes_between_vertices, scalar_type type) const -> result noexcept
Reads positions from the mesh into a vertex buffer.
template<typename T>
auto read_positions(T* dest, size_t bytes_between_vertices = sizeof(T)*3) const -> result noexcept
Reads positions from the mesh into a vertex buffer.
template<typename T>
auto read_positions(span<T> dest) const -> result noexcept
Reads positions from the mesh into a vertex buffer.
template<typename T>
auto read_positions(vector<T, 3>* dest) const -> result noexcept
Reads positions from the mesh into a vertex buffer.
template<typename T>
auto read_positions(span<vector<T, 3>> dest) const -> result noexcept
Reads positions from the mesh into a vertex buffer.
auto read_uvs(void* dest, size_t bytes_between_vertices, scalar_type type) const -> result noexcept
Reads UVs from the mesh into a vertex buffer.
template<typename T>
auto read_uvs(T* dest, size_t bytes_between_vertices = sizeof(T)*2) const -> result noexcept
Reads UVs from the mesh into a vertex buffer.
template<typename T>
auto read_uvs(span<T> dest) const -> result noexcept
Reads UVs from the mesh into a vertex buffer.
template<typename T>
auto read_uvs(vector<T, 2>* dest) const -> result noexcept
Reads UVs from the mesh into a vertex buffer.
template<typename T>
auto read_uvs(span<vector<T, 2>> dest) const -> result noexcept
Reads UVs from the mesh into a vertex buffer.
auto vertex_count() const -> size_t noexcept
The number of vertices in the mesh.

Function documentation

result stim::mesh_reader::read_normals(::FVector* dest) const noexcept

Reads normals from the mesh into a vertex buffer.

result stim::mesh_reader::read_positions(::FVector* dest) const noexcept

Reads positions from the mesh into a vertex buffer.

result stim::mesh_reader::read_uvs(::FVector2D* dest) const noexcept

Reads UVs from the mesh into a vertex buffer.

result stim::mesh_reader::read_uvs(::FVector2DHalf* dest) const noexcept

Reads UVs from the mesh into a vertex buffer.

size_t stim::mesh_reader::max_index_count() const noexcept

The maximum possible number of indices (i.e. internal capacity) in the mesh after any modification (e.g. cutting).

result stim::mesh_reader::read_indices(void* dest, size_t bytes_between_indices, scalar_type type) const noexcept

Reads indices from the mesh into an index buffer.

Parameters
dest Pointer to the first index in the destination buffer.
bytes_between_indices The byte stride from one index to the next.
type The fundamental data type of the indices. Must be integral.
std::vector<unsigned> buffer(reader.index_count());
reader.read_indices(buffer.data(), sizeof(unsigned), stim::to_scalar_type<unsigned>::value);

template<typename T>
result stim::mesh_reader::read_indices(T* dest, size_t bytes_between_indices = sizeof(T)) const noexcept

Reads indices from the mesh into an index buffer.

Template parameters
T Index type. Must be integral.
Parameters
dest Pointer to the first index in the destination buffer.
bytes_between_indices The byte stride from one index to the next.
std::vector<unsigned> buffer(reader.index_count());
reader.read_indices(buffer.data());

template<typename T>
result stim::mesh_reader::read_indices(span<T> dest) const noexcept

Reads indices from the mesh into an index buffer.

Template parameters
T Index type. Must be integral.
std::vector<unsigned> indices(buffer.index_count());
reader.read_indices(stim::span<unsigned>{ buffer.data(), buffer.size() });

mesh_traits stim::mesh_reader::changes() const noexcept

Returns the cumulative set of mesh traits which have changed since the last time a mesh reader was created from the source object.

bool stim::mesh_reader::has_uvs() const noexcept

Returns true if the mesh vertices have a UV data channel.

bool stim::mesh_reader::operator()(mesh_traits traits) const noexcept

Returns true if the set of flags returned by changes() contains any of the given inputs.

This is a shorthand intended to simplify callsites:

stim::mesh_reader reader = /* ... */;

// this:
if (reader(stim::mesh_traits::topology | stim::mesh_traits::winding_order))
{
    // ...
}

// is equivalent to this:
if ((reader.changes() & (stim::mesh_traits::topology | stim::mesh_traits::winding_order))
    != stim::mesh_traits::none)
{
    // ...
}

mesh_flags stim::mesh_reader::topology() const noexcept

The topology of the mesh.

mesh_flags stim::mesh_reader::winding_order() const noexcept

The triangle winding order of the mesh.

size_t stim::mesh_reader::max_vertex_count() const noexcept

The maximum possible number of vertices (i.e. internal capacity) in the mesh after any modification (e.g. cutting).

result stim::mesh_reader::read_normals(void* dest, size_t bytes_between_vertices, scalar_type type) const noexcept

Reads surface normals from the mesh into a vertex buffer.

Parameters
dest Pointer to the first normal in the destination buffer.
bytes_between_vertices The byte stride from one vertex to the next.
type The fundamental data type of the normals. Integral normals are re-mapped from [-1.0, 1.0] to [min, max].
std::vector<float> buffer(reader.vertex_count() * 3u);
reader.read_normals(buffer.data(), sizeof(float) * 3u, stim::to_scalar_type<float>::value);

template<typename T>
result stim::mesh_reader::read_normals(T* dest, size_t bytes_between_vertices = sizeof(T)*3) const noexcept

Reads surface normals from the mesh into a vertex buffer.

Template parameters
T Normal scalar type. Integral normals are re-mapped from [-1.0, 1.0] to [min, max].
Parameters
dest Pointer to the first normal scalar in the destination buffer.
bytes_between_vertices The byte stride from one vertex to the next.
std::vector<float> buffer(reader.vertex_count() * 3u);
reader.read_normals(buffer.data());

template<typename T>
result stim::mesh_reader::read_normals(span<T> dest) const noexcept

Reads normals from the mesh into a vertex buffer.

Template parameters
T Normal scalar type.
std::vector<float> buffer(reader.vertex_count() * 3u);
reader.read_normals(stim::span<float>{ buffer.data(), buffer.size() });

template<typename T>
result stim::mesh_reader::read_normals(vector<T, 3>* dest) const noexcept

Reads normals from the mesh into a vertex buffer.

Template parameters
T Normal scalar type.
std::vector<stim::vec3> buffer(reader.vertex_count());
reader.read_normals(buffer.data());

template<typename T>
result stim::mesh_reader::read_normals(span<vector<T, 3>> dest) const noexcept

Reads normals from the mesh into a vertex buffer.

Template parameters
T Normal scalar type.
std::vector<stim::vec3> buffer(reader.vertex_count());
reader.read_normals(stim::span<stim::vec3>{ buffer.data(), buffer.size() });

result stim::mesh_reader::read_positions(void* dest, size_t bytes_between_vertices, scalar_type type) const noexcept

Reads positions from the mesh into a vertex buffer.

Parameters
dest Pointer to the first position in the destination buffer.
bytes_between_vertices The byte stride from one vertex to the next.
type The fundamental data type of the positions.
std::vector<float> buffer(reader.vertex_count() * 3u);
reader.read_positions(buffer.data(), sizeof(float) * 3u, stim::to_scalar_type<float>::value);

template<typename T>
result stim::mesh_reader::read_positions(T* dest, size_t bytes_between_vertices = sizeof(T)*3) const noexcept

Reads positions from the mesh into a vertex buffer.

Template parameters
T Position scalar type.
Parameters
dest Pointer to the first position scalar in the destination buffer.
bytes_between_vertices The byte stride from one vertex to the next.
std::vector<float> buffer(reader.vertex_count() * 3u);
reader.read_positions(buffer.data());

template<typename T>
result stim::mesh_reader::read_positions(span<T> dest) const noexcept

Reads positions from the mesh into a vertex buffer.

Template parameters
T Position scalar type.
std::vector<float> buffer(reader.vertex_count() * 3u);
reader.read_positions(stim::span<float>{ buffer.data(), buffer.size() });

template<typename T>
result stim::mesh_reader::read_positions(vector<T, 3>* dest) const noexcept

Reads positions from the mesh into a vertex buffer.

Template parameters
T Position scalar type.
std::vector<stim::vec3> buffer(reader.vertex_count());
reader.read_positions(buffer.data());

template<typename T>
result stim::mesh_reader::read_positions(span<vector<T, 3>> dest) const noexcept

Reads positions from the mesh into a vertex buffer.

Template parameters
T Position scalar type.
std::vector<stim::vec3> buffer(reader.vertex_count());
reader.read_positions(stim::span<stim::vec3>{ buffer.data(), buffer.size() });

result stim::mesh_reader::read_uvs(void* dest, size_t bytes_between_vertices, scalar_type type) const noexcept

Reads UVs from the mesh into a vertex buffer.

Parameters
dest Pointer to the first normal in the destination buffer.
bytes_between_vertices The byte stride from one vertex to the next.
type The fundamental data type of the normals. Integral UVs are re-mapped from [0.0, 1.0] to [min, max].
std::vector<float> buffer(reader.vertex_count() * 2u);
reader.read_uvs(buffer.data(), sizeof(float) * 2u, stim::to_scalar_type<float>::value);

template<typename T>
result stim::mesh_reader::read_uvs(T* dest, size_t bytes_between_vertices = sizeof(T)*2) const noexcept

Reads UVs from the mesh into a vertex buffer.

Template parameters
T UV scalar type. Integral normals are re-mapped from [0.0, 1.0] to [min, max].
Parameters
dest Pointer to the first UV scalar in the destination buffer.
bytes_between_vertices The byte stride from one vertex to the next.
std::vector<float> buffer(reader.vertex_count() * 2u);
reader.read_uvs(buffer.data());

template<typename T>
result stim::mesh_reader::read_uvs(span<T> dest) const noexcept

Reads UVs from the mesh into a vertex buffer.

Template parameters
T UV scalar type.
std::vector<float> buffer(reader.vertex_count() * 2u);
reader.read_uvs(stim::span<float>{ buffer.data(), buffer.size() });

template<typename T>
result stim::mesh_reader::read_uvs(vector<T, 2>* dest) const noexcept

Reads UVs from the mesh into a vertex buffer.

Template parameters
T UV scalar type.
std::vector<stim::vec2> buffer(reader.vertex_count());
reader.read_uvs(buffer.data());

template<typename T>
result stim::mesh_reader::read_uvs(span<vector<T, 2>> dest) const noexcept

Reads UVs from the mesh into a vertex buffer.

Template parameters
T UV scalar type.
std::vector<stim::vec2> buffer(reader.vertex_count());
reader.read_uvs(stim::span<stim::vec2>{ buffer.data(), buffer.size() });