Files
MapLibreParticleLab/include/mbgl/gfx/vertex_attribute.hpp

171 lines
5.6 KiB
C++

#pragma once
#include <mbgl/gfx/gfx_types.hpp>
#include <array>
#include <cstdint>
#include <functional>
#include <memory>
#include <string>
#include <unordered_map>
#include <variant>
#include <vector>
namespace mbgl {
using mat2 = std::array<double, 2*2>;
using mat3 = std::array<double, 3*3>;
using mat4 = std::array<double, 4*4>;
namespace gfx {
class ShaderProgramBase;
class VertexAttribute {
public:
using float2 = std::array<float, 2>;
using float3 = std::array<float, 3>;
using float4 = std::array<float, 4>;
using matf2 = std::array<float, 2*2>;
using matf3 = std::array<float, 3*3>;
using matf4 = std::array<float, 4*4>;
using int2 = std::array<std::int32_t, 2>;
using int3 = std::array<std::int32_t, 3>;
using int4 = std::array<std::int32_t, 4>;
using ElementType = std::variant<std::int32_t, int2, int3, int4,
float, float2, float3, float4,
matf3, matf4>;
// Can only be created by VertexAttributeArray implementations
protected:
VertexAttribute(int index_, AttributeDataType dataType_, int size_, std::size_t count_)
: index(index_),
size(size_),
dataType(dataType_),
items(count_) {
}
VertexAttribute(const VertexAttribute &) = default;
VertexAttribute(VertexAttribute&& other)
: index(other.index),
size(other.size),
dataType(other.dataType),
items(std::move(other.items)) {
}
public:
~VertexAttribute() = default;
int getIndex() const { return index; }
void setIndex(int value) { index = value; }
int getSize() const { return size; }
std::size_t getCount() const { return items.size(); }
AttributeDataType getDataType() const { return dataType; }
const ElementType& get(std::size_t i) const { return items[i]; }
template <typename T>
const ElementType& set(std::size_t i, T value) {
dirty = true; // need to rebuild the raw data next time
return items[i] = value;
}
bool getDirty() const { return dirty; }
void clearDirty() { dirty = false; }
protected:
VertexAttribute& operator=(const VertexAttribute&) = default;
VertexAttribute& operator=(VertexAttribute&& other) {
index = other.index;
size = other.size;
dataType = other.dataType;
items = std::move(other.items);
return *this;
}
protected:
int index;
int size;
/// indicates that a value has changed and any cached result should be discarded
mutable bool dirty = true;
AttributeDataType dataType;
std::vector<ElementType> items;
};
/// Stores a collection of vertex attributes by name
class VertexAttributeArray {
public:
using AttributeMap = std::unordered_map<std::string, std::unique_ptr<VertexAttribute>>;
VertexAttributeArray(int initCapacity = 10);
VertexAttributeArray(VertexAttributeArray &&);
// Would need to use the virtual assignment operator
VertexAttributeArray(const VertexAttributeArray&) = delete;
virtual ~VertexAttributeArray() = default;
std::size_t size() const { return attrs.size(); }
/// Add a new attribute element.
/// Returns a pointer to the new element on success, or null if the attribute already exists.
/// The result is valid only until the next non-const method call on this class.
VertexAttribute* get(const std::string& name) const;
/// Add a new attribute element.
/// Returns a pointer to the new element on success, or null if the attribute already exists.
/// The result is valid only until the next non-const method call on this class.
VertexAttribute* add(std::string name, int index, AttributeDataType, int size, std::size_t count);
/// Add a new attribute element if it doesn't already exist.
/// Returns a pointer to the new element on success, or null if the type or count conflict with an existing entry.
/// The result is valid only until the next non-const method call on this class.
VertexAttribute* getOrAdd(std::string name, int index, AttributeDataType, int size, std::size_t count);
// Set a value if the element is present
template <typename T>
bool set(const std::string& name, std::size_t i, T value) {
if (auto *item = get(name)) {
return item->set(i, value);
}
return false;
}
/// Indicates whether any values have changed
bool isDirty() const;
void resetDirty();
using ResolveDelegate = std::function<void(const std::string&, const VertexAttribute&, const VertexAttribute*)>;
/// Call the provided delegate with each value, providing the override if one exists.
void resolve(const VertexAttributeArray& overrides, ResolveDelegate) const;
/// Apply to the active program
virtual void applyUniforms(const ShaderProgramBase&) = 0;
VertexAttributeArray& operator=(VertexAttributeArray &&);
VertexAttributeArray& operator=(const VertexAttributeArray&);
protected:
VertexAttribute* add(std::string name, std::unique_ptr<VertexAttribute>&& attr) {
const auto result = attrs.insert(std::make_pair(std::move(name), std::unique_ptr<VertexAttribute>()));
if (result.second) {
result.first->second = std::move(attr);
return result.first->second.get();
} else {
return nullptr;
}
}
virtual std::unique_ptr<VertexAttribute> create(int index, AttributeDataType dataType,
int size, std::size_t count) = 0;
virtual std::unique_ptr<VertexAttribute> copy(const VertexAttribute& attr) = 0;
protected:
AttributeMap attrs;
};
} // namespace gfx
} // namespace mbgl