Skip to content

Instantly share code, notes, and snippets.

@CrosRoad95
Created December 6, 2025 16:32
Show Gist options
  • Select an option

  • Save CrosRoad95/8ddc3457f14bc0bb9072246391becdf9 to your computer and use it in GitHub Desktop.

Select an option

Save CrosRoad95/8ddc3457f14bc0bb9072246391becdf9 to your computer and use it in GitHub Desktop.
struct VisibilityContext {
flecs::entity observer;
flecs::entity target;
float distanceSquared;
};
template <glm::vec3 (*ObserverPosFn)(flecs::entity), glm::vec3 (*TargetPosFn)(flecs::entity), typename... Checks>
struct VisibilityPipeline {
private:
std::tuple<Checks...> checks;
public:
VisibilityPipeline(Checks... c): checks(std::move(c)...) {}
FORCEINLINE bool IsVisible(flecs::entity observer, flecs::entity target) const {
VisibilityContext ctx {};
ctx.observer = observer;
ctx.target = target;
auto obsPos = ObserverPosFn(observer);
auto tgtPos = TargetPosFn(target);
ctx.distanceSquared = glm::distance(obsPos, tgtPos);
return IsVisibleImpl(ctx, std::index_sequence_for<Checks...> {});
}
template <typename Context>
FORCEINLINE bool IsVisible(const Context &ctx) const {
return IsVisibleImpl(ctx, std::index_sequence_for<Checks...> {});
}
private:
template <std::size_t... I, typename Context>
FORCEINLINE bool IsVisibleImpl(const Context &ctx, std::index_sequence<I...>) const {
return (... && std::get<I>(checks)(ctx));
}
};
template <auto ObsFn, auto TgtFn, typename... Checks>
FORCEINLINE auto CreateVisibilityPipeline(Checks... checks) {
return VisibilityPipeline<ObsFn, TgtFn, Checks...>(std::move(checks)...);
}
struct DistanceCheck {
float maxDistanceSq;
FORCEINLINE bool operator()(const VisibilityContext &ctx) const {
return ctx.distanceSquared <= maxDistanceSq;
}
};
template <typename Pipeline>
struct SubPipeline {
const Pipeline &subPipeline;
// Constructor
SubPipeline(const Pipeline &p): subPipeline(p) {}
FORCEINLINE bool operator()(const VisibilityContext &ctx) const {
return subPipeline.IsVisible(ctx.observer, ctx.target);
}
};
// Usage:
glm::vec3 getPos1(flecs::entity e) {
return glm::vec3 {0, 0, 0};
}
glm::vec3 getPos2(flecs::entity e) {
return glm::vec3 {10, 0, 0};
}
VisibilityPipeline customPipeline = CreateVisibilityPipeline<getPos1, getPos2>(DistanceCheck {15}, DistanceCheck {12});
VisibilityPipeline customPipeline2 = CreateVisibilityPipeline<getPos1, getPos2>(SubPipeline {customPipeline}, DistanceCheck {9});
flecs::entity a;
flecs::entity b;
bool result = customPipeline2.IsVisible(a, b);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment