Update light updates

- Remove NetworkLightUpdateMixin and associated code
- Do not defer level renderer reload when changing backend
- Remove RenderWork
- Reset DrawBuffer on free
- Move CoordinateConsumer inside ImmutableBox
- Rename GridAlignedBB -> MutableBox
- Rename LightListener#isListenerInvalid -> #isInvalid
- Move package light -> lib.light
- Move package util.box -> lib.box
This commit is contained in:
PepperCode1 2023-04-01 11:01:24 -07:00
parent a1910f06d4
commit f2d55a5001
28 changed files with 131 additions and 260 deletions

View file

@ -20,7 +20,6 @@ import com.jozufozu.flywheel.lib.model.PartialModel;
import com.jozufozu.flywheel.lib.pipeline.Pipelines; import com.jozufozu.flywheel.lib.pipeline.Pipelines;
import com.jozufozu.flywheel.lib.struct.StructTypes; import com.jozufozu.flywheel.lib.struct.StructTypes;
import com.jozufozu.flywheel.lib.util.QuadConverter; import com.jozufozu.flywheel.lib.util.QuadConverter;
import com.jozufozu.flywheel.lib.util.RenderWork;
import com.jozufozu.flywheel.lib.util.ShadersModHandler; import com.jozufozu.flywheel.lib.util.ShadersModHandler;
import com.jozufozu.flywheel.mixin.PausedPartialTickAccessor; import com.jozufozu.flywheel.mixin.PausedPartialTickAccessor;
import com.jozufozu.flywheel.vanilla.VanillaInstances; import com.jozufozu.flywheel.vanilla.VanillaInstances;
@ -97,8 +96,6 @@ public class Flywheel {
forgeEventBus.addListener(ForgeEvents::unloadWorld); forgeEventBus.addListener(ForgeEvents::unloadWorld);
forgeEventBus.addListener(ForgeEvents::tickLight); forgeEventBus.addListener(ForgeEvents::tickLight);
forgeEventBus.addListener(EventPriority.LOWEST, RenderWork::onRenderLevelLast);
modEventBus.addListener(PartialModel::onModelRegistry); modEventBus.addListener(PartialModel::onModelRegistry);
modEventBus.addListener(PartialModel::onModelBake); modEventBus.addListener(PartialModel::onModelBake);

View file

@ -9,7 +9,6 @@ import com.jozufozu.flywheel.api.backend.BackendType;
import com.jozufozu.flywheel.backend.task.ParallelTaskExecutor; import com.jozufozu.flywheel.backend.task.ParallelTaskExecutor;
import com.jozufozu.flywheel.config.FlwConfig; import com.jozufozu.flywheel.config.FlwConfig;
import com.jozufozu.flywheel.lib.backend.BackendTypes; import com.jozufozu.flywheel.lib.backend.BackendTypes;
import com.jozufozu.flywheel.lib.util.RenderWork;
import com.mojang.logging.LogUtils; import com.mojang.logging.LogUtils;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
@ -86,7 +85,7 @@ public class Backend {
} }
public static void reloadWorldRenderers() { public static void reloadWorldRenderers() {
RenderWork.enqueue(Minecraft.getInstance().levelRenderer::allChanged); Minecraft.getInstance().levelRenderer.allChanged();
} }
private static BackendType chooseEngine() { private static BackendType chooseEngine() {

View file

@ -127,6 +127,8 @@ public class DrawBuffer {
} }
public void free() { public void free() {
reset();
if (memory == null) { if (memory == null) {
return; return;
} }

View file

@ -9,10 +9,10 @@ import com.jozufozu.flywheel.api.instance.TickableInstance;
import com.jozufozu.flywheel.api.instancer.FlatLit; import com.jozufozu.flywheel.api.instancer.FlatLit;
import com.jozufozu.flywheel.api.instancer.InstancerManager; import com.jozufozu.flywheel.api.instancer.InstancerManager;
import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstanceManager; import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstanceManager;
import com.jozufozu.flywheel.light.LightListener; import com.jozufozu.flywheel.lib.light.LightListener;
import com.jozufozu.flywheel.util.box.ImmutableBox;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.SectionPos;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.LightLayer; import net.minecraft.world.level.LightLayer;
@ -86,7 +86,7 @@ public abstract class AbstractInstance implements Instance, LightListener {
} }
@Override @Override
public boolean isListenerInvalid() { public boolean isInvalid() {
return removed; return removed;
} }
@ -96,7 +96,7 @@ public abstract class AbstractInstance implements Instance, LightListener {
} }
@Override @Override
public void onLightUpdate(LightLayer type, ImmutableBox changed) { public void onLightUpdate(LightLayer type, SectionPos pos) {
updateLight(); updateLight();
} }

View file

@ -19,7 +19,7 @@ import com.jozufozu.flywheel.backend.instancing.ratelimit.DistanceUpdateLimiter;
import com.jozufozu.flywheel.backend.instancing.ratelimit.NonLimiter; import com.jozufozu.flywheel.backend.instancing.ratelimit.NonLimiter;
import com.jozufozu.flywheel.backend.instancing.storage.Storage; import com.jozufozu.flywheel.backend.instancing.storage.Storage;
import com.jozufozu.flywheel.config.FlwConfig; import com.jozufozu.flywheel.config.FlwConfig;
import com.jozufozu.flywheel.light.LightUpdater; import com.jozufozu.flywheel.lib.light.LightUpdater;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;

View file

@ -10,8 +10,8 @@ import com.jozufozu.flywheel.api.instance.TickableInstance;
import com.jozufozu.flywheel.api.instancer.InstancedPart; import com.jozufozu.flywheel.api.instancer.InstancedPart;
import com.jozufozu.flywheel.api.instancer.InstancerManager; import com.jozufozu.flywheel.api.instancer.InstancerManager;
import com.jozufozu.flywheel.backend.instancing.AbstractInstance; import com.jozufozu.flywheel.backend.instancing.AbstractInstance;
import com.jozufozu.flywheel.util.box.GridAlignedBB; import com.jozufozu.flywheel.lib.box.ImmutableBox;
import com.jozufozu.flywheel.util.box.ImmutableBox; import com.jozufozu.flywheel.lib.box.MutableBox;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntity;
@ -90,7 +90,7 @@ public abstract class BlockEntityInstance<T extends BlockEntity> extends Abstrac
@Override @Override
public ImmutableBox getVolume() { public ImmutableBox getVolume() {
return GridAlignedBB.from(pos); return MutableBox.from(pos);
} }
@Override @Override

View file

@ -9,7 +9,7 @@ import com.jozufozu.flywheel.backend.instancing.AbstractInstance;
import com.jozufozu.flywheel.backend.instancing.InstanceManager; import com.jozufozu.flywheel.backend.instancing.InstanceManager;
import com.jozufozu.flywheel.backend.instancing.storage.AbstractStorage; import com.jozufozu.flywheel.backend.instancing.storage.AbstractStorage;
import com.jozufozu.flywheel.backend.instancing.storage.Storage; import com.jozufozu.flywheel.backend.instancing.storage.Storage;
import com.jozufozu.flywheel.light.LightUpdater; import com.jozufozu.flywheel.lib.light.LightUpdater;
public class EffectInstanceManager extends InstanceManager<Effect> { public class EffectInstanceManager extends InstanceManager<Effect> {

View file

@ -7,9 +7,9 @@ import com.jozufozu.flywheel.api.instance.TickableInstance;
import com.jozufozu.flywheel.api.instancer.InstancerManager; import com.jozufozu.flywheel.api.instancer.InstancerManager;
import com.jozufozu.flywheel.backend.instancing.AbstractInstance; import com.jozufozu.flywheel.backend.instancing.AbstractInstance;
import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstanceManager; import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstanceManager;
import com.jozufozu.flywheel.light.LightListener; import com.jozufozu.flywheel.lib.box.MutableBox;
import com.jozufozu.flywheel.light.TickingLightListener; import com.jozufozu.flywheel.lib.light.LightListener;
import com.jozufozu.flywheel.util.box.GridAlignedBB; import com.jozufozu.flywheel.lib.light.TickingLightListener;
import com.mojang.math.Vector3f; import com.mojang.math.Vector3f;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
@ -38,16 +38,16 @@ import net.minecraft.world.phys.Vec3;
public abstract class EntityInstance<E extends Entity> extends AbstractInstance implements LightListener, TickingLightListener { public abstract class EntityInstance<E extends Entity> extends AbstractInstance implements LightListener, TickingLightListener {
protected final E entity; protected final E entity;
protected final GridAlignedBB bounds; protected final MutableBox bounds;
public EntityInstance(InstancerManager instancerManager, E entity) { public EntityInstance(InstancerManager instancerManager, E entity) {
super(instancerManager, entity.level); super(instancerManager, entity.level);
this.entity = entity; this.entity = entity;
bounds = GridAlignedBB.from(entity.getBoundingBox()); bounds = MutableBox.from(entity.getBoundingBox());
} }
@Override @Override
public GridAlignedBB getVolume() { public MutableBox getVolume() {
return bounds; return bounds;
} }

View file

@ -7,7 +7,7 @@ import com.jozufozu.flywheel.api.instance.DynamicInstance;
import com.jozufozu.flywheel.api.instance.TickableInstance; import com.jozufozu.flywheel.api.instance.TickableInstance;
import com.jozufozu.flywheel.api.instancer.InstancerManager; import com.jozufozu.flywheel.api.instancer.InstancerManager;
import com.jozufozu.flywheel.backend.instancing.AbstractInstance; import com.jozufozu.flywheel.backend.instancing.AbstractInstance;
import com.jozufozu.flywheel.light.LightUpdater; import com.jozufozu.flywheel.lib.light.LightUpdater;
public abstract class AbstractStorage<T> implements Storage<T> { public abstract class AbstractStorage<T> implements Storage<T> {
protected final List<TickableInstance> tickableInstances; protected final List<TickableInstance> tickableInstances;

View file

@ -7,7 +7,7 @@ import org.jetbrains.annotations.Nullable;
import com.jozufozu.flywheel.api.instancer.InstancerManager; import com.jozufozu.flywheel.api.instancer.InstancerManager;
import com.jozufozu.flywheel.backend.instancing.AbstractInstance; import com.jozufozu.flywheel.backend.instancing.AbstractInstance;
import com.jozufozu.flywheel.light.LightUpdater; import com.jozufozu.flywheel.lib.light.LightUpdater;
public abstract class One2OneStorage<T> extends AbstractStorage<T> { public abstract class One2OneStorage<T> extends AbstractStorage<T> {
private final Map<T, AbstractInstance> instances; private final Map<T, AbstractInstance> instances;

View file

@ -5,8 +5,8 @@ import java.util.ArrayList;
import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
import com.jozufozu.flywheel.lib.light.LightUpdater;
import com.jozufozu.flywheel.lib.memory.FlwMemoryTracker; import com.jozufozu.flywheel.lib.memory.FlwMemoryTracker;
import com.jozufozu.flywheel.light.LightUpdater;
import com.jozufozu.flywheel.util.StringUtil; import com.jozufozu.flywheel.util.StringUtil;
import com.jozufozu.flywheel.util.WorldAttached; import com.jozufozu.flywheel.util.WorldAttached;

View file

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.util.box; package com.jozufozu.flywheel.lib.box;
import static com.jozufozu.flywheel.util.RenderMath.isPowerOf2; import static com.jozufozu.flywheel.util.RenderMath.isPowerOf2;
@ -65,14 +65,14 @@ public interface ImmutableBox {
return isPowerOf2(volume()); return isPowerOf2(volume());
} }
default GridAlignedBB intersect(ImmutableBox other) { default MutableBox intersect(ImmutableBox other) {
int minX = Math.max(this.getMinX(), other.getMinX()); int minX = Math.max(this.getMinX(), other.getMinX());
int minY = Math.max(this.getMinY(), other.getMinY()); int minY = Math.max(this.getMinY(), other.getMinY());
int minZ = Math.max(this.getMinZ(), other.getMinZ()); int minZ = Math.max(this.getMinZ(), other.getMinZ());
int maxX = Math.min(this.getMaxX(), other.getMaxX()); int maxX = Math.min(this.getMaxX(), other.getMaxX());
int maxY = Math.min(this.getMaxY(), other.getMaxY()); int maxY = Math.min(this.getMaxY(), other.getMaxY());
int maxZ = Math.min(this.getMaxZ(), other.getMaxZ()); int maxZ = Math.min(this.getMaxZ(), other.getMaxZ());
return new GridAlignedBB(minX, minY, minZ, maxX, maxY, maxZ); return new MutableBox(minX, minY, minZ, maxX, maxY, maxZ);
} }
default ImmutableBox union(ImmutableBox other) { default ImmutableBox union(ImmutableBox other) {
@ -82,7 +82,7 @@ public interface ImmutableBox {
int maxX = Math.max(this.getMaxX(), other.getMaxX()); int maxX = Math.max(this.getMaxX(), other.getMaxX());
int maxY = Math.max(this.getMaxY(), other.getMaxY()); int maxY = Math.max(this.getMaxY(), other.getMaxY());
int maxZ = Math.max(this.getMaxZ(), other.getMaxZ()); int maxZ = Math.max(this.getMaxZ(), other.getMaxZ());
return new GridAlignedBB(minX, minY, minZ, maxX, maxY, maxZ); return new MutableBox(minX, minY, minZ, maxX, maxY, maxZ);
} }
@ -108,7 +108,7 @@ public interface ImmutableBox {
&& other.getMaxZ() <= this.getMaxZ(); && other.getMaxZ() <= this.getMaxZ();
} }
default boolean isContainedBy(GridAlignedBB other) { default boolean isContainedBy(MutableBox other) {
return other.contains(this); return other.contains(this);
} }
@ -132,7 +132,12 @@ public interface ImmutableBox {
return new AABB(getMinX(), getMinY(), getMinZ(), getMaxX(), getMaxY(), getMaxZ()); return new AABB(getMinX(), getMinY(), getMinZ(), getMaxX(), getMaxY(), getMaxZ());
} }
default GridAlignedBB copy() { default MutableBox copy() {
return new GridAlignedBB(getMinX(), getMinY(), getMinZ(), getMaxX(), getMaxY(), getMaxZ()); return new MutableBox(getMinX(), getMinY(), getMinZ(), getMaxX(), getMaxY(), getMaxZ());
}
@FunctionalInterface
interface CoordinateConsumer {
void consume(int x, int y, int z);
} }
} }

View file

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.util.box; package com.jozufozu.flywheel.lib.box;
import java.util.Collection; import java.util.Collection;
@ -10,7 +10,7 @@ import net.minecraft.core.SectionPos;
import net.minecraft.core.Vec3i; import net.minecraft.core.Vec3i;
import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.AABB;
public class GridAlignedBB implements ImmutableBox { public class MutableBox implements ImmutableBox {
private int minX; private int minX;
private int minY; private int minY;
private int minZ; private int minZ;
@ -18,11 +18,11 @@ public class GridAlignedBB implements ImmutableBox {
private int maxY; private int maxY;
private int maxZ; private int maxZ;
public GridAlignedBB() { public MutableBox() {
} }
public GridAlignedBB(int minX, int minY, int minZ, int maxX, int maxY, int maxZ) { public MutableBox(int minX, int minY, int minZ, int maxX, int maxY, int maxZ) {
this.minX = minX; this.minX = minX;
this.minY = minY; this.minY = minY;
this.minZ = minZ; this.minZ = minZ;
@ -31,41 +31,41 @@ public class GridAlignedBB implements ImmutableBox {
this.maxZ = maxZ; this.maxZ = maxZ;
} }
public static GridAlignedBB ofRadius(int radius) { public static MutableBox ofRadius(int radius) {
return new GridAlignedBB(-radius, -radius, -radius, radius + 1, radius + 1, radius + 1); return new MutableBox(-radius, -radius, -radius, radius + 1, radius + 1, radius + 1);
} }
public static GridAlignedBB from(AABB aabb) { public static MutableBox from(AABB aabb) {
int minX = (int) Math.floor(aabb.minX); int minX = (int) Math.floor(aabb.minX);
int minY = (int) Math.floor(aabb.minY); int minY = (int) Math.floor(aabb.minY);
int minZ = (int) Math.floor(aabb.minZ); int minZ = (int) Math.floor(aabb.minZ);
int maxX = (int) Math.ceil(aabb.maxX); int maxX = (int) Math.ceil(aabb.maxX);
int maxY = (int) Math.ceil(aabb.maxY); int maxY = (int) Math.ceil(aabb.maxY);
int maxZ = (int) Math.ceil(aabb.maxZ); int maxZ = (int) Math.ceil(aabb.maxZ);
return new GridAlignedBB(minX, minY, minZ, maxX, maxY, maxZ); return new MutableBox(minX, minY, minZ, maxX, maxY, maxZ);
} }
public static GridAlignedBB from(SectionPos pos) { public static MutableBox from(SectionPos pos) {
return new GridAlignedBB(pos.minBlockX(), pos.minBlockY(), pos.minBlockZ(), pos.maxBlockX() + 1, pos.maxBlockY() + 1, pos.maxBlockZ() + 1); return new MutableBox(pos.minBlockX(), pos.minBlockY(), pos.minBlockZ(), pos.maxBlockX() + 1, pos.maxBlockY() + 1, pos.maxBlockZ() + 1);
} }
public static GridAlignedBB from(BlockPos start, BlockPos end) { public static MutableBox from(BlockPos start, BlockPos end) {
return new GridAlignedBB(start.getX(), start.getY(), start.getZ(), end.getX() + 1, end.getY() + 1, end.getZ() + 1); return new MutableBox(start.getX(), start.getY(), start.getZ(), end.getX() + 1, end.getY() + 1, end.getZ() + 1);
} }
public static GridAlignedBB from(BlockPos pos) { public static MutableBox from(BlockPos pos) {
return new GridAlignedBB(pos.getX(), pos.getY(), pos.getZ(), pos.getX() + 1, pos.getY() + 1, pos.getZ() + 1); return new MutableBox(pos.getX(), pos.getY(), pos.getZ(), pos.getX() + 1, pos.getY() + 1, pos.getZ() + 1);
} }
public static GridAlignedBB from(int sectionX, int sectionZ) { public static MutableBox from(int sectionX, int sectionZ) {
int startX = sectionX << 4; int startX = sectionX << 4;
int startZ = sectionZ << 4; int startZ = sectionZ << 4;
return new GridAlignedBB(startX, 0, startZ, startX + 16, 256, startZ + 16); return new MutableBox(startX, 0, startZ, startX + 16, 256, startZ + 16);
} }
public static ImmutableBox containingAll(Collection<BlockPos> positions) { public static ImmutableBox containingAll(Collection<BlockPos> positions) {
if (positions.isEmpty()) { if (positions.isEmpty()) {
return new GridAlignedBB(); return new MutableBox();
} }
int minX = Integer.MAX_VALUE; int minX = Integer.MAX_VALUE;
int minY = Integer.MAX_VALUE; int minY = Integer.MAX_VALUE;
@ -81,7 +81,7 @@ public class GridAlignedBB implements ImmutableBox {
maxY = Math.max(maxY, pos.getY()); maxY = Math.max(maxY, pos.getY());
maxZ = Math.max(maxZ, pos.getZ()); maxZ = Math.max(maxZ, pos.getZ());
} }
return new GridAlignedBB(minX, minY, minZ, maxX, maxY, maxZ); return new MutableBox(minX, minY, minZ, maxX, maxY, maxZ);
} }
public void fixMinMax() { public void fixMinMax() {
@ -277,37 +277,37 @@ public class GridAlignedBB implements ImmutableBox {
return maxZ; return maxZ;
} }
public GridAlignedBB setMinX(int minX) { public MutableBox setMinX(int minX) {
this.minX = minX; this.minX = minX;
return this; return this;
} }
public GridAlignedBB setMinY(int minY) { public MutableBox setMinY(int minY) {
this.minY = minY; this.minY = minY;
return this; return this;
} }
public GridAlignedBB setMinZ(int minZ) { public MutableBox setMinZ(int minZ) {
this.minZ = minZ; this.minZ = minZ;
return this; return this;
} }
public GridAlignedBB setMaxX(int maxX) { public MutableBox setMaxX(int maxX) {
this.maxX = maxX; this.maxX = maxX;
return this; return this;
} }
public GridAlignedBB setMaxY(int maxY) { public MutableBox setMaxY(int maxY) {
this.maxY = maxY; this.maxY = maxY;
return this; return this;
} }
public GridAlignedBB setMaxZ(int maxZ) { public MutableBox setMaxZ(int maxZ) {
this.maxZ = maxZ; this.maxZ = maxZ;
return this; return this;
} }
public GridAlignedBB assign(BlockPos start, BlockPos end) { public MutableBox assign(BlockPos start, BlockPos end) {
minX = start.getX(); minX = start.getX();
minY = start.getY(); minY = start.getY();
minZ = start.getZ(); minZ = start.getZ();
@ -317,22 +317,22 @@ public class GridAlignedBB implements ImmutableBox {
return this; return this;
} }
public GridAlignedBB setMax(Vec3i v) { public MutableBox setMax(Vec3i v) {
return setMax(v.getX(), v.getY(), v.getZ()); return setMax(v.getX(), v.getY(), v.getZ());
} }
public GridAlignedBB setMin(Vec3i v) { public MutableBox setMin(Vec3i v) {
return setMin(v.getX(), v.getY(), v.getZ()); return setMin(v.getX(), v.getY(), v.getZ());
} }
public GridAlignedBB setMax(int x, int y, int z) { public MutableBox setMax(int x, int y, int z) {
maxX = x; maxX = x;
maxY = y; maxY = y;
maxZ = z; maxZ = z;
return this; return this;
} }
public GridAlignedBB setMin(int x, int y, int z) { public MutableBox setMin(int x, int y, int z) {
minX = x; minX = x;
minY = y; minY = y;
minZ = z; minZ = z;
@ -376,14 +376,14 @@ public class GridAlignedBB implements ImmutableBox {
} }
@Override @Override
public GridAlignedBB intersect(ImmutableBox other) { public MutableBox intersect(ImmutableBox other) {
int minX = Math.max(this.minX, other.getMinX()); int minX = Math.max(this.minX, other.getMinX());
int minY = Math.max(this.minY, other.getMinY()); int minY = Math.max(this.minY, other.getMinY());
int minZ = Math.max(this.minZ, other.getMinZ()); int minZ = Math.max(this.minZ, other.getMinZ());
int maxX = Math.min(this.maxX, other.getMaxX()); int maxX = Math.min(this.maxX, other.getMaxX());
int maxY = Math.min(this.maxY, other.getMaxY()); int maxY = Math.min(this.maxY, other.getMaxY());
int maxZ = Math.min(this.maxZ, other.getMaxZ()); int maxZ = Math.min(this.maxZ, other.getMaxZ());
return new GridAlignedBB(minX, minY, minZ, maxX, maxY, maxZ); return new MutableBox(minX, minY, minZ, maxX, maxY, maxZ);
} }
@Override @Override
@ -394,7 +394,7 @@ public class GridAlignedBB implements ImmutableBox {
int maxX = Math.max(this.maxX, other.getMaxX()); int maxX = Math.max(this.maxX, other.getMaxX());
int maxY = Math.max(this.maxY, other.getMaxY()); int maxY = Math.max(this.maxY, other.getMaxY());
int maxZ = Math.max(this.maxZ, other.getMaxZ()); int maxZ = Math.max(this.maxZ, other.getMaxZ());
return new GridAlignedBB(minX, minY, minZ, maxX, maxY, maxZ); return new MutableBox(minX, minY, minZ, maxX, maxY, maxZ);
} }
@Override @Override
@ -426,8 +426,8 @@ public class GridAlignedBB implements ImmutableBox {
} }
@Override @Override
public GridAlignedBB copy() { public MutableBox copy() {
return new GridAlignedBB(minX, minY, minZ, maxX, maxY, maxZ); return new MutableBox(minX, minY, minZ, maxX, maxY, maxZ);
} }
@Override @Override

View file

@ -1,9 +1,10 @@
package com.jozufozu.flywheel.light; package com.jozufozu.flywheel.lib.light;
import java.util.stream.Stream; import java.util.stream.Stream;
import com.jozufozu.flywheel.util.box.ImmutableBox; import com.jozufozu.flywheel.lib.box.ImmutableBox;
import net.minecraft.core.SectionPos;
import net.minecraft.world.level.LightLayer; import net.minecraft.world.level.LightLayer;
public class DummyLightUpdater extends LightUpdater { public class DummyLightUpdater extends LightUpdater {
@ -29,12 +30,7 @@ public class DummyLightUpdater extends LightUpdater {
} }
@Override @Override
public void onLightUpdate(LightLayer type, long sectionPos) { public void onLightUpdate(LightLayer type, SectionPos pos) {
// noop
}
@Override
public void onLightPacket(int chunkX, int chunkZ) {
// noop // noop
} }

View file

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.light; package com.jozufozu.flywheel.lib.light;
import static org.lwjgl.opengl.GL11.GL_LINEAR; import static org.lwjgl.opengl.GL11.GL_LINEAR;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_MAG_FILTER; import static org.lwjgl.opengl.GL11.GL_TEXTURE_MAG_FILTER;
@ -23,14 +23,14 @@ import org.lwjgl.opengl.GL30;
import com.jozufozu.flywheel.gl.GlTexture; import com.jozufozu.flywheel.gl.GlTexture;
import com.jozufozu.flywheel.gl.GlTextureUnit; import com.jozufozu.flywheel.gl.GlTextureUnit;
import com.jozufozu.flywheel.util.box.GridAlignedBB; import com.jozufozu.flywheel.lib.box.ImmutableBox;
import com.jozufozu.flywheel.util.box.ImmutableBox; import com.jozufozu.flywheel.lib.box.MutableBox;
import net.minecraft.world.level.BlockAndTintGetter; import net.minecraft.world.level.BlockAndTintGetter;
public class GPULightVolume extends LightVolume { public class GPULightVolume extends LightVolume {
protected final GridAlignedBB sampleVolume = new GridAlignedBB(); protected final MutableBox sampleVolume = new MutableBox();
private final GlTexture glTexture; private final GlTexture glTexture;
private final GlTextureUnit textureUnit = GlTextureUnit.T4; private final GlTextureUnit textureUnit = GlTextureUnit.T4;

View file

@ -1,8 +1,8 @@
package com.jozufozu.flywheel.light; package com.jozufozu.flywheel.lib.light;
import com.jozufozu.flywheel.util.box.GridAlignedBB; import com.jozufozu.flywheel.lib.box.ImmutableBox;
import com.jozufozu.flywheel.util.box.ImmutableBox;
import net.minecraft.core.SectionPos;
import net.minecraft.world.level.LightLayer; import net.minecraft.world.level.LightLayer;
/** /**
@ -20,22 +20,10 @@ public interface LightListener {
* @return {@code true} if the listener is invalid/removed/deleted, * @return {@code true} if the listener is invalid/removed/deleted,
* and should no longer receive updates. * and should no longer receive updates.
*/ */
boolean isListenerInvalid(); boolean isInvalid();
/** /**
* Called when a light updates in a chunk the implementor cares about. * Called when a light updates in a chunk the implementor cares about.
*/ */
void onLightUpdate(LightLayer type, ImmutableBox changed); void onLightUpdate(LightLayer type, SectionPos pos);
/**
* Called when the server sends light data to the client.
*
*/
default void onLightPacket(int chunkX, int chunkZ) {
GridAlignedBB changedVolume = GridAlignedBB.from(chunkX, chunkZ);
onLightUpdate(LightLayer.BLOCK, changedVolume);
onLightUpdate(LightLayer.SKY, changedVolume);
}
} }

View file

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.light; package com.jozufozu.flywheel.lib.light;
/** /**
* Utility class for bit-twiddling light. * Utility class for bit-twiddling light.

View file

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.light; package com.jozufozu.flywheel.lib.light;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.LevelAccessor;

View file

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.light; package com.jozufozu.flywheel.lib.light;
import java.util.Queue; import java.util.Queue;
import java.util.Set; import java.util.Set;
@ -6,15 +6,12 @@ import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.stream.Stream; import java.util.stream.Stream;
import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.task.ParallelTaskExecutor;
import com.jozufozu.flywheel.backend.task.WorkGroup; import com.jozufozu.flywheel.backend.task.WorkGroup;
import com.jozufozu.flywheel.lib.box.ImmutableBox;
import com.jozufozu.flywheel.util.FlwUtil; import com.jozufozu.flywheel.util.FlwUtil;
import com.jozufozu.flywheel.util.WorldAttached; import com.jozufozu.flywheel.util.WorldAttached;
import com.jozufozu.flywheel.util.box.GridAlignedBB;
import com.jozufozu.flywheel.util.box.ImmutableBox;
import it.unimi.dsi.fastutil.longs.LongSet; import it.unimi.dsi.fastutil.longs.LongSet;
import net.minecraft.core.BlockPos;
import net.minecraft.core.SectionPos; import net.minecraft.core.SectionPos;
import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.LightLayer; import net.minecraft.world.level.LightLayer;
@ -28,7 +25,11 @@ import net.minecraft.world.level.LightLayer;
public class LightUpdater { public class LightUpdater {
private static final WorldAttached<LightUpdater> LEVELS = new WorldAttached<>(LightUpdater::new); private static final WorldAttached<LightUpdater> LEVELS = new WorldAttached<>(LightUpdater::new);
private final ParallelTaskExecutor taskExecutor;
private final LevelAccessor level;
private final WeakContainmentMultiMap<LightListener> listenersBySection = new WeakContainmentMultiMap<>();
private final Set<TickingLightListener> tickingListeners = FlwUtil.createWeakHashSet();
public static LightUpdater get(LevelAccessor level) { public static LightUpdater get(LevelAccessor level) {
if (LightUpdated.receivesLightUpdates(level)) { if (LightUpdated.receivesLightUpdates(level)) {
@ -40,14 +41,7 @@ public class LightUpdater {
} }
} }
private final LevelAccessor level;
private final Set<TickingLightListener> tickingLightListeners = FlwUtil.createWeakHashSet();
private final WeakContainmentMultiMap<LightListener> sections = new WeakContainmentMultiMap<>();
private final WeakContainmentMultiMap<LightListener> chunks = new WeakContainmentMultiMap<>();
public LightUpdater(LevelAccessor level) { public LightUpdater(LevelAccessor level) {
taskExecutor = Backend.getTaskExecutor();
this.level = level; this.level = level;
} }
@ -57,7 +51,7 @@ public class LightUpdater {
} }
private void tickSerial() { private void tickSerial() {
for (TickingLightListener tickingLightListener : tickingLightListeners) { for (TickingLightListener tickingLightListener : tickingListeners) {
if (tickingLightListener.tickLightListener()) { if (tickingLightListener.tickLightListener()) {
addListener(tickingLightListener); addListener(tickingLightListener);
} }
@ -68,13 +62,13 @@ public class LightUpdater {
Queue<LightListener> listeners = new ConcurrentLinkedQueue<>(); Queue<LightListener> listeners = new ConcurrentLinkedQueue<>();
WorkGroup.builder() WorkGroup.builder()
.addTasks(tickingLightListeners.stream(), listener -> { .addTasks(tickingListeners.stream(), listener -> {
if (listener.tickLightListener()) { if (listener.tickLightListener()) {
listeners.add(listener); listeners.add(listener);
} }
}) })
.onComplete(() -> listeners.forEach(this::addListener)) .onComplete(() -> listeners.forEach(this::addListener))
.execute(taskExecutor); .execute(Backend.getTaskExecutor());
} }
/** /**
@ -84,12 +78,11 @@ public class LightUpdater {
*/ */
public void addListener(LightListener listener) { public void addListener(LightListener listener) {
if (listener instanceof TickingLightListener) if (listener instanceof TickingLightListener)
tickingLightListeners.add(((TickingLightListener) listener)); tickingListeners.add(((TickingLightListener) listener));
ImmutableBox box = listener.getVolume(); ImmutableBox box = listener.getVolume();
LongSet sections = this.sections.getAndResetContainment(listener); LongSet sections = this.listenersBySection.getAndResetContainment(listener);
LongSet chunks = this.chunks.getAndResetContainment(listener);
int minX = SectionPos.blockToSectionCoord(box.getMinX()); int minX = SectionPos.blockToSectionCoord(box.getMinX());
int minY = SectionPos.blockToSectionCoord(box.getMinY()); int minY = SectionPos.blockToSectionCoord(box.getMinY());
@ -99,75 +92,42 @@ public class LightUpdater {
int maxZ = SectionPos.blockToSectionCoord(box.getMaxZ()); int maxZ = SectionPos.blockToSectionCoord(box.getMaxZ());
for (int x = minX; x <= maxX; x++) { for (int x = minX; x <= maxX; x++) {
for (int z = minZ; z <= maxZ; z++) {
for (int y = minY; y <= maxY; y++) { for (int y = minY; y <= maxY; y++) {
for (int z = minZ; z <= maxZ; z++) {
long sectionPos = SectionPos.asLong(x, y, z); long sectionPos = SectionPos.asLong(x, y, z);
this.sections.put(sectionPos, listener); this.listenersBySection.put(sectionPos, listener);
sections.add(sectionPos); sections.add(sectionPos);
} }
long chunkPos = SectionPos.asLong(x, 0, z);
this.chunks.put(chunkPos, listener);
chunks.add(chunkPos);
} }
} }
} }
public void removeListener(LightListener listener) { public void removeListener(LightListener listener) {
this.sections.remove(listener); this.listenersBySection.remove(listener);
this.chunks.remove(listener);
} }
/** /**
* Dispatch light updates to all registered {@link LightListener}s. * Dispatch light updates to all registered {@link LightListener}s.
* @param type The type of light that changed. * @param type The type of light that changed.
* @param sectionPos A long representing the section position where light changed. * @param pos The section position where light changed.
*/ */
public void onLightUpdate(LightLayer type, long sectionPos) { public void onLightUpdate(LightLayer type, SectionPos pos) {
Set<LightListener> set = sections.get(sectionPos); Set<LightListener> listeners = listenersBySection.get(pos.asLong());
if (set == null || set.isEmpty()) return; if (listeners == null || listeners.isEmpty()) return;
set.removeIf(LightListener::isListenerInvalid); listeners.removeIf(LightListener::isInvalid);
ImmutableBox chunkBox = GridAlignedBB.from(SectionPos.of(sectionPos)); for (LightListener listener : listeners) {
listener.onLightUpdate(type, pos);
for (LightListener listener : set) {
listener.onLightUpdate(type, chunkBox);
} }
} }
/**
* Dispatch light updates to all registered {@link LightListener}s
* when the server sends lighting data for an entire chunk.
*
*/
public void onLightPacket(int chunkX, int chunkZ) {
long chunkPos = SectionPos.asLong(chunkX, 0, chunkZ);
Set<LightListener> set = chunks.get(chunkPos);
if (set == null || set.isEmpty()) return;
set.removeIf(LightListener::isListenerInvalid);
for (LightListener listener : set) {
listener.onLightPacket(chunkX, chunkZ);
}
}
public static long blockToSection(BlockPos pos) {
return SectionPos.asLong(pos.getX(), pos.getY(), pos.getZ());
}
public static long sectionToChunk(long sectionPos) {
return sectionPos & 0xFFFFFFFFFFF_00000L;
}
public Stream<ImmutableBox> getAllBoxes() { public Stream<ImmutableBox> getAllBoxes() {
return chunks.stream().map(LightListener::getVolume); return listenersBySection.stream().map(LightListener::getVolume);
} }
public boolean isEmpty() { public boolean isEmpty() {
return chunks.isEmpty(); return listenersBySection.isEmpty();
} }
} }

View file

@ -1,19 +1,20 @@
package com.jozufozu.flywheel.light; package com.jozufozu.flywheel.lib.light;
import org.lwjgl.system.MemoryUtil; import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.lib.box.ImmutableBox;
import com.jozufozu.flywheel.lib.box.MutableBox;
import com.jozufozu.flywheel.lib.memory.MemoryBlock; import com.jozufozu.flywheel.lib.memory.MemoryBlock;
import com.jozufozu.flywheel.util.box.GridAlignedBB;
import com.jozufozu.flywheel.util.box.ImmutableBox;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.SectionPos;
import net.minecraft.world.level.BlockAndTintGetter; import net.minecraft.world.level.BlockAndTintGetter;
import net.minecraft.world.level.LightLayer; import net.minecraft.world.level.LightLayer;
public class LightVolume implements ImmutableBox, LightListener { public class LightVolume implements ImmutableBox, LightListener {
protected final BlockAndTintGetter level; protected final BlockAndTintGetter level;
protected final GridAlignedBB box = new GridAlignedBB(); protected final MutableBox box = new MutableBox();
protected MemoryBlock lightData; protected MemoryBlock lightData;
public LightVolume(BlockAndTintGetter level, ImmutableBox sampleVolume) { public LightVolume(BlockAndTintGetter level, ImmutableBox sampleVolume) {
@ -59,7 +60,7 @@ public class LightVolume implements ImmutableBox, LightListener {
} }
@Override @Override
public boolean isListenerInvalid() { public boolean isInvalid() {
return lightData == null; return lightData == null;
} }
@ -207,10 +208,10 @@ public class LightVolume implements ImmutableBox, LightListener {
} }
@Override @Override
public void onLightUpdate(LightLayer type, ImmutableBox changedVolume) { public void onLightUpdate(LightLayer type, SectionPos pos) {
if (lightData == null) return; if (lightData == null) return;
GridAlignedBB vol = changedVolume.copy(); MutableBox vol = MutableBox.from(pos);
if (!vol.intersects(getVolume())) return; if (!vol.intersects(getVolume())) return;
vol.intersectAssign(getVolume()); // compute the region contained by us that has dirty lighting data. vol.intersectAssign(getVolume()); // compute the region contained by us that has dirty lighting data.
@ -219,16 +220,4 @@ public class LightVolume implements ImmutableBox, LightListener {
markDirty(); markDirty();
} }
@Override
public void onLightPacket(int chunkX, int chunkZ) {
if (lightData == null) return;
GridAlignedBB changedVolume = GridAlignedBB.from(chunkX, chunkZ);
if (!changedVolume.intersects(getVolume())) return;
changedVolume.intersectAssign(getVolume()); // compute the region contained by us that has dirty lighting data.
copyLight(changedVolume);
markDirty();
}
} }

View file

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.light; package com.jozufozu.flywheel.lib.light;
public interface TickingLightListener extends LightListener { public interface TickingLightListener extends LightListener {
/** /**

View file

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.light; package com.jozufozu.flywheel.lib.light;
import java.util.AbstractCollection; import java.util.AbstractCollection;
import java.util.Iterator; import java.util.Iterator;
@ -24,7 +24,7 @@ public class WeakContainmentMultiMap<T> extends AbstractCollection<T> {
} }
/** /**
* This is a confusing function, but it maintains the internal state of the chunk/section maps. * This is a confusing function, but it maintains the internal state of the section maps.
* *
* <p> * <p>
* First, uses the reverse lookup map to remove listener from all sets in the lookup map.<br> * First, uses the reverse lookup map to remove listener from all sets in the lookup map.<br>
@ -32,7 +32,7 @@ public class WeakContainmentMultiMap<T> extends AbstractCollection<T> {
* </p> * </p>
* *
* @param listener The listener to clean up. * @param listener The listener to clean up.
* @return An empty set that should be populated with the chunks/sections the listener is contained in. * @return An empty set that should be populated with the sections the listener is contained in.
*/ */
public LongSet getAndResetContainment(T listener) { public LongSet getAndResetContainment(T listener) {
LongSet containmentSet = reverse.computeIfAbsent(listener, $ -> new LongRBTreeSet()); LongSet containmentSet = reverse.computeIfAbsent(listener, $ -> new LongRBTreeSet());

View file

@ -1,24 +0,0 @@
package com.jozufozu.flywheel.lib.util;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import net.minecraftforge.client.event.RenderLevelLastEvent;
public class RenderWork {
private static final Queue<Runnable> RUNS = new ConcurrentLinkedQueue<>();
public static void onRenderLevelLast(RenderLevelLastEvent event) {
while (!RUNS.isEmpty()) {
RUNS.remove()
.run();
}
}
/**
* Queue work to be executed at the end of a frame
*/
public static void enqueue(Runnable run) {
RUNS.add(run);
}
}

View file

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.mixin.light; package com.jozufozu.flywheel.mixin;
import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
@ -7,7 +7,7 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import com.jozufozu.flywheel.light.LightUpdater; import com.jozufozu.flywheel.lib.light.LightUpdater;
import net.minecraft.client.multiplayer.ClientChunkCache; import net.minecraft.client.multiplayer.ClientChunkCache;
import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.multiplayer.ClientLevel;
@ -22,14 +22,12 @@ public abstract class LightUpdateMixin extends ChunkSource {
ClientLevel level; ClientLevel level;
/** /**
* JUSTIFICATION: This method is called after a lighting tick once per subchunk where a * JUSTIFICATION: This method is called after lighting updates are finished processing
* lighting change occurred that tick. On the client, Minecraft uses this method to inform * per section where a lighting change occurred that frame. On the client, Minecraft
* the rendering system that it needs to redraw a chunk. It does all that work asynchronously, * uses this method to inform the rendering system that it needs to redraw a chunk.
* and we should too.
*/ */
@Inject(at = @At("HEAD"), method = "onLightUpdate") @Inject(method = "onLightUpdate(Lnet/minecraft/world/level/LightLayer;Lnet/minecraft/core/SectionPos;)V", at = @At("HEAD"))
private void flywheel$onLightUpdate(LightLayer type, SectionPos pos, CallbackInfo ci) { private void flywheel$onLightUpdate(LightLayer type, SectionPos pos, CallbackInfo ci) {
LightUpdater.get(level) LightUpdater.get(level).onLightUpdate(type, pos);
.onLightUpdate(type, pos.asLong());
} }
} }

View file

@ -1,32 +0,0 @@
package com.jozufozu.flywheel.mixin.light;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import com.jozufozu.flywheel.lib.util.RenderWork;
import com.jozufozu.flywheel.light.LightUpdater;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.multiplayer.ClientPacketListener;
import net.minecraft.network.protocol.game.ClientboundLightUpdatePacket;
@Mixin(ClientPacketListener.class)
public class NetworkLightUpdateMixin {
@Inject(at = @At("TAIL"), method = "handleLightUpdatePacket")
private void flywheel$onLightPacket(ClientboundLightUpdatePacket packet, CallbackInfo ci) {
RenderWork.enqueue(() -> {
ClientLevel level = Minecraft.getInstance().level;
if (level == null) return;
int chunkX = packet.getX();
int chunkZ = packet.getZ();
LightUpdater.get(level)
.onLightPacket(chunkX, chunkZ);
});
}
}

View file

@ -1,6 +0,0 @@
package com.jozufozu.flywheel.util.box;
@FunctionalInterface
public interface CoordinateConsumer {
void consume(int x, int y, int z);
}

View file

@ -16,12 +16,12 @@ import com.jozufozu.flywheel.api.instancer.InstancerManager;
import com.jozufozu.flywheel.backend.instancing.AbstractInstance; import com.jozufozu.flywheel.backend.instancing.AbstractInstance;
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
import com.jozufozu.flywheel.backend.instancing.effect.Effect; import com.jozufozu.flywheel.backend.instancing.effect.Effect;
import com.jozufozu.flywheel.lib.box.ImmutableBox;
import com.jozufozu.flywheel.lib.box.MutableBox;
import com.jozufozu.flywheel.lib.model.Models; import com.jozufozu.flywheel.lib.model.Models;
import com.jozufozu.flywheel.lib.struct.StructTypes; import com.jozufozu.flywheel.lib.struct.StructTypes;
import com.jozufozu.flywheel.lib.struct.TransformedPart; import com.jozufozu.flywheel.lib.struct.TransformedPart;
import com.jozufozu.flywheel.util.AnimationTickHolder; import com.jozufozu.flywheel.util.AnimationTickHolder;
import com.jozufozu.flywheel.util.box.GridAlignedBB;
import com.jozufozu.flywheel.util.box.ImmutableBox;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
@ -67,7 +67,7 @@ public class ExampleEffect implements Effect {
this.level = level; this.level = level;
this.targetPoint = targetPoint; this.targetPoint = targetPoint;
this.blockPos = new BlockPos(targetPoint.x, targetPoint.y, targetPoint.z); this.blockPos = new BlockPos(targetPoint.x, targetPoint.y, targetPoint.z);
this.volume = GridAlignedBB.from(this.blockPos); this.volume = MutableBox.from(this.blockPos);
this.effects = new ArrayList<>(INSTANCE_COUNT); this.effects = new ArrayList<>(INSTANCE_COUNT);
this.boids = new ArrayList<>(INSTANCE_COUNT); this.boids = new ArrayList<>(INSTANCE_COUNT);
} }

View file

@ -15,6 +15,7 @@
"GlStateManagerMixin", "GlStateManagerMixin",
"LevelRendererAccessor", "LevelRendererAccessor",
"LevelRendererMixin", "LevelRendererMixin",
"LightUpdateMixin",
"PausedPartialTickAccessor", "PausedPartialTickAccessor",
"RenderTypeMixin", "RenderTypeMixin",
"VertexFormatMixin", "VertexFormatMixin",
@ -22,8 +23,6 @@
"instancemanage.InstanceAddMixin", "instancemanage.InstanceAddMixin",
"instancemanage.InstanceRemoveMixin", "instancemanage.InstanceRemoveMixin",
"instancemanage.InstanceUpdateMixin", "instancemanage.InstanceUpdateMixin",
"light.LightUpdateMixin",
"light.NetworkLightUpdateMixin",
"matrix.Matrix3fAccessor", "matrix.Matrix3fAccessor",
"matrix.Matrix4fAccessor", "matrix.Matrix4fAccessor",
"matrix.PoseStackMixin" "matrix.PoseStackMixin"