}
}
+ struct FaceSet {
+
+ explicit FaceSet(unsigned char v = 0)
+ : value(v) { }
+
+ bool IsSet(Face f) const {
+ return value & Mask(f);
+ }
+ void Set(Face f) {
+ value |= Mask(f);
+ }
+ void Unset(Face f) {
+ value |= ~Mask(f);
+ }
+
+ void Clear() {
+ value = 0;
+ }
+ void Fill() {
+ value = Mask(FACE_COUNT) - 1;
+ }
+
+ bool Empty() const {
+ return value == 0;
+ }
+ bool All() const {
+ return value == Mask(FACE_COUNT) - 1;
+ }
+
+ unsigned char Mask(Face f) const {
+ return 1 << f;
+ }
+
+ unsigned char value;
+
+ };
+
};
for (size_t i = 0; i < Size(); ++i) {
const BlockType &type = Type(blocks[i]);
- if (!type.visible || Obstructed(i)) continue;
+ if (!type.visible || Obstructed(i).All()) continue;
type.FillBlockModel(buf, ToTransform(i), vtx_counter);
size_t vtx_begin = vtx_counter;
dirty = false;
}
-bool Chunk::Obstructed(int idx) const {
+Block::FaceSet Chunk::Obstructed(int idx) const {
Chunk::Pos pos(ToPos(idx));
+ Block::FaceSet result;
for (int f = 0; f < Block::FACE_COUNT; ++f) {
Block::Face face = Block::Face(f);
BlockLookup next(const_cast<Chunk *>(this), pos, face);
- if (!next || !next.GetType().FaceFilled(next.GetBlock(), Block::Opposite(face))) {
- return false;
+ if (next && next.GetType().FaceFilled(next.GetBlock(), Block::Opposite(face))) {
+ result.Set(face);
}
}
- return true;
+ return result;
}
glm::mat4 Chunk::ToTransform(int idx) const {
void Unlink();
void Relink();
- // check if block at given index is completely enclosed (and therefore invisible)
- bool Obstructed(int idx) const;
+ // check which faces of a block at given index are obstructed (and therefore invisible)
+ Block::FaceSet Obstructed(int idx) const;
void Invalidate() { dirty = true; }