Files
MapLibreParticleLab/src/mbgl/gfx/drawable_builder.cpp

287 lines
10 KiB
C++

#include <mbgl/gfx/drawable_builder.hpp>
#include <mbgl/gfx/drawable_builder_impl.hpp>
#include <mbgl/gfx/drawable_impl.hpp>
#include <mbgl/gfx/vertex_attribute.hpp>
#include <mbgl/renderer/render_pass.hpp>
#include <mbgl/util/logging.hpp>
#include <mbgl/util/string_indexer.hpp>
#include <mbgl/gfx/gfx_types.hpp>
namespace mbgl {
namespace gfx {
DrawableBuilder::DrawableBuilder(std::string name_)
: name(std::move(name_)),
vertexAttrNameId(stringIndexer().get("a_pos")),
renderPass(mbgl::RenderPass::Opaque),
impl(std::make_unique<Impl>()) {}
DrawableBuilder::~DrawableBuilder() = default;
const gfx::ColorMode& DrawableBuilder::getColorMode() const {
return impl->colorMode;
}
void DrawableBuilder::setColorMode(const gfx::ColorMode& value) {
impl->colorMode = value;
}
const gfx::CullFaceMode& DrawableBuilder::getCullFaceMode() const {
return impl->cullFaceMode;
}
void DrawableBuilder::setCullFaceMode(const gfx::CullFaceMode& value) {
impl->cullFaceMode = value;
}
const gfx::VertexAttributeArray& DrawableBuilder::getVertexAttributes() const {
return impl->vertexAttrs;
}
UniqueDrawable& DrawableBuilder::getCurrentDrawable(bool createIfNone) {
if (!currentDrawable && createIfNone) {
currentDrawable = createDrawable();
}
return currentDrawable;
}
void DrawableBuilder::flush() {
if (curVertexCount()) {
if (Impl::Mode::Polylines == impl->getMode()) {
// setup for polylines
impl->setupForPolylines(*this);
}
const auto& draw = getCurrentDrawable(/*createIfNone=*/true);
draw->setEnabled(enabled);
draw->setLineWidth(static_cast<int32_t>(lineWidth));
draw->setEnableColor(enableColor);
draw->setEnableStencil(enableStencil);
draw->setRenderPass(renderPass);
draw->setDrawPriority(drawPriority);
draw->setSubLayerIndex(subLayerIndex);
draw->setEnableDepth(enableDepth);
draw->setDepthType(depthType);
draw->setIs3D(is3D);
draw->setColorMode(impl->colorMode);
draw->setCullFaceMode(impl->cullFaceMode);
draw->setShader(shader);
draw->setTextures(textures);
draw->setTweakers(tweakers);
const auto& builderAttrs = getVertexAttributes();
if (auto drawAttrs = builderAttrs.clone()) {
draw->setVertexAttributes(std::move(*drawAttrs));
}
init();
// reset mode
impl->setMode(Impl::Mode::Custom);
}
if (currentDrawable) {
drawables.emplace_back(std::move(currentDrawable));
}
}
util::SimpleIdentity DrawableBuilder::getDrawableId() {
return currentDrawable ? currentDrawable->getID() : util::SimpleIdentity::Empty;
}
DrawPriority DrawableBuilder::getDrawPriority() const {
return drawPriority;
}
void DrawableBuilder::setDrawPriority(DrawPriority value) {
drawPriority = value;
if (currentDrawable) {
currentDrawable->setDrawPriority(value);
}
}
void DrawableBuilder::resetDrawPriority(DrawPriority value) {
setDrawPriority(value);
for (auto& drawble : drawables) {
drawble->setDrawPriority(value);
}
}
void DrawableBuilder::setTexture(const std::shared_ptr<gfx::Texture2D>& texture, int32_t location) {
textures.insert(std::make_pair(location, gfx::Texture2DPtr{})).first->second = std::move(texture);
}
void DrawableBuilder::addTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2) {
// check and set the current mode
if (!impl->checkAndSetMode(Impl::Mode::Primitives)) return;
const auto n = static_cast<uint16_t>(impl->vertices.elements());
impl->vertices.emplace_back(Impl::VT({{{x0, y0}}}));
impl->vertices.emplace_back(Impl::VT({{{x1, y1}}}));
impl->vertices.emplace_back(Impl::VT({{{x2, y2}}}));
impl->buildIndexes.insert(impl->buildIndexes.end(),
{n, static_cast<uint16_t>(n + 1), static_cast<uint16_t>(n + 2)});
if (impl->segments.empty()) {
impl->segments.emplace_back(createSegment(gfx::Triangles(), {0, 0}));
}
auto& segment = impl->segments.back();
segment->getSegment().vertexLength += 3;
segment->getSegment().indexLength += 3;
}
void DrawableBuilder::appendTriangle(int16_t x0, int16_t y0) {
// check and set the current mode
if (!impl->checkAndSetMode(Impl::Mode::Primitives)) return;
const auto n = (uint16_t)impl->vertices.elements();
impl->vertices.emplace_back(Impl::VT({{{x0, y0}}}));
impl->buildIndexes.insert(impl->buildIndexes.end(),
{static_cast<uint16_t>(n - 2), static_cast<uint16_t>(n - 1), n});
assert(!impl->segments.empty());
auto& segment = impl->segments.back();
segment->getSegment().vertexLength += 1;
segment->getSegment().indexLength += 3;
}
void DrawableBuilder::addQuad(int16_t x0, int16_t y0, int16_t x1, int16_t y1) {
// check and set the current mode
if (!impl->checkAndSetMode(Impl::Mode::Primitives)) return;
addTriangle(x0, y0, x1, y0, x0, y1);
appendTriangle(x1, y1);
}
void DrawableBuilder::setVertexAttributes(const VertexAttributeArray& attrs) {
impl->vertexAttrs = attrs;
}
void DrawableBuilder::setVertexAttributes(VertexAttributeArray&& attrs) {
impl->vertexAttrs = std::move(attrs);
}
std::size_t DrawableBuilder::addVertices(const std::vector<std::array<int16_t, 2>>& vertices,
std::size_t vertexOffset,
std::size_t vertexLength) {
const auto baseIndex = impl->vertices.elements();
std::for_each(std::next(vertices.begin(), vertexOffset),
std::next(vertices.begin(), vertexOffset + vertexLength),
[&](const std::array<int16_t, 2>& x) { impl->vertices.emplace_back(Impl::VT({{x}})); });
return baseIndex;
}
void DrawableBuilder::setRawVertices(std::vector<uint8_t>&& data, std::size_t count, AttributeDataType type) {
impl->rawVertices = std::move(data);
impl->rawVerticesCount = count;
impl->rawVerticesType = type;
}
void DrawableBuilder::setSegments(const gfx::DrawMode mode,
std::vector<uint16_t> indexes,
const SegmentBase* segments,
const std::size_t segmentCount) {
setSegments(mode, std::make_shared<gfx::IndexVectorBase>(std::move(indexes)), segments, segmentCount);
}
void DrawableBuilder::setSegments(const gfx::DrawMode mode,
gfx::IndexVectorBasePtr indexes,
const SegmentBase* segments,
const std::size_t segmentCount) {
if (!indexes || !indexes->elements()) {
assert("Missing segment indexes");
return;
}
impl->sharedIndexes = std::move(indexes);
for (std::size_t i = 0; i < segmentCount; ++i) {
const auto& seg = segments[i];
#if !defined(NDEBUG)
if (mode.type == DrawModeType::Triangles) {
assert(seg.indexLength % 3 == 0);
} else if (mode.type == DrawModeType::Lines) {
assert(seg.indexLength % 2 == 0);
}
const auto vertexCount = curVertexCount();
assert(!vertexCount || seg.vertexOffset + seg.vertexLength <= curVertexCount());
assert(seg.indexOffset + seg.indexLength <= impl->sharedIndexes->elements());
if (vertexCount) {
for (decltype(seg.indexLength) j = 0; j < seg.indexLength; ++j) {
assert(impl->sharedIndexes->vector()[seg.indexOffset + j] < vertexCount);
}
}
#endif
auto segCopy = SegmentBase{
// no copy constructor
seg.vertexOffset,
seg.indexOffset,
seg.vertexLength,
seg.indexLength,
seg.sortKey,
};
impl->segments.emplace_back(createSegment(mode, std::move(segCopy)));
}
}
void DrawableBuilder::addLines(const std::vector<uint16_t>& indexes,
std::size_t indexOffset,
std::size_t indexLength,
std::size_t baseIndex) {
if (!indexLength) {
return;
}
impl->segments.emplace_back(createSegment(Lines(lineWidth),
SegmentBase{/*.vertexOffset = */ 0,
/*.indexOffset = */ indexes.size(),
/*.vertexLength = */ 0,
/*.indexLength = */ indexLength}));
if (impl->buildIndexes.empty()) {
impl->buildIndexes.reserve(indexLength);
}
for (auto i = std::next(indexes.begin(), indexOffset); i != std::next(indexes.begin(), indexOffset + indexLength);
++i) {
impl->buildIndexes.emplace_back(static_cast<uint16_t>(*i + baseIndex));
}
}
void DrawableBuilder::addTriangles(const std::vector<uint16_t>& indexes,
std::size_t indexOffset,
std::size_t indexLength,
std::size_t baseIndex) {
if (!indexLength) {
return;
}
impl->segments.emplace_back(createSegment(Triangles(),
SegmentBase{/*.vertexOffset = */ 0,
/*.indexOffset = */ impl->buildIndexes.size(),
/*.vertexLength = */ impl->vertices.elements(),
/*.indexLength = */ indexLength}));
if (impl->buildIndexes.empty()) {
impl->buildIndexes.reserve(indexLength);
}
for (auto i = std::next(indexes.begin(), indexOffset); i != std::next(indexes.begin(), indexOffset + indexLength);
++i) {
impl->buildIndexes.emplace_back(static_cast<uint16_t>(*i + baseIndex));
}
}
std::size_t DrawableBuilder::curVertexCount() const {
return impl->vertexCount();
}
void DrawableBuilder::addPolyline(const GeometryCoordinates& coordinates,
const gfx::PolylineGeneratorOptions& options) {
// mark the current mode
if (!impl->checkAndSetMode(Impl::Mode::Polylines)) return;
// append polyline
impl->addPolyline(*this, coordinates, options);
}
} // namespace gfx
} // namespace mbgl