Use enum instead of packed struct for *Index objects (#1640)

Resolves: #1600

---------

Co-authored-by: IntegratedQuantum <43880493+IntegratedQuantum@users.noreply.github.com>
This commit is contained in:
Krzysztof Wiśniewski 2025-06-28 15:45:34 +02:00 committed by GitHub
parent 24a1fcdc69
commit 254546c789
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 58 additions and 55 deletions

View File

@ -301,7 +301,7 @@ pub fn createBlockModel(_: Block, modeData: *u16, zon: ZonElement) ModelIndex {
} }
pub fn model(block: Block) ModelIndex { pub fn model(block: Block) ModelIndex {
return .{.index = blocks.meshes.modelIndexStart(block).index + (block.data & 63)}; return blocks.meshes.modelIndexStart(block).add(block.data & 63);
} }
pub fn rotateZ(data: u16, angle: Degrees) u16 { pub fn rotateZ(data: u16, angle: Degrees) u16 {
@ -396,7 +396,7 @@ fn closestRay(block: Block, relativePlayerPos: Vec3f, playerDir: Vec3f) ?u16 {
const directionBitMask = Neighbor.bitMask(direction); const directionBitMask = Neighbor.bitMask(direction);
if((block.data & directionBitMask) != 0) { if((block.data & directionBitMask) != 0) {
const modelIndex = ModelIndex{.index = blocks.meshes.modelIndexStart(block).index + directionBitMask}; const modelIndex: ModelIndex = blocks.meshes.modelIndexStart(block).add(directionBitMask);
if(RotationMode.DefaultFunctions.rayModelIntersection(modelIndex, relativePlayerPos, playerDir)) |intersection| { if(RotationMode.DefaultFunctions.rayModelIntersection(modelIndex, relativePlayerPos, playerDir)) |intersection| {
if(@abs(closestIntersectionDistance) > @abs(intersection.distance)) { if(@abs(closestIntersectionDistance) > @abs(intersection.distance)) {
closestIntersectionDistance = intersection.distance; closestIntersectionDistance = intersection.distance;

View File

@ -120,7 +120,7 @@ pub fn createBlockModel(_: Block, _: *u16, zon: ZonElement) ModelIndex {
} }
pub fn model(block: Block) ModelIndex { pub fn model(block: Block) ModelIndex {
return .{.index = blocks.meshes.modelIndexStart(block).index + (@as(u6, @truncate(block.data)) -| 1)}; return blocks.meshes.modelIndexStart(block).add(@as(u6, @truncate(block.data)) -| 1);
} }
pub fn generateData(_: *main.game.World, _: Vec3i, relativePlayerPos: Vec3f, playerDir: Vec3f, relativeDir: Vec3i, _: ?Neighbor, currentData: *Block, neighbor: Block, _: bool) bool { pub fn generateData(_: *main.game.World, _: Vec3i, relativePlayerPos: Vec3f, playerDir: Vec3f, relativeDir: Vec3i, _: ?Neighbor, currentData: *Block, neighbor: Block, _: bool) bool {
@ -154,7 +154,7 @@ fn closestRay(comptime typ: enum {bit, intersection}, block: Block, _: ?main.ite
var resultBit: u16 = 0; var resultBit: u16 = 0;
for([_]u16{1, 2, 4, 8, 16, 32}) |bit| { for([_]u16{1, 2, 4, 8, 16, 32}) |bit| {
if(block.data & bit != 0) { if(block.data & bit != 0) {
const modelIndex = ModelIndex{.index = blocks.meshes.modelIndexStart(block).index + bit - 1}; const modelIndex: ModelIndex = blocks.meshes.modelIndexStart(block).add(bit - 1);
if(RotationMode.DefaultFunctions.rayModelIntersection(modelIndex, relativePlayerPos, playerDir)) |intersection| { if(RotationMode.DefaultFunctions.rayModelIntersection(modelIndex, relativePlayerPos, playerDir)) |intersection| {
if(result == null or result.?.distance > intersection.distance) { if(result == null or result.?.distance > intersection.distance) {
result = intersection; result = intersection;

View File

@ -44,7 +44,7 @@ pub fn createBlockModel(_: Block, _: *u16, zon: ZonElement) ModelIndex {
} }
pub fn model(block: Block) ModelIndex { pub fn model(block: Block) ModelIndex {
return .{.index = blocks.meshes.modelIndexStart(block).index + @min(block.data, 5)}; return blocks.meshes.modelIndexStart(block).add(@min(block.data, 5));
} }
pub fn rotateZ(data: u16, angle: Degrees) u16 { pub fn rotateZ(data: u16, angle: Degrees) u16 {

View File

@ -99,7 +99,7 @@ pub fn createBlockModel(_: Block, _: *u16, zon: ZonElement) ModelIndex {
} }
pub fn model(block: Block) ModelIndex { pub fn model(block: Block) ModelIndex {
return .{.index = blocks.meshes.modelIndexStart(block).index + (block.data & 15)}; return blocks.meshes.modelIndexStart(block).add(block.data & 15);
} }
pub fn updateData(block: *Block, neighbor: Neighbor, neighborBlock: Block) bool { pub fn updateData(block: *Block, neighbor: Neighbor, neighborBlock: Block) bool {

View File

@ -179,7 +179,7 @@ pub fn createBlockModel(_: Block, _: *u16, _: ZonElement) ModelIndex {
} }
pub fn model(block: Block) ModelIndex { pub fn model(block: Block) ModelIndex {
return .{.index = blocks.meshes.modelIndexStart(block).index + (block.data & 63)}; return blocks.meshes.modelIndexStart(block).add(block.data & 63);
} }
pub const rotateZ = branch.rotateZ; pub const rotateZ = branch.rotateZ;

View File

@ -42,7 +42,7 @@ pub fn createBlockModel(_: Block, _: *u16, zon: ZonElement) ModelIndex {
} }
pub fn model(block: Block) ModelIndex { pub fn model(block: Block) ModelIndex {
return .{.index = blocks.meshes.modelIndexStart(block).index + @min(block.data, 3)}; return blocks.meshes.modelIndexStart(block).add(@min(block.data, 3));
} }
pub fn rotateZ(data: u16, angle: Degrees) u16 { pub fn rotateZ(data: u16, angle: Degrees) u16 {

View File

@ -62,7 +62,7 @@ pub fn createBlockModel(_: Block, _: *u16, zon: ZonElement) ModelIndex {
} }
pub fn model(block: Block) ModelIndex { pub fn model(block: Block) ModelIndex {
return .{.index = blocks.meshes.modelIndexStart(block).index + @min(centerRotations*2 + sideRotations, block.data)}; return blocks.meshes.modelIndexStart(block).add(@min(centerRotations*2 + sideRotations, block.data));
} }
pub fn rotateZ(data: u16, angle: Degrees) u16 { pub fn rotateZ(data: u16, angle: Degrees) u16 {

View File

@ -243,7 +243,7 @@ pub fn createBlockModel(_: Block, _: *u16, _: ZonElement) ModelIndex {
} }
pub fn model(block: Block) ModelIndex { pub fn model(block: Block) ModelIndex {
return .{.index = blocks.meshes.modelIndexStart(block).index + (block.data & 255)}; return blocks.meshes.modelIndexStart(block).add(block.data & 255);
} }
pub fn generateData(_: *main.game.World, _: Vec3i, _: Vec3f, _: Vec3f, _: Vec3i, _: ?Neighbor, currentData: *Block, _: Block, blockPlacing: bool) bool { pub fn generateData(_: *main.game.World, _: Vec3i, _: Vec3f, _: Vec3f, _: Vec3i, _: ?Neighbor, currentData: *Block, _: Block, blockPlacing: bool) bool {
@ -259,7 +259,7 @@ fn closestRay(comptime typ: enum {bit, intersection}, block: Block, relativePlay
var resultBit: u16 = 0; var resultBit: u16 = 0;
for([_]u16{1, 2, 4, 8, 16, 32, 64, 128}) |bit| { for([_]u16{1, 2, 4, 8, 16, 32, 64, 128}) |bit| {
if(block.data & bit == 0) { if(block.data & bit == 0) {
const cornerModelIndex = ModelIndex{.index = blocks.meshes.modelIndexStart(block).index + (255 ^ bit)}; const cornerModelIndex: ModelIndex = blocks.meshes.modelIndexStart(block).add(255 ^ bit);
if(RotationMode.DefaultFunctions.rayModelIntersection(cornerModelIndex, relativePlayerPos, playerDir)) |intersection| { if(RotationMode.DefaultFunctions.rayModelIntersection(cornerModelIndex, relativePlayerPos, playerDir)) |intersection| {
if(result == null or intersection.distance < result.?.distance) { if(result == null or intersection.distance < result.?.distance) {
result = intersection; result = intersection;

View File

@ -54,7 +54,7 @@ pub fn createBlockModel(block: Block, modeData: *u16, zon: ZonElement) ModelInde
} }
pub fn model(block: Block) ModelIndex { pub fn model(block: Block) ModelIndex {
return .{.index = blocks.meshes.modelIndexStart(block).index + @min(block.data, block.modeData() - 1)}; return blocks.meshes.modelIndexStart(block).add(@min(block.data, block.modeData() - 1));
} }
pub fn generateData(_: *main.game.World, _: Vec3i, _: Vec3f, _: Vec3f, _: Vec3i, _: ?Neighbor, currentData: *Block, _: Block, blockPlacing: bool) bool { pub fn generateData(_: *main.game.World, _: Vec3i, _: Vec3f, _: Vec3f, _: Vec3i, _: ?Neighbor, currentData: *Block, _: Block, blockPlacing: bool) bool {

View File

@ -94,7 +94,7 @@ pub fn createBlockModel(_: Block, _: *u16, zon: ZonElement) ModelIndex {
} }
pub fn model(block: Block) ModelIndex { pub fn model(block: Block) ModelIndex {
return .{.index = blocks.meshes.modelIndexStart(block).index + (@as(u5, @truncate(block.data)) -| 1)}; return blocks.meshes.modelIndexStart(block).add(@as(u5, @truncate(block.data)) -| 1);
} }
pub fn rotateZ(data: u16, angle: Degrees) u16 { pub fn rotateZ(data: u16, angle: Degrees) u16 {
@ -172,7 +172,7 @@ fn closestRay(comptime typ: enum {bit, intersection}, block: Block, _: ?main.ite
var resultBit: u16 = 0; var resultBit: u16 = 0;
for([_]u16{1, 2, 4, 8, 16}) |bit| { for([_]u16{1, 2, 4, 8, 16}) |bit| {
if(block.data & bit != 0) { if(block.data & bit != 0) {
const modelIndex = ModelIndex{.index = blocks.meshes.modelIndexStart(block).index + bit - 1}; const modelIndex: ModelIndex = blocks.meshes.modelIndexStart(block).add(bit - 1);
if(RotationMode.DefaultFunctions.rayModelIntersection(modelIndex, relativePlayerPos, playerDir)) |intersection| { if(RotationMode.DefaultFunctions.rayModelIntersection(modelIndex, relativePlayerPos, playerDir)) |intersection| {
if(result == null or intersection.distance < result.?.distance) { if(result == null or intersection.distance < result.?.distance) {
result = intersection; result = intersection;

View File

@ -365,8 +365,8 @@ fn registerBlock(assetFolder: []const u8, id: []const u8, zon: ZonElement) !void
fn assignBlockItem(stringId: []const u8) !void { fn assignBlockItem(stringId: []const u8) !void {
const block = blocks_zig.getTypeById(stringId); const block = blocks_zig.getTypeById(stringId);
// TODO: This must be gone in PixelGuys/Cubyz#1205 // TODO: This must be gone in PixelGuys/Cubyz#1205
const index = (items_zig.BaseItemIndex.fromId(stringId) orelse unreachable).index; const index = items_zig.BaseItemIndex.fromId(stringId) orelse unreachable;
const item = &items_zig.itemList[index]; const item = &items_zig.itemList[@intFromEnum(index)];
item.block = block; item.block = block;
} }

View File

@ -477,7 +477,7 @@ pub const BlockEntityTypes = struct {
signData.renderedTexture.?.bindTo(0); signData.renderedTexture.?.bindTo(0);
c.glUniform1i(uniforms.quadIndex, quad.index); c.glUniform1i(uniforms.quadIndex, @intFromEnum(quad));
const mesh = main.renderer.mesh_storage.getMeshAndIncreaseRefCount(main.chunk.ChunkPosition.initFromWorldPos(signData.blockPos, 1)) orelse continue :outer; const mesh = main.renderer.mesh_storage.getMeshAndIncreaseRefCount(main.chunk.ChunkPosition.initFromWorldPos(signData.blockPos, 1)) orelse continue :outer;
defer mesh.decreaseRefCount(); defer mesh.decreaseRefCount();
mesh.lightingData[0].lock.lockRead(); mesh.lightingData[0].lock.lockRead();

View File

@ -607,7 +607,7 @@ pub const Player = struct { // MARK: Player
const block = main.renderer.mesh_storage.getBlock(selectedPos[0], selectedPos[1], selectedPos[2]) orelse return; const block = main.renderer.mesh_storage.getBlock(selectedPos[0], selectedPos[1], selectedPos[2]) orelse return;
const item: items.Item = for(0..items.itemListSize) |idx| { const item: items.Item = for(0..items.itemListSize) |idx| {
const baseItem: main.items.BaseItemIndex = .{.index = @intCast(idx)}; const baseItem: main.items.BaseItemIndex = @enumFromInt(idx);
if(baseItem.block() == block.typ) { if(baseItem.block() == block.typ) {
break .{.baseItem = baseItem}; break .{.baseItem = baseItem};
} }

View File

@ -592,13 +592,13 @@ pub const ItemDropRenderer = struct { // MARK: ItemDropRenderer
defer data.deinit(); defer data.deinit();
for(model.internalQuads) |quad| { for(model.internalQuads) |quad| {
const textureIndex = blocks.meshes.textureIndex(block, quad.quadInfo().textureSlot); const textureIndex = blocks.meshes.textureIndex(block, quad.quadInfo().textureSlot);
data.append(@as(u32, quad.index) << 16 | textureIndex); // modelAndTexture data.append(@as(u32, @intFromEnum(quad)) << 16 | textureIndex); // modelAndTexture
data.append(0); // offsetByNormal data.append(0); // offsetByNormal
} }
for(model.neighborFacingQuads) |list| { for(model.neighborFacingQuads) |list| {
for(list) |quad| { for(list) |quad| {
const textureIndex = blocks.meshes.textureIndex(block, quad.quadInfo().textureSlot); const textureIndex = blocks.meshes.textureIndex(block, quad.quadInfo().textureSlot);
data.append(@as(u32, quad.index) << 16 | textureIndex); // modelAndTexture data.append(@as(u32, @intFromEnum(quad)) << 16 | textureIndex); // modelAndTexture
data.append(1); // offsetByNormal data.append(1); // offsetByNormal
} }
} }

View File

@ -157,47 +157,47 @@ const MaterialProperty = enum {
} }
}; };
pub const BaseItemIndex = packed struct { pub const BaseItemIndex = enum(u16) {
index: u16, _,
pub fn fromId(_id: []const u8) ?BaseItemIndex { pub fn fromId(_id: []const u8) ?BaseItemIndex {
return reverseIndices.get(_id); return reverseIndices.get(_id);
} }
pub fn image(self: BaseItemIndex) graphics.Image { pub fn image(self: BaseItemIndex) graphics.Image {
return itemList[self.index].image; return itemList[@intFromEnum(self)].image;
} }
pub fn texture(self: BaseItemIndex) ?graphics.Texture { pub fn texture(self: BaseItemIndex) ?graphics.Texture {
return itemList[self.index].texture; return itemList[@intFromEnum(self)].texture;
} }
pub fn id(self: BaseItemIndex) []const u8 { pub fn id(self: BaseItemIndex) []const u8 {
return itemList[self.index].id; return itemList[@intFromEnum(self)].id;
} }
pub fn name(self: BaseItemIndex) []const u8 { pub fn name(self: BaseItemIndex) []const u8 {
return itemList[self.index].name; return itemList[@intFromEnum(self)].name;
} }
pub fn tags(self: BaseItemIndex) []const Tag { pub fn tags(self: BaseItemIndex) []const Tag {
return itemList[self.index].tags; return itemList[@intFromEnum(self)].tags;
} }
pub fn stackSize(self: BaseItemIndex) u16 { pub fn stackSize(self: BaseItemIndex) u16 {
return itemList[self.index].stackSize; return itemList[@intFromEnum(self)].stackSize;
} }
pub fn material(self: BaseItemIndex) ?Material { pub fn material(self: BaseItemIndex) ?Material {
return itemList[self.index].material; return itemList[@intFromEnum(self)].material;
} }
pub fn block(self: BaseItemIndex) ?u16 { pub fn block(self: BaseItemIndex) ?u16 {
return itemList[self.index].block; return itemList[@intFromEnum(self)].block;
} }
pub fn hasTag(self: BaseItemIndex, tag: Tag) bool { pub fn hasTag(self: BaseItemIndex, tag: Tag) bool {
return itemList[self.index].hasTag(tag); return itemList[@intFromEnum(self)].hasTag(tag);
} }
pub fn hashCode(self: BaseItemIndex) u32 { pub fn hashCode(self: BaseItemIndex) u32 {
return itemList[self.index].hashCode(); return itemList[@intFromEnum(self)].hashCode();
} }
pub fn getTexture(self: BaseItemIndex) graphics.Texture { pub fn getTexture(self: BaseItemIndex) graphics.Texture {
return itemList[self.index].getTexture(); return itemList[@intFromEnum(self)].getTexture();
} }
pub fn getTooltip(self: BaseItemIndex) []const u8 { pub fn getTooltip(self: BaseItemIndex) []const u8 {
return itemList[self.index].getTooltip(); return itemList[@intFromEnum(self)].getTooltip();
} }
}; };
@ -505,8 +505,8 @@ const PropertyMatrix = struct { // MARK: PropertyMatrix
}; };
}; };
pub const ToolTypeIndex = packed struct { pub const ToolTypeIndex = enum(u16) {
index: u16, _,
const ToolTypeIterator = struct { const ToolTypeIterator = struct {
i: u16 = 0, i: u16 = 0,
@ -514,7 +514,7 @@ pub const ToolTypeIndex = packed struct {
pub fn next(self: *ToolTypeIterator) ?ToolTypeIndex { pub fn next(self: *ToolTypeIterator) ?ToolTypeIndex {
if(self.i >= toolTypeList.items.len) return null; if(self.i >= toolTypeList.items.len) return null;
defer self.i += 1; defer self.i += 1;
return ToolTypeIndex{.index = self.i}; return @enumFromInt(self.i);
} }
}; };
@ -525,22 +525,22 @@ pub const ToolTypeIndex = packed struct {
return toolTypeIdToIndex.get(_id); return toolTypeIdToIndex.get(_id);
} }
pub fn id(self: ToolTypeIndex) []const u8 { pub fn id(self: ToolTypeIndex) []const u8 {
return toolTypeList.items[self.index].id; return toolTypeList.items[@intFromEnum(self)].id;
} }
pub fn blockTags(self: ToolTypeIndex) []const Tag { pub fn blockTags(self: ToolTypeIndex) []const Tag {
return toolTypeList.items[self.index].blockTags; return toolTypeList.items[@intFromEnum(self)].blockTags;
} }
pub fn properties(self: ToolTypeIndex) []const PropertyMatrix { pub fn properties(self: ToolTypeIndex) []const PropertyMatrix {
return toolTypeList.items[self.index].properties; return toolTypeList.items[@intFromEnum(self)].properties;
} }
pub fn slotInfos(self: ToolTypeIndex) *const [25]SlotInfo { pub fn slotInfos(self: ToolTypeIndex) *const [25]SlotInfo {
return &toolTypeList.items[self.index].slotInfos; return &toolTypeList.items[@intFromEnum(self)].slotInfos;
} }
pub fn pixelSources(self: ToolTypeIndex) *const [16][16]u8 { pub fn pixelSources(self: ToolTypeIndex) *const [16][16]u8 {
return &toolTypeList.items[self.index].pixelSources; return &toolTypeList.items[@intFromEnum(self)].pixelSources;
} }
pub fn pixelSourcesOverlay(self: ToolTypeIndex) *const [16][16]u8 { pub fn pixelSourcesOverlay(self: ToolTypeIndex) *const [16][16]u8 {
return &toolTypeList.items[self.index].pixelSourcesOverlay; return &toolTypeList.items[@intFromEnum(self)].pixelSourcesOverlay;
} }
}; };
@ -982,7 +982,7 @@ pub fn register(_: []const u8, texturePath: []const u8, replacementTexturePath:
defer itemListSize += 1; defer itemListSize += 1;
newItem.init(arena.allocator(), texturePath, replacementTexturePath, id, zon); newItem.init(arena.allocator(), texturePath, replacementTexturePath, id, zon);
reverseIndices.put(newItem.id, .{.index = itemListSize}) catch unreachable; reverseIndices.put(newItem.id, @enumFromInt(itemListSize)) catch unreachable;
std.log.debug("Registered item: {d: >5} '{s}'", .{itemListSize, id}); std.log.debug("Registered item: {d: >5} '{s}'", .{itemListSize, id});
return newItem; return newItem;
@ -1068,7 +1068,7 @@ pub fn registerTool(assetFolder: []const u8, id: []const u8, zon: ZonElement) vo
.pixelSources = pixelSources, .pixelSources = pixelSources,
.pixelSourcesOverlay = pixelSourcesOverlay, .pixelSourcesOverlay = pixelSourcesOverlay,
}); });
toolTypeIdToIndex.put(arena.allocator().allocator, idDupe, .{.index = @intCast(toolTypeList.items.len - 1)}) catch unreachable; toolTypeIdToIndex.put(arena.allocator().allocator, idDupe, @enumFromInt(toolTypeList.items.len - 1)) catch unreachable;
std.log.debug("Registered tool: '{s}'", .{id}); std.log.debug("Registered tool: '{s}'", .{id});
} }

View File

@ -60,23 +60,26 @@ const Quad = struct {
uvs: [4]usize, uvs: [4]usize,
}; };
pub const ModelIndex = packed struct { pub const ModelIndex = enum(u32) {
index: u32, _,
pub fn model(self: ModelIndex) *const Model { pub fn model(self: ModelIndex) *const Model {
return &models.items()[self.index]; return &models.items()[@intFromEnum(self)];
}
pub fn add(self: ModelIndex, offset: u32) ModelIndex {
return @enumFromInt(@intFromEnum(self) + offset);
} }
}; };
pub const QuadIndex = packed struct { pub const QuadIndex = enum(u16) {
index: u16, _,
pub fn quadInfo(self: QuadIndex) *const QuadInfo { pub fn quadInfo(self: QuadIndex) *const QuadInfo {
return &quads.items[self.index]; return &quads.items[@intFromEnum(self)];
} }
pub fn extraQuadInfo(self: QuadIndex) *const ExtraQuadInfo { pub fn extraQuadInfo(self: QuadIndex) *const ExtraQuadInfo {
return &extraQuadInfos.items[self.index]; return &extraQuadInfos.items[@intFromEnum(self)];
} }
}; };
@ -134,7 +137,7 @@ pub const Model = struct {
// Snap the normals as well: // Snap the normals as well:
dest.normal = snapToGrid(dest.normal); dest.normal = snapToGrid(dest.normal);
} }
const modelIndex: ModelIndex = .{.index = models.len}; const modelIndex: ModelIndex = @enumFromInt(models.len);
const self = models.addOne(); const self = models.addOne();
var amounts: [6]usize = .{0, 0, 0, 0, 0, 0}; var amounts: [6]usize = .{0, 0, 0, 0, 0, 0};
var internalAmount: usize = 0; var internalAmount: usize = 0;
@ -440,7 +443,7 @@ var nameToIndex: std.StringHashMap(ModelIndex) = undefined;
pub fn getModelIndex(string: []const u8) ModelIndex { pub fn getModelIndex(string: []const u8) ModelIndex {
return nameToIndex.get(string) orelse { return nameToIndex.get(string) orelse {
std.log.err("Couldn't find voxelModel with name: {s}.", .{string}); std.log.err("Couldn't find voxelModel with name: {s}.", .{string});
return .{.index = 0}; return @enumFromInt(0);
}; };
} }
@ -463,7 +466,7 @@ fn addQuad(info_: QuadInfo) error{Degenerate}!QuadIndex {
} }
} }
if(cornerEqualities >= 2) return error.Degenerate; // One corner equality is fine, since then the quad degenerates to a triangle, which has a non-zero area. if(cornerEqualities >= 2) return error.Degenerate; // One corner equality is fine, since then the quad degenerates to a triangle, which has a non-zero area.
const index: QuadIndex = .{.index = @intCast(quads.items.len)}; const index: QuadIndex = @enumFromInt(quads.items.len);
if(info.opaqueInLod == 2) { if(info.opaqueInLod == 2) {
info.opaqueInLod = 0; info.opaqueInLod = 0;
} else { } else {