mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2025-01-23 11:27:54 +01:00
Merge branch 'refs/heads/1.20/dev' into feat/multi-loader-1.20.4
# Conflicts: # gradle.properties
This commit is contained in:
commit
a9c4e5c6f4
38 changed files with 469 additions and 443 deletions
|
@ -31,5 +31,6 @@ gradlePlugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("dev.architectury.loom:dev.architectury.loom.gradle.plugin:1.6-SNAPSHOT")
|
// FIXME: This should not hard-code the Loom version.
|
||||||
|
implementation("dev.architectury.loom:dev.architectury.loom.gradle.plugin:1.6.397")
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
package dev.engine_room.flywheel.api.vertex;
|
package dev.engine_room.flywheel.api.vertex;
|
||||||
|
|
||||||
import org.joml.Vector3f;
|
|
||||||
import org.joml.Vector4f;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A read only view of a vertex buffer.
|
* A read only view of a vertex buffer.
|
||||||
*
|
*
|
||||||
|
@ -40,14 +37,6 @@ public interface VertexList {
|
||||||
|
|
||||||
float normalZ(int index);
|
float normalZ(int index);
|
||||||
|
|
||||||
default Vector4f getPos(int i, Vector4f dest) {
|
|
||||||
return dest.set(x(i), y(i), z(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
default Vector3f getNormal(int i, Vector3f dest) {
|
|
||||||
return dest.set(normalX(i), normalY(i), normalZ(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
default void write(MutableVertexList dst, int srcIndex, int dstIndex) {
|
default void write(MutableVertexList dst, int srcIndex, int dstIndex) {
|
||||||
dst.x(dstIndex, x(srcIndex));
|
dst.x(dstIndex, x(srcIndex));
|
||||||
dst.y(dstIndex, y(srcIndex));
|
dst.y(dstIndex, y(srcIndex));
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package dev.engine_room.flywheel.api.visual;
|
package dev.engine_room.flywheel.api.visual;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import dev.engine_room.flywheel.api.visualization.VisualizationContext;
|
import dev.engine_room.flywheel.api.visualization.VisualizationContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -14,5 +16,5 @@ public interface Effect {
|
||||||
* @param ctx The visualization context.
|
* @param ctx The visualization context.
|
||||||
* @return An arbitrary EffectVisual.
|
* @return An arbitrary EffectVisual.
|
||||||
*/
|
*/
|
||||||
EffectVisual<?> visualize(VisualizationContext ctx);
|
List<EffectVisual<?>> visualize(VisualizationContext ctx, float partialTick);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,16 +13,14 @@ import net.minecraft.core.SectionPos;
|
||||||
*/
|
*/
|
||||||
public interface LitVisual extends Visual {
|
public interface LitVisual extends Visual {
|
||||||
/**
|
/**
|
||||||
* Called when a section this visual is contained in receives a light update.
|
* Set the notifier object.
|
||||||
*
|
*
|
||||||
* <p>Even if multiple sections are updated at the same time, this method will only be called once.</p>
|
* <p>This method is only called once right after the visual
|
||||||
|
* is created and before {@link #collectLightSections}.</p>
|
||||||
*
|
*
|
||||||
* <p>The implementation is free to parallelize calls to this method, as well as execute the plan
|
* @param notifier The notifier.
|
||||||
* returned by {@link DynamicVisual#planFrame} simultaneously. It is safe to query/update light here,
|
|
||||||
* but you must ensure proper synchronization if you want to mutate anything outside this visual or
|
|
||||||
* anything that is also mutated within {@link DynamicVisual#planFrame}.</p>
|
|
||||||
*/
|
*/
|
||||||
void updateLight();
|
void setLightSectionNotifier(Notifier notifier);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Collect the sections that this visual is contained in.
|
* Collect the sections that this visual is contained in.
|
||||||
|
@ -36,14 +34,18 @@ public interface LitVisual extends Visual {
|
||||||
void collectLightSections(LongConsumer consumer);
|
void collectLightSections(LongConsumer consumer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the notifier object.
|
* Called when a section this visual is contained in receives a light update.
|
||||||
*
|
*
|
||||||
* <p>This method is only called once, upon visual creation,
|
* <p>Even if multiple sections are updated at the same time, this method will only be called once.</p>
|
||||||
* after {@link #init} and before {@link #collectLightSections}.</p>
|
|
||||||
*
|
*
|
||||||
* @param notifier The notifier.
|
* <p>The implementation is free to parallelize calls to this method, as well as execute the plan
|
||||||
|
* returned by {@link DynamicVisual#planFrame} simultaneously. It is safe to query/update light here,
|
||||||
|
* but you must ensure proper synchronization if you want to mutate anything outside this visual or
|
||||||
|
* anything that is also mutated within {@link DynamicVisual#planFrame}.</p>
|
||||||
|
*
|
||||||
|
* <p>This method not is invoked automatically after visual creation.</p>
|
||||||
*/
|
*/
|
||||||
void initLightSectionNotifier(Notifier notifier);
|
void updateLight(float partialTick);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A notifier object that can be used to indicate to the impl
|
* A notifier object that can be used to indicate to the impl
|
||||||
|
|
|
@ -8,13 +8,6 @@ package dev.engine_room.flywheel.api.visual;
|
||||||
* @see LitVisual
|
* @see LitVisual
|
||||||
*/
|
*/
|
||||||
public interface Visual {
|
public interface Visual {
|
||||||
/**
|
|
||||||
* Initialize instances here.
|
|
||||||
*
|
|
||||||
* <p>This method will be called exactly once upon visual creation.</p>
|
|
||||||
*/
|
|
||||||
void init(float partialTick);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update instances here.
|
* Update instances here.
|
||||||
*
|
*
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package dev.engine_room.flywheel.api.visualization;
|
package dev.engine_room.flywheel.api.visualization;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import dev.engine_room.flywheel.api.visual.BlockEntityVisual;
|
import dev.engine_room.flywheel.api.visual.BlockEntityVisual;
|
||||||
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer;
|
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
|
@ -16,7 +18,7 @@ public interface BlockEntityVisualizer<T extends BlockEntity> {
|
||||||
* @param blockEntity The block entity to construct a visual for.
|
* @param blockEntity The block entity to construct a visual for.
|
||||||
* @return The visual.
|
* @return The visual.
|
||||||
*/
|
*/
|
||||||
BlockEntityVisual<? super T> createVisual(VisualizationContext ctx, T blockEntity);
|
List<BlockEntityVisual<? super T>> createVisual(VisualizationContext ctx, T blockEntity, float partialTick);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the given block entity should not be rendered with the vanilla {@link BlockEntityRenderer}.
|
* Checks if the given block entity should not be rendered with the vanilla {@link BlockEntityRenderer}.
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package dev.engine_room.flywheel.api.visualization;
|
package dev.engine_room.flywheel.api.visualization;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import dev.engine_room.flywheel.api.visual.EntityVisual;
|
import dev.engine_room.flywheel.api.visual.EntityVisual;
|
||||||
import net.minecraft.client.renderer.entity.EntityRenderer;
|
import net.minecraft.client.renderer.entity.EntityRenderer;
|
||||||
import net.minecraft.world.entity.Entity;
|
import net.minecraft.world.entity.Entity;
|
||||||
|
@ -16,7 +18,7 @@ public interface EntityVisualizer<T extends Entity> {
|
||||||
* @param entity The entity to construct a visual for.
|
* @param entity The entity to construct a visual for.
|
||||||
* @return The visual.
|
* @return The visual.
|
||||||
*/
|
*/
|
||||||
EntityVisual<? super T> createVisual(VisualizationContext ctx, T entity);
|
List<EntityVisual<? super T>> createVisual(VisualizationContext ctx, T entity, float partialTick);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the given entity should not render with the vanilla {@link EntityRenderer}.
|
* Checks if the given entity should not render with the vanilla {@link EntityRenderer}.
|
||||||
|
|
|
@ -8,7 +8,7 @@ import dev.engine_room.flywheel.api.instance.Instance;
|
||||||
import dev.engine_room.flywheel.api.instance.InstanceType;
|
import dev.engine_room.flywheel.api.instance.InstanceType;
|
||||||
import dev.engine_room.flywheel.api.instance.Instancer;
|
import dev.engine_room.flywheel.api.instance.Instancer;
|
||||||
import dev.engine_room.flywheel.backend.engine.embed.Environment;
|
import dev.engine_room.flywheel.backend.engine.embed.Environment;
|
||||||
import dev.engine_room.flywheel.lib.util.AtomicBitset;
|
import dev.engine_room.flywheel.lib.util.AtomicBitSet;
|
||||||
|
|
||||||
public abstract class AbstractInstancer<I extends Instance> implements Instancer<I> {
|
public abstract class AbstractInstancer<I extends Instance> implements Instancer<I> {
|
||||||
public final InstanceType<I> type;
|
public final InstanceType<I> type;
|
||||||
|
@ -19,8 +19,8 @@ public abstract class AbstractInstancer<I extends Instance> implements Instancer
|
||||||
protected final ArrayList<I> instances = new ArrayList<>();
|
protected final ArrayList<I> instances = new ArrayList<>();
|
||||||
protected final ArrayList<InstanceHandleImpl> handles = new ArrayList<>();
|
protected final ArrayList<InstanceHandleImpl> handles = new ArrayList<>();
|
||||||
|
|
||||||
protected final AtomicBitset changed = new AtomicBitset();
|
protected final AtomicBitSet changed = new AtomicBitSet();
|
||||||
protected final AtomicBitset deleted = new AtomicBitset();
|
protected final AtomicBitSet deleted = new AtomicBitSet();
|
||||||
|
|
||||||
protected AbstractInstancer(InstanceType<I> type, Environment environment) {
|
protected AbstractInstancer(InstanceType<I> type, Environment environment) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
|
|
|
@ -3,7 +3,7 @@ package dev.engine_room.flywheel.backend.engine.uniform;
|
||||||
import org.joml.Matrix4f;
|
import org.joml.Matrix4f;
|
||||||
import org.lwjgl.system.MemoryUtil;
|
import org.lwjgl.system.MemoryUtil;
|
||||||
|
|
||||||
import dev.engine_room.flywheel.lib.math.MatrixMath;
|
import dev.engine_room.flywheel.lib.util.ExtraMemoryOps;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.tags.FluidTags;
|
import net.minecraft.tags.FluidTags;
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
|
@ -46,7 +46,7 @@ class UniformWriter {
|
||||||
}
|
}
|
||||||
|
|
||||||
static long writeMat4(long ptr, Matrix4f mat) {
|
static long writeMat4(long ptr, Matrix4f mat) {
|
||||||
MatrixMath.writeUnsafe(ptr, mat);
|
ExtraMemoryOps.putMatrix4f(ptr, mat);
|
||||||
return ptr + 64;
|
return ptr + 64;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,6 @@ package dev.engine_room.flywheel.lib.instance;
|
||||||
|
|
||||||
import dev.engine_room.flywheel.api.instance.InstanceHandle;
|
import dev.engine_room.flywheel.api.instance.InstanceHandle;
|
||||||
import dev.engine_room.flywheel.api.instance.InstanceType;
|
import dev.engine_room.flywheel.api.instance.InstanceType;
|
||||||
import net.minecraft.client.renderer.LightTexture;
|
|
||||||
import net.minecraft.client.renderer.texture.OverlayTexture;
|
import net.minecraft.client.renderer.texture.OverlayTexture;
|
||||||
|
|
||||||
public abstract class ColoredLitInstance extends AbstractInstance implements FlatLit {
|
public abstract class ColoredLitInstance extends AbstractInstance implements FlatLit {
|
||||||
|
@ -11,43 +10,42 @@ public abstract class ColoredLitInstance extends AbstractInstance implements Fla
|
||||||
public byte b = (byte) 0xFF;
|
public byte b = (byte) 0xFF;
|
||||||
public byte a = (byte) 0xFF;
|
public byte a = (byte) 0xFF;
|
||||||
|
|
||||||
public int packedLight;
|
|
||||||
|
|
||||||
public int overlay = OverlayTexture.NO_OVERLAY;
|
public int overlay = OverlayTexture.NO_OVERLAY;
|
||||||
|
public int light = 0;
|
||||||
|
|
||||||
public ColoredLitInstance(InstanceType<? extends ColoredLitInstance> type, InstanceHandle handle) {
|
public ColoredLitInstance(InstanceType<? extends ColoredLitInstance> type, InstanceHandle handle) {
|
||||||
super(type, handle);
|
super(type, handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ColoredLitInstance setColor(int color) {
|
public ColoredLitInstance color(int color) {
|
||||||
return setColor(color, false);
|
return color(color, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ColoredLitInstance setColor(int color, boolean alpha) {
|
public ColoredLitInstance color(int color, boolean alpha) {
|
||||||
byte r = (byte) ((color >> 16) & 0xFF);
|
byte r = (byte) ((color >> 16) & 0xFF);
|
||||||
byte g = (byte) ((color >> 8) & 0xFF);
|
byte g = (byte) ((color >> 8) & 0xFF);
|
||||||
byte b = (byte) (color & 0xFF);
|
byte b = (byte) (color & 0xFF);
|
||||||
|
|
||||||
if (alpha) {
|
if (alpha) {
|
||||||
byte a = (byte) ((color >> 24) & 0xFF);
|
byte a = (byte) ((color >> 24) & 0xFF);
|
||||||
return setColor(r, g, b, a);
|
return color(r, g, b, a);
|
||||||
} else {
|
} else {
|
||||||
return setColor(r, g, b);
|
return color(r, g, b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ColoredLitInstance setColor(int r, int g, int b) {
|
public ColoredLitInstance color(int r, int g, int b) {
|
||||||
return setColor((byte) r, (byte) g, (byte) b);
|
return color((byte) r, (byte) g, (byte) b);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ColoredLitInstance setColor(byte r, byte g, byte b) {
|
public ColoredLitInstance color(byte r, byte g, byte b) {
|
||||||
this.r = r;
|
this.r = r;
|
||||||
this.g = g;
|
this.g = g;
|
||||||
this.b = b;
|
this.b = b;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ColoredLitInstance setColor(byte r, byte g, byte b, byte a) {
|
public ColoredLitInstance color(byte r, byte g, byte b, byte a) {
|
||||||
this.r = r;
|
this.r = r;
|
||||||
this.g = g;
|
this.g = g;
|
||||||
this.b = b;
|
this.b = b;
|
||||||
|
@ -55,19 +53,14 @@ public abstract class ColoredLitInstance extends AbstractInstance implements Fla
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public ColoredLitInstance overlay(int overlay) {
|
||||||
public ColoredLitInstance light(int blockLight, int skyLight) {
|
|
||||||
return light(LightTexture.pack(blockLight, skyLight));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ColoredLitInstance light(int packedLight) {
|
|
||||||
this.packedLight = packedLight;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ColoredLitInstance setOverlay(int overlay) {
|
|
||||||
this.overlay = overlay;
|
this.overlay = overlay;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ColoredLitInstance light(int light) {
|
||||||
|
this.light = light;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,26 +1,64 @@
|
||||||
package dev.engine_room.flywheel.lib.instance;
|
package dev.engine_room.flywheel.lib.instance;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import dev.engine_room.flywheel.api.instance.Instance;
|
import dev.engine_room.flywheel.api.instance.Instance;
|
||||||
import dev.engine_room.flywheel.lib.visual.AbstractVisual;
|
import dev.engine_room.flywheel.lib.visual.AbstractBlockEntityVisual;
|
||||||
|
import dev.engine_room.flywheel.lib.visual.AbstractEntityVisual;
|
||||||
import net.minecraft.client.renderer.LightTexture;
|
import net.minecraft.client.renderer.LightTexture;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An interface that implementors of {@link Instance} should also implement
|
* An interface that implementors of {@link Instance} should also implement if they wish to make use of
|
||||||
* if they wish to make use of the relighting utilities in {@link AbstractVisual}.
|
* {@link #relight} and the relighting utilities in {@link AbstractBlockEntityVisual} and {@link AbstractEntityVisual}.
|
||||||
*/
|
*/
|
||||||
public interface FlatLit extends Instance {
|
public interface FlatLit extends Instance {
|
||||||
/**
|
|
||||||
* Set the block and sky light values for this instance.
|
|
||||||
* @param blockLight Block light value
|
|
||||||
* @param skyLight Sky light value
|
|
||||||
* @return {@code this} for chaining
|
|
||||||
*/
|
|
||||||
FlatLit light(int blockLight, int skyLight);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the packed light value for this instance.
|
* Set the packed light value for this instance.
|
||||||
* @param packedLight Packed block and sky light per {@link LightTexture#pack(int, int)}
|
* @param packedLight Packed block and sky light per {@link LightTexture#pack(int, int)}
|
||||||
* @return {@code this} for chaining
|
* @return {@code this} for chaining
|
||||||
*/
|
*/
|
||||||
FlatLit light(int packedLight);
|
FlatLit light(int packedLight);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the block and sky light values for this instance.
|
||||||
|
* @param blockLight Block light value
|
||||||
|
* @param skyLight Sky light value
|
||||||
|
* @return {@code this} for chaining
|
||||||
|
*/
|
||||||
|
default FlatLit light(int blockLight, int skyLight) {
|
||||||
|
return light(LightTexture.pack(blockLight, skyLight));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void relight(int packedLight, @Nullable FlatLit... instances) {
|
||||||
|
for (FlatLit instance : instances) {
|
||||||
|
if (instance != null) {
|
||||||
|
instance.light(packedLight)
|
||||||
|
.handle()
|
||||||
|
.setChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void relight(int packedLight, Iterator<@Nullable FlatLit> instances) {
|
||||||
|
while (instances.hasNext()) {
|
||||||
|
FlatLit instance = instances.next();
|
||||||
|
|
||||||
|
if (instance != null) {
|
||||||
|
instance.light(packedLight)
|
||||||
|
.handle()
|
||||||
|
.setChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void relight(int packedLight, Iterable<@Nullable FlatLit> instances) {
|
||||||
|
relight(packedLight, instances.iterator());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void relight(int packedLight, Stream<@Nullable FlatLit> instances) {
|
||||||
|
relight(packedLight, instances.iterator());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ import dev.engine_room.flywheel.api.instance.InstanceType;
|
||||||
import dev.engine_room.flywheel.api.layout.FloatRepr;
|
import dev.engine_room.flywheel.api.layout.FloatRepr;
|
||||||
import dev.engine_room.flywheel.api.layout.IntegerRepr;
|
import dev.engine_room.flywheel.api.layout.IntegerRepr;
|
||||||
import dev.engine_room.flywheel.api.layout.LayoutBuilder;
|
import dev.engine_room.flywheel.api.layout.LayoutBuilder;
|
||||||
import dev.engine_room.flywheel.lib.math.MatrixMath;
|
import dev.engine_room.flywheel.lib.util.ExtraMemoryOps;
|
||||||
|
|
||||||
public final class InstanceTypes {
|
public final class InstanceTypes {
|
||||||
public static final InstanceType<TransformedInstance> TRANSFORMED = SimpleInstanceType.builder(TransformedInstance::new)
|
public static final InstanceType<TransformedInstance> TRANSFORMED = SimpleInstanceType.builder(TransformedInstance::new)
|
||||||
|
@ -24,12 +24,10 @@ public final class InstanceTypes {
|
||||||
MemoryUtil.memPutByte(ptr + 1, instance.g);
|
MemoryUtil.memPutByte(ptr + 1, instance.g);
|
||||||
MemoryUtil.memPutByte(ptr + 2, instance.b);
|
MemoryUtil.memPutByte(ptr + 2, instance.b);
|
||||||
MemoryUtil.memPutByte(ptr + 3, instance.a);
|
MemoryUtil.memPutByte(ptr + 3, instance.a);
|
||||||
MemoryUtil.memPutShort(ptr + 4, (short) (instance.overlay & 0xFFFF));
|
ExtraMemoryOps.put2x16(ptr + 4, instance.overlay);
|
||||||
MemoryUtil.memPutShort(ptr + 6, (short) (instance.overlay >> 16 & 0xFFFF));
|
ExtraMemoryOps.put2x16(ptr + 8, instance.light);
|
||||||
MemoryUtil.memPutShort(ptr + 8, (short) (instance.packedLight & 0xFFFF));
|
ExtraMemoryOps.putMatrix4f(ptr + 12, instance.model);
|
||||||
MemoryUtil.memPutShort(ptr + 10, (short) (instance.packedLight >> 16 & 0xFFFF));
|
ExtraMemoryOps.putMatrix3f(ptr + 76, instance.normal);
|
||||||
MatrixMath.writeUnsafe(ptr + 12, instance.model);
|
|
||||||
MatrixMath.writeUnsafe(ptr + 76, instance.normal);
|
|
||||||
})
|
})
|
||||||
.vertexShader(Flywheel.rl("instance/transformed.vert"))
|
.vertexShader(Flywheel.rl("instance/transformed.vert"))
|
||||||
.cullShader(Flywheel.rl("instance/cull/transformed.glsl"))
|
.cullShader(Flywheel.rl("instance/cull/transformed.glsl"))
|
||||||
|
@ -49,20 +47,15 @@ public final class InstanceTypes {
|
||||||
MemoryUtil.memPutByte(ptr + 1, instance.g);
|
MemoryUtil.memPutByte(ptr + 1, instance.g);
|
||||||
MemoryUtil.memPutByte(ptr + 2, instance.b);
|
MemoryUtil.memPutByte(ptr + 2, instance.b);
|
||||||
MemoryUtil.memPutByte(ptr + 3, instance.a);
|
MemoryUtil.memPutByte(ptr + 3, instance.a);
|
||||||
MemoryUtil.memPutShort(ptr + 4, (short) (instance.overlay & 0xFFFF));
|
ExtraMemoryOps.put2x16(ptr + 4, instance.overlay);
|
||||||
MemoryUtil.memPutShort(ptr + 6, (short) (instance.overlay >> 16 & 0xFFFF));
|
ExtraMemoryOps.put2x16(ptr + 8, instance.light);
|
||||||
MemoryUtil.memPutShort(ptr + 8, (short) (instance.packedLight & 0xFFFF));
|
|
||||||
MemoryUtil.memPutShort(ptr + 10, (short) (instance.packedLight >> 16 & 0xFFFF));
|
|
||||||
MemoryUtil.memPutFloat(ptr + 12, instance.posX);
|
MemoryUtil.memPutFloat(ptr + 12, instance.posX);
|
||||||
MemoryUtil.memPutFloat(ptr + 16, instance.posY);
|
MemoryUtil.memPutFloat(ptr + 16, instance.posY);
|
||||||
MemoryUtil.memPutFloat(ptr + 20, instance.posZ);
|
MemoryUtil.memPutFloat(ptr + 20, instance.posZ);
|
||||||
MemoryUtil.memPutFloat(ptr + 24, instance.pivotX);
|
MemoryUtil.memPutFloat(ptr + 24, instance.pivotX);
|
||||||
MemoryUtil.memPutFloat(ptr + 28, instance.pivotY);
|
MemoryUtil.memPutFloat(ptr + 28, instance.pivotY);
|
||||||
MemoryUtil.memPutFloat(ptr + 32, instance.pivotZ);
|
MemoryUtil.memPutFloat(ptr + 32, instance.pivotZ);
|
||||||
MemoryUtil.memPutFloat(ptr + 36, instance.rotation.x);
|
ExtraMemoryOps.putQuaternionf(ptr + 36, instance.rotation);
|
||||||
MemoryUtil.memPutFloat(ptr + 40, instance.rotation.y);
|
|
||||||
MemoryUtil.memPutFloat(ptr + 44, instance.rotation.z);
|
|
||||||
MemoryUtil.memPutFloat(ptr + 48, instance.rotation.w);
|
|
||||||
})
|
})
|
||||||
.vertexShader(Flywheel.rl("instance/oriented.vert"))
|
.vertexShader(Flywheel.rl("instance/oriented.vert"))
|
||||||
.cullShader(Flywheel.rl("instance/cull/oriented.glsl"))
|
.cullShader(Flywheel.rl("instance/cull/oriented.glsl"))
|
||||||
|
|
|
@ -7,25 +7,10 @@ import org.joml.Matrix3f;
|
||||||
import org.joml.Matrix4f;
|
import org.joml.Matrix4f;
|
||||||
import org.lwjgl.system.MemoryUtil;
|
import org.lwjgl.system.MemoryUtil;
|
||||||
|
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
|
||||||
|
|
||||||
public final class MatrixMath {
|
public final class MatrixMath {
|
||||||
private MatrixMath() {
|
private MatrixMath() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PoseStack copyPoseStack(PoseStack stack) {
|
|
||||||
PoseStack copy = new PoseStack();
|
|
||||||
copy.last()
|
|
||||||
.pose()
|
|
||||||
.set(stack.last()
|
|
||||||
.pose());
|
|
||||||
copy.last()
|
|
||||||
.normal()
|
|
||||||
.set(stack.last()
|
|
||||||
.normal());
|
|
||||||
return copy;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static float transformPositionX(Matrix4f matrix, float x, float y, float z) {
|
public static float transformPositionX(Matrix4f matrix, float x, float y, float z) {
|
||||||
return fma(matrix.m00(), x, fma(matrix.m10(), y, fma(matrix.m20(), z, matrix.m30())));
|
return fma(matrix.m00(), x, fma(matrix.m10(), y, fma(matrix.m20(), z, matrix.m30())));
|
||||||
}
|
}
|
||||||
|
@ -50,37 +35,6 @@ public final class MatrixMath {
|
||||||
return fma(matrix.m02(), x, fma(matrix.m12(), y, matrix.m22() * z));
|
return fma(matrix.m02(), x, fma(matrix.m12(), y, matrix.m22() * z));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void writeUnsafe(long ptr, Matrix4f matrix) {
|
|
||||||
MemoryUtil.memPutFloat(ptr, matrix.m00());
|
|
||||||
MemoryUtil.memPutFloat(ptr + 4, matrix.m01());
|
|
||||||
MemoryUtil.memPutFloat(ptr + 8, matrix.m02());
|
|
||||||
MemoryUtil.memPutFloat(ptr + 12, matrix.m03());
|
|
||||||
MemoryUtil.memPutFloat(ptr + 16, matrix.m10());
|
|
||||||
MemoryUtil.memPutFloat(ptr + 20, matrix.m11());
|
|
||||||
MemoryUtil.memPutFloat(ptr + 24, matrix.m12());
|
|
||||||
MemoryUtil.memPutFloat(ptr + 28, matrix.m13());
|
|
||||||
MemoryUtil.memPutFloat(ptr + 32, matrix.m20());
|
|
||||||
MemoryUtil.memPutFloat(ptr + 36, matrix.m21());
|
|
||||||
MemoryUtil.memPutFloat(ptr + 40, matrix.m22());
|
|
||||||
MemoryUtil.memPutFloat(ptr + 44, matrix.m23());
|
|
||||||
MemoryUtil.memPutFloat(ptr + 48, matrix.m30());
|
|
||||||
MemoryUtil.memPutFloat(ptr + 52, matrix.m31());
|
|
||||||
MemoryUtil.memPutFloat(ptr + 56, matrix.m32());
|
|
||||||
MemoryUtil.memPutFloat(ptr + 60, matrix.m33());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void writeUnsafe(long ptr, Matrix3f matrix) {
|
|
||||||
MemoryUtil.memPutFloat(ptr, matrix.m00());
|
|
||||||
MemoryUtil.memPutFloat(ptr + 4, matrix.m01());
|
|
||||||
MemoryUtil.memPutFloat(ptr + 8, matrix.m02());
|
|
||||||
MemoryUtil.memPutFloat(ptr + 12, matrix.m10());
|
|
||||||
MemoryUtil.memPutFloat(ptr + 16, matrix.m11());
|
|
||||||
MemoryUtil.memPutFloat(ptr + 20, matrix.m12());
|
|
||||||
MemoryUtil.memPutFloat(ptr + 24, matrix.m20());
|
|
||||||
MemoryUtil.memPutFloat(ptr + 28, matrix.m21());
|
|
||||||
MemoryUtil.memPutFloat(ptr + 32, matrix.m22());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extracts the greatest scale factor across all axes from the given matrix.
|
* Extracts the greatest scale factor across all axes from the given matrix.
|
||||||
*
|
*
|
||||||
|
|
|
@ -9,7 +9,7 @@ import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
// https://github.com/Netflix/hollow/blob/master/hollow/src/main/java/com/netflix/hollow/core/memory/ThreadSafeBitSet.java
|
// https://github.com/Netflix/hollow/blob/master/hollow/src/main/java/com/netflix/hollow/core/memory/ThreadSafeBitSet.java
|
||||||
// Refactored to remove unused methods, deduplicate some code segments, and add extra functionality with #forEachSetSpan
|
// Refactored to remove unused methods, deduplicate some code segments, and add extra functionality with #forEachSetSpan
|
||||||
public class AtomicBitset {
|
public class AtomicBitSet {
|
||||||
// 1024 bits, 128 bytes, 16 longs per segment
|
// 1024 bits, 128 bytes, 16 longs per segment
|
||||||
public static final int DEFAULT_LOG2_SEGMENT_SIZE_IN_BITS = 10;
|
public static final int DEFAULT_LOG2_SEGMENT_SIZE_IN_BITS = 10;
|
||||||
|
|
||||||
|
@ -18,17 +18,17 @@ public class AtomicBitset {
|
||||||
private final int numLongsPerSegment;
|
private final int numLongsPerSegment;
|
||||||
private final int log2SegmentSize;
|
private final int log2SegmentSize;
|
||||||
private final int segmentMask;
|
private final int segmentMask;
|
||||||
private final AtomicReference<AtomicBitsetSegments> segments;
|
private final AtomicReference<AtomicBitSetSegments> segments;
|
||||||
|
|
||||||
public AtomicBitset() {
|
public AtomicBitSet() {
|
||||||
this(DEFAULT_LOG2_SEGMENT_SIZE_IN_BITS);
|
this(DEFAULT_LOG2_SEGMENT_SIZE_IN_BITS);
|
||||||
}
|
}
|
||||||
|
|
||||||
public AtomicBitset(int log2SegmentSizeInBits) {
|
public AtomicBitSet(int log2SegmentSizeInBits) {
|
||||||
this(log2SegmentSizeInBits, 0);
|
this(log2SegmentSizeInBits, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public AtomicBitset(int log2SegmentSizeInBits, int numBitsToPreallocate) {
|
public AtomicBitSet(int log2SegmentSizeInBits, int numBitsToPreallocate) {
|
||||||
if (log2SegmentSizeInBits < 6) {
|
if (log2SegmentSizeInBits < 6) {
|
||||||
throw new IllegalArgumentException("Cannot specify fewer than 64 bits in each segment!");
|
throw new IllegalArgumentException("Cannot specify fewer than 64 bits in each segment!");
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ public class AtomicBitset {
|
||||||
long numBitsPerSegment = numLongsPerSegment * 64L;
|
long numBitsPerSegment = numLongsPerSegment * 64L;
|
||||||
int numSegmentsToPreallocate = numBitsToPreallocate == 0 ? 1 : (int) (((numBitsToPreallocate - 1) / numBitsPerSegment) + 1);
|
int numSegmentsToPreallocate = numBitsToPreallocate == 0 ? 1 : (int) (((numBitsToPreallocate - 1) / numBitsPerSegment) + 1);
|
||||||
|
|
||||||
segments = new AtomicReference<>(new AtomicBitsetSegments(numSegmentsToPreallocate, numLongsPerSegment));
|
segments = new AtomicReference<>(new AtomicBitSetSegments(numSegmentsToPreallocate, numLongsPerSegment));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void set(int position) {
|
public void set(int position) {
|
||||||
|
@ -251,7 +251,7 @@ public class AtomicBitset {
|
||||||
}
|
}
|
||||||
|
|
||||||
public long maxSetBit() {
|
public long maxSetBit() {
|
||||||
AtomicBitsetSegments segments = this.segments.get();
|
AtomicBitSetSegments segments = this.segments.get();
|
||||||
|
|
||||||
int segmentIdx = segments.numSegments() - 1;
|
int segmentIdx = segments.numSegments() - 1;
|
||||||
|
|
||||||
|
@ -273,7 +273,7 @@ public class AtomicBitset {
|
||||||
throw new IndexOutOfBoundsException("fromIndex < 0: " + fromIndex);
|
throw new IndexOutOfBoundsException("fromIndex < 0: " + fromIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
AtomicBitsetSegments segments = this.segments.get();
|
AtomicBitSetSegments segments = this.segments.get();
|
||||||
|
|
||||||
int segmentPosition = segmentIndexForPosition(fromIndex);
|
int segmentPosition = segmentIndexForPosition(fromIndex);
|
||||||
if (segmentPosition >= segments.numSegments()) {
|
if (segmentPosition >= segments.numSegments()) {
|
||||||
|
@ -309,7 +309,7 @@ public class AtomicBitset {
|
||||||
|
|
||||||
int segmentPosition = segmentIndexForPosition(fromIndex);
|
int segmentPosition = segmentIndexForPosition(fromIndex);
|
||||||
|
|
||||||
AtomicBitsetSegments segments = this.segments.get();
|
AtomicBitSetSegments segments = this.segments.get();
|
||||||
|
|
||||||
if (segmentPosition >= segments.numSegments()) {
|
if (segmentPosition >= segments.numSegments()) {
|
||||||
return fromIndex;
|
return fromIndex;
|
||||||
|
@ -352,7 +352,7 @@ public class AtomicBitset {
|
||||||
* @param consumer The consumer to accept each span.
|
* @param consumer The consumer to accept each span.
|
||||||
*/
|
*/
|
||||||
public void forEachSetSpan(BitSpanConsumer consumer) {
|
public void forEachSetSpan(BitSpanConsumer consumer) {
|
||||||
AtomicBitsetSegments segments = this.segments.get();
|
AtomicBitSetSegments segments = this.segments.get();
|
||||||
|
|
||||||
if (segments.cardinality() == 0) {
|
if (segments.cardinality() == 0) {
|
||||||
return;
|
return;
|
||||||
|
@ -415,7 +415,7 @@ public class AtomicBitset {
|
||||||
* Clear all bits to 0.
|
* Clear all bits to 0.
|
||||||
*/
|
*/
|
||||||
public void clear() {
|
public void clear() {
|
||||||
AtomicBitsetSegments segments = this.segments.get();
|
AtomicBitSetSegments segments = this.segments.get();
|
||||||
|
|
||||||
for (int i = 0; i < segments.numSegments(); i++) {
|
for (int i = 0; i < segments.numSegments(); i++) {
|
||||||
AtomicLongArray segment = segments.getSegment(i);
|
AtomicLongArray segment = segments.getSegment(i);
|
||||||
|
@ -478,13 +478,13 @@ public class AtomicBitset {
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private AtomicBitsetSegments expandToFit(int segmentIndex) {
|
private AtomicBitSet.AtomicBitSetSegments expandToFit(int segmentIndex) {
|
||||||
AtomicBitsetSegments visibleSegments = segments.get();
|
AtomicBitSetSegments visibleSegments = segments.get();
|
||||||
|
|
||||||
while (visibleSegments.numSegments() <= segmentIndex) {
|
while (visibleSegments.numSegments() <= segmentIndex) {
|
||||||
// Thread safety: newVisibleSegments contains all of the segments from the currently visible segments, plus extra.
|
// Thread safety: newVisibleSegments contains all of the segments from the currently visible segments, plus extra.
|
||||||
// all of the segments in the currently visible segments are canonical and will not change.
|
// all of the segments in the currently visible segments are canonical and will not change.
|
||||||
AtomicBitsetSegments newVisibleSegments = new AtomicBitsetSegments(visibleSegments, segmentIndex + 1, numLongsPerSegment);
|
AtomicBitSetSegments newVisibleSegments = new AtomicBitSetSegments(visibleSegments, segmentIndex + 1, numLongsPerSegment);
|
||||||
|
|
||||||
// because we are using a compareAndSet, if this thread "wins the race" and successfully sets this variable, then the segments
|
// because we are using a compareAndSet, if this thread "wins the race" and successfully sets this variable, then the segments
|
||||||
// which are newly defined in newVisibleSegments become canonical.
|
// which are newly defined in newVisibleSegments become canonical.
|
||||||
|
@ -500,10 +500,10 @@ public class AtomicBitset {
|
||||||
return visibleSegments;
|
return visibleSegments;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class AtomicBitsetSegments {
|
private static class AtomicBitSetSegments {
|
||||||
private final AtomicLongArray[] segments;
|
private final AtomicLongArray[] segments;
|
||||||
|
|
||||||
private AtomicBitsetSegments(int numSegments, int segmentLength) {
|
private AtomicBitSetSegments(int numSegments, int segmentLength) {
|
||||||
AtomicLongArray[] segments = new AtomicLongArray[numSegments];
|
AtomicLongArray[] segments = new AtomicLongArray[numSegments];
|
||||||
|
|
||||||
for (int i = 0; i < numSegments; i++) {
|
for (int i = 0; i < numSegments; i++) {
|
||||||
|
@ -515,7 +515,7 @@ public class AtomicBitset {
|
||||||
this.segments = segments;
|
this.segments = segments;
|
||||||
}
|
}
|
||||||
|
|
||||||
private AtomicBitsetSegments(AtomicBitsetSegments copyFrom, int numSegments, int segmentLength) {
|
private AtomicBitSetSegments(AtomicBitSetSegments copyFrom, int numSegments, int segmentLength) {
|
||||||
AtomicLongArray[] segments = new AtomicLongArray[numSegments];
|
AtomicLongArray[] segments = new AtomicLongArray[numSegments];
|
||||||
|
|
||||||
for (int i = 0; i < numSegments; i++) {
|
for (int i = 0; i < numSegments; i++) {
|
||||||
|
@ -550,7 +550,7 @@ public class AtomicBitset {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
if (!(obj instanceof AtomicBitset other)) {
|
if (!(obj instanceof AtomicBitSet other)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -558,8 +558,8 @@ public class AtomicBitset {
|
||||||
throw new IllegalArgumentException("Segment sizes must be the same");
|
throw new IllegalArgumentException("Segment sizes must be the same");
|
||||||
}
|
}
|
||||||
|
|
||||||
AtomicBitsetSegments thisSegments = this.segments.get();
|
AtomicBitSetSegments thisSegments = this.segments.get();
|
||||||
AtomicBitsetSegments otherSegments = other.segments.get();
|
AtomicBitSetSegments otherSegments = other.segments.get();
|
||||||
|
|
||||||
for (int i = 0; i < thisSegments.numSegments(); i++) {
|
for (int i = 0; i < thisSegments.numSegments(); i++) {
|
||||||
AtomicLongArray thisArray = thisSegments.getSegment(i);
|
AtomicLongArray thisArray = thisSegments.getSegment(i);
|
|
@ -0,0 +1,82 @@
|
||||||
|
package dev.engine_room.flywheel.lib.util;
|
||||||
|
|
||||||
|
import org.joml.Matrix3fc;
|
||||||
|
import org.joml.Matrix4fc;
|
||||||
|
import org.joml.Quaternionfc;
|
||||||
|
import org.joml.Vector2fc;
|
||||||
|
import org.joml.Vector3fc;
|
||||||
|
import org.joml.Vector4fc;
|
||||||
|
import org.lwjgl.system.MemoryUtil;
|
||||||
|
|
||||||
|
public final class ExtraMemoryOps {
|
||||||
|
private ExtraMemoryOps() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void put4x8(long ptr, int value) {
|
||||||
|
MemoryUtil.memPutByte(ptr, (byte) (value & 0xFF));
|
||||||
|
MemoryUtil.memPutByte(ptr + 1, (byte) (value >>> 8 & 0xFF));
|
||||||
|
MemoryUtil.memPutByte(ptr + 2, (byte) (value >>> 16 & 0xFF));
|
||||||
|
MemoryUtil.memPutByte(ptr + 3, (byte) (value >>> 24 & 0xFF));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void put2x16(long ptr, int value) {
|
||||||
|
MemoryUtil.memPutShort(ptr, (short) (value & 0xFFFF));
|
||||||
|
MemoryUtil.memPutShort(ptr + 2, (short) (value >>> 16 & 0xFFFF));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void putVector2f(long ptr, Vector2fc vector) {
|
||||||
|
MemoryUtil.memPutFloat(ptr, vector.x());
|
||||||
|
MemoryUtil.memPutFloat(ptr + 4, vector.y());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void putVector3f(long ptr, Vector3fc vector) {
|
||||||
|
MemoryUtil.memPutFloat(ptr, vector.x());
|
||||||
|
MemoryUtil.memPutFloat(ptr + 4, vector.y());
|
||||||
|
MemoryUtil.memPutFloat(ptr + 8, vector.z());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void putVector4f(long ptr, Vector4fc vector) {
|
||||||
|
MemoryUtil.memPutFloat(ptr, vector.x());
|
||||||
|
MemoryUtil.memPutFloat(ptr + 4, vector.y());
|
||||||
|
MemoryUtil.memPutFloat(ptr + 8, vector.z());
|
||||||
|
MemoryUtil.memPutFloat(ptr + 12, vector.w());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void putQuaternionf(long ptr, Quaternionfc quaternion) {
|
||||||
|
MemoryUtil.memPutFloat(ptr, quaternion.x());
|
||||||
|
MemoryUtil.memPutFloat(ptr + 4, quaternion.y());
|
||||||
|
MemoryUtil.memPutFloat(ptr + 8, quaternion.z());
|
||||||
|
MemoryUtil.memPutFloat(ptr + 12, quaternion.w());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void putMatrix3f(long ptr, Matrix3fc matrix) {
|
||||||
|
MemoryUtil.memPutFloat(ptr, matrix.m00());
|
||||||
|
MemoryUtil.memPutFloat(ptr + 4, matrix.m01());
|
||||||
|
MemoryUtil.memPutFloat(ptr + 8, matrix.m02());
|
||||||
|
MemoryUtil.memPutFloat(ptr + 12, matrix.m10());
|
||||||
|
MemoryUtil.memPutFloat(ptr + 16, matrix.m11());
|
||||||
|
MemoryUtil.memPutFloat(ptr + 20, matrix.m12());
|
||||||
|
MemoryUtil.memPutFloat(ptr + 24, matrix.m20());
|
||||||
|
MemoryUtil.memPutFloat(ptr + 28, matrix.m21());
|
||||||
|
MemoryUtil.memPutFloat(ptr + 32, matrix.m22());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void putMatrix4f(long ptr, Matrix4fc matrix) {
|
||||||
|
MemoryUtil.memPutFloat(ptr, matrix.m00());
|
||||||
|
MemoryUtil.memPutFloat(ptr + 4, matrix.m01());
|
||||||
|
MemoryUtil.memPutFloat(ptr + 8, matrix.m02());
|
||||||
|
MemoryUtil.memPutFloat(ptr + 12, matrix.m03());
|
||||||
|
MemoryUtil.memPutFloat(ptr + 16, matrix.m10());
|
||||||
|
MemoryUtil.memPutFloat(ptr + 20, matrix.m11());
|
||||||
|
MemoryUtil.memPutFloat(ptr + 24, matrix.m12());
|
||||||
|
MemoryUtil.memPutFloat(ptr + 28, matrix.m13());
|
||||||
|
MemoryUtil.memPutFloat(ptr + 32, matrix.m20());
|
||||||
|
MemoryUtil.memPutFloat(ptr + 36, matrix.m21());
|
||||||
|
MemoryUtil.memPutFloat(ptr + 40, matrix.m22());
|
||||||
|
MemoryUtil.memPutFloat(ptr + 44, matrix.m23());
|
||||||
|
MemoryUtil.memPutFloat(ptr + 48, matrix.m30());
|
||||||
|
MemoryUtil.memPutFloat(ptr + 52, matrix.m31());
|
||||||
|
MemoryUtil.memPutFloat(ptr + 56, matrix.m32());
|
||||||
|
MemoryUtil.memPutFloat(ptr + 60, matrix.m33());
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,7 +11,9 @@ import dev.engine_room.flywheel.api.visual.LitVisual;
|
||||||
import dev.engine_room.flywheel.api.visual.TickableVisual;
|
import dev.engine_room.flywheel.api.visual.TickableVisual;
|
||||||
import dev.engine_room.flywheel.api.visualization.VisualManager;
|
import dev.engine_room.flywheel.api.visualization.VisualManager;
|
||||||
import dev.engine_room.flywheel.api.visualization.VisualizationContext;
|
import dev.engine_room.flywheel.api.visualization.VisualizationContext;
|
||||||
|
import dev.engine_room.flywheel.lib.instance.FlatLit;
|
||||||
import dev.engine_room.flywheel.lib.math.MoreMath;
|
import dev.engine_room.flywheel.lib.math.MoreMath;
|
||||||
|
import net.minecraft.client.renderer.LevelRenderer;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.SectionPos;
|
import net.minecraft.core.SectionPos;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
|
@ -40,8 +42,8 @@ public abstract class AbstractBlockEntityVisual<T extends BlockEntity> extends A
|
||||||
@Nullable
|
@Nullable
|
||||||
protected LitVisual.Notifier notifier;
|
protected LitVisual.Notifier notifier;
|
||||||
|
|
||||||
public AbstractBlockEntityVisual(VisualizationContext ctx, T blockEntity) {
|
public AbstractBlockEntityVisual(VisualizationContext ctx, T blockEntity, float partialTick) {
|
||||||
super(ctx, blockEntity.getLevel());
|
super(ctx, blockEntity.getLevel(), partialTick);
|
||||||
this.blockEntity = blockEntity;
|
this.blockEntity = blockEntity;
|
||||||
this.pos = blockEntity.getBlockPos();
|
this.pos = blockEntity.getBlockPos();
|
||||||
this.blockState = blockEntity.getBlockState();
|
this.blockState = blockEntity.getBlockState();
|
||||||
|
@ -49,8 +51,8 @@ public abstract class AbstractBlockEntityVisual<T extends BlockEntity> extends A
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(float partialTick) {
|
public void setLightSectionNotifier(Notifier notifier) {
|
||||||
updateLight();
|
this.notifier = notifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -58,11 +60,6 @@ public abstract class AbstractBlockEntityVisual<T extends BlockEntity> extends A
|
||||||
consumer.accept(SectionPos.asLong(pos));
|
consumer.accept(SectionPos.asLong(pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void initLightSectionNotifier(Notifier notifier) {
|
|
||||||
this.notifier = notifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* In order to accommodate for floating point precision errors at high coordinates,
|
* In order to accommodate for floating point precision errors at high coordinates,
|
||||||
* {@link VisualManager}s are allowed to arbitrarily adjust the origin, and
|
* {@link VisualManager}s are allowed to arbitrarily adjust the origin, and
|
||||||
|
@ -100,4 +97,12 @@ public abstract class AbstractBlockEntityVisual<T extends BlockEntity> extends A
|
||||||
return !context.limiter()
|
return !context.limiter()
|
||||||
.shouldUpdate(pos.distToCenterSqr(context.camera().getPosition()));
|
.shouldUpdate(pos.distToCenterSqr(context.camera().getPosition()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void relight(BlockPos pos, @Nullable FlatLit... instances) {
|
||||||
|
FlatLit.relight(LevelRenderer.getLightColor(level, pos), instances);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void relight(@Nullable FlatLit... instances) {
|
||||||
|
relight(pos, instances);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,8 +8,12 @@ import dev.engine_room.flywheel.api.visual.EntityVisual;
|
||||||
import dev.engine_room.flywheel.api.visual.TickableVisual;
|
import dev.engine_room.flywheel.api.visual.TickableVisual;
|
||||||
import dev.engine_room.flywheel.api.visualization.VisualizationContext;
|
import dev.engine_room.flywheel.api.visualization.VisualizationContext;
|
||||||
import dev.engine_room.flywheel.api.visualization.VisualizationManager;
|
import dev.engine_room.flywheel.api.visualization.VisualizationManager;
|
||||||
|
import dev.engine_room.flywheel.lib.instance.FlatLit;
|
||||||
|
import net.minecraft.client.renderer.LightTexture;
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.util.Mth;
|
import net.minecraft.util.Mth;
|
||||||
import net.minecraft.world.entity.Entity;
|
import net.minecraft.world.entity.Entity;
|
||||||
|
import net.minecraft.world.level.LightLayer;
|
||||||
import net.minecraft.world.phys.Vec3;
|
import net.minecraft.world.phys.Vec3;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -31,16 +35,12 @@ public abstract class AbstractEntityVisual<T extends Entity> extends AbstractVis
|
||||||
protected final T entity;
|
protected final T entity;
|
||||||
protected final EntityVisibilityTester visibilityTester;
|
protected final EntityVisibilityTester visibilityTester;
|
||||||
|
|
||||||
public AbstractEntityVisual(VisualizationContext ctx, T entity) {
|
public AbstractEntityVisual(VisualizationContext ctx, T entity, float partialTick) {
|
||||||
super(ctx, entity.level());
|
super(ctx, entity.level(), partialTick);
|
||||||
this.entity = entity;
|
this.entity = entity;
|
||||||
visibilityTester = new EntityVisibilityTester(entity, ctx.renderOrigin(), 1.5f);
|
visibilityTester = new EntityVisibilityTester(entity, ctx.renderOrigin(), 1.5f);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void init(float partialTick) {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate the distance squared between this visual and the given <em>level</em> position.
|
* Calculate the distance squared between this visual and the given <em>level</em> position.
|
||||||
*
|
*
|
||||||
|
@ -84,4 +84,12 @@ public abstract class AbstractEntityVisual<T extends Entity> extends AbstractVis
|
||||||
public boolean isVisible(FrustumIntersection frustum) {
|
public boolean isVisible(FrustumIntersection frustum) {
|
||||||
return entity.noCulling || visibilityTester.check(frustum);
|
return entity.noCulling || visibilityTester.check(frustum);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void relight(float partialTick, FlatLit... instances) {
|
||||||
|
BlockPos pos = BlockPos.containing(entity.getLightProbePosition(partialTick));
|
||||||
|
int blockLight = entity.isOnFire() ? 15 : level.getBrightness(LightLayer.BLOCK, pos);
|
||||||
|
int skyLight = level.getBrightness(LightLayer.SKY, pos);
|
||||||
|
int light = LightTexture.pack(blockLight, skyLight);
|
||||||
|
FlatLit.relight(light, instances);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,10 @@
|
||||||
package dev.engine_room.flywheel.lib.visual;
|
package dev.engine_room.flywheel.lib.visual;
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import dev.engine_room.flywheel.api.instance.InstancerProvider;
|
import dev.engine_room.flywheel.api.instance.InstancerProvider;
|
||||||
import dev.engine_room.flywheel.api.visual.Visual;
|
import dev.engine_room.flywheel.api.visual.Visual;
|
||||||
import dev.engine_room.flywheel.api.visualization.VisualizationContext;
|
import dev.engine_room.flywheel.api.visualization.VisualizationContext;
|
||||||
import dev.engine_room.flywheel.lib.instance.FlatLit;
|
|
||||||
import net.minecraft.core.BlockPos;
|
|
||||||
import net.minecraft.core.Vec3i;
|
import net.minecraft.core.Vec3i;
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
import net.minecraft.world.level.LightLayer;
|
|
||||||
|
|
||||||
public abstract class AbstractVisual implements Visual {
|
public abstract class AbstractVisual implements Visual {
|
||||||
/**
|
/**
|
||||||
|
@ -27,7 +19,7 @@ public abstract class AbstractVisual implements Visual {
|
||||||
|
|
||||||
protected boolean deleted = false;
|
protected boolean deleted = false;
|
||||||
|
|
||||||
public AbstractVisual(VisualizationContext ctx, Level level) {
|
public AbstractVisual(VisualizationContext ctx, Level level, float partialTick) {
|
||||||
this.visualizationContext = ctx;
|
this.visualizationContext = ctx;
|
||||||
this.instancerProvider = ctx.instancerProvider();
|
this.instancerProvider = ctx.instancerProvider();
|
||||||
this.renderOrigin = ctx.renderOrigin();
|
this.renderOrigin = ctx.renderOrigin();
|
||||||
|
@ -49,46 +41,4 @@ public abstract class AbstractVisual implements Visual {
|
||||||
_delete();
|
_delete();
|
||||||
deleted = true;
|
deleted = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void relight(BlockPos pos, @Nullable FlatLit... instances) {
|
|
||||||
relight(level.getBrightness(LightLayer.BLOCK, pos), level.getBrightness(LightLayer.SKY, pos), instances);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void relight(int block, int sky, @Nullable FlatLit... instances) {
|
|
||||||
for (FlatLit instance : instances) {
|
|
||||||
if (instance == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
instance.light(block, sky)
|
|
||||||
.handle()
|
|
||||||
.setChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void relight(BlockPos pos, Stream<? extends @Nullable FlatLit> instances) {
|
|
||||||
relight(level.getBrightness(LightLayer.BLOCK, pos), level.getBrightness(LightLayer.SKY, pos), instances);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void relight(int block, int sky, Stream<? extends @Nullable FlatLit> instances) {
|
|
||||||
instances.filter(Objects::nonNull)
|
|
||||||
.forEach(instance -> instance.light(block, sky)
|
|
||||||
.handle()
|
|
||||||
.setChanged());
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void relight(BlockPos pos, Iterable<? extends @Nullable FlatLit> instances) {
|
|
||||||
relight(level.getBrightness(LightLayer.BLOCK, pos), level.getBrightness(LightLayer.SKY, pos), instances);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void relight(int block, int sky, Iterable<? extends @Nullable FlatLit> instances) {
|
|
||||||
for (FlatLit instance : instances) {
|
|
||||||
if (instance == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
instance.light(block, sky)
|
|
||||||
.handle()
|
|
||||||
.setChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package dev.engine_room.flywheel.lib.visual;
|
package dev.engine_room.flywheel.lib.visual;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
@ -23,8 +24,8 @@ public class SimpleBlockEntityVisualizer<T extends BlockEntity> implements Block
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BlockEntityVisual<? super T> createVisual(VisualizationContext ctx, T blockEntity) {
|
public List<BlockEntityVisual<? super T>> createVisual(VisualizationContext ctx, T blockEntity, float partialTick) {
|
||||||
return visualFactory.create(ctx, blockEntity);
|
return List.of(visualFactory.create(ctx, blockEntity, partialTick));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -45,7 +46,7 @@ public class SimpleBlockEntityVisualizer<T extends BlockEntity> implements Block
|
||||||
|
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface Factory<T extends BlockEntity> {
|
public interface Factory<T extends BlockEntity> {
|
||||||
BlockEntityVisual<? super T> create(VisualizationContext ctx, T blockEntity);
|
BlockEntityVisual<? super T> create(VisualizationContext ctx, T blockEntity, float partialTick);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -9,8 +9,8 @@ import net.minecraft.world.entity.Entity;
|
||||||
public class SimpleEntityVisual<T extends Entity> extends AbstractEntityVisual<T> implements SimpleDynamicVisual {
|
public class SimpleEntityVisual<T extends Entity> extends AbstractEntityVisual<T> implements SimpleDynamicVisual {
|
||||||
protected final List<EntityComponent> components = new ArrayList<>();
|
protected final List<EntityComponent> components = new ArrayList<>();
|
||||||
|
|
||||||
public SimpleEntityVisual(VisualizationContext ctx, T entity) {
|
public SimpleEntityVisual(VisualizationContext ctx, T entity, float partialTick) {
|
||||||
super(ctx, entity);
|
super(ctx, entity, partialTick);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addComponent(EntityComponent component) {
|
public void addComponent(EntityComponent component) {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package dev.engine_room.flywheel.lib.visual;
|
package dev.engine_room.flywheel.lib.visual;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
@ -23,8 +24,8 @@ public class SimpleEntityVisualizer<T extends Entity> implements EntityVisualize
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EntityVisual<? super T> createVisual(VisualizationContext ctx, T entity) {
|
public List<EntityVisual<? super T>> createVisual(VisualizationContext ctx, T entity, float partialTick) {
|
||||||
return visualFactory.create(ctx, entity);
|
return List.of(visualFactory.create(ctx, entity, partialTick));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -45,7 +46,7 @@ public class SimpleEntityVisualizer<T extends Entity> implements EntityVisualize
|
||||||
|
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface Factory<T extends Entity> {
|
public interface Factory<T extends Entity> {
|
||||||
EntityVisual<? super T> create(VisualizationContext ctx, T entity);
|
EntityVisual<? super T> create(VisualizationContext ctx, T entity, float partialTick);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -109,7 +109,7 @@ public class HitboxComponent implements EntityComponent {
|
||||||
.loadIdentity()
|
.loadIdentity()
|
||||||
.translate(entityX - bbWidthHalf, entityY + entity.getEyeHeight() - 0.01, entityZ - bbWidthHalf)
|
.translate(entityX - bbWidthHalf, entityY + entity.getEyeHeight() - 0.01, entityZ - bbWidthHalf)
|
||||||
.scale(bbWidth, 0.02f, bbWidth)
|
.scale(bbWidth, 0.02f, bbWidth)
|
||||||
.setColor(255, 0, 0)
|
.color(255, 0, 0)
|
||||||
.setChanged();
|
.setChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,7 +119,7 @@ public class HitboxComponent implements EntityComponent {
|
||||||
.loadIdentity()
|
.loadIdentity()
|
||||||
.translate(entityX, entityY + entity.getEyeHeight(), entityZ)
|
.translate(entityX, entityY + entity.getEyeHeight(), entityZ)
|
||||||
.rotate(new Quaternionf().rotateTo(0, 1, 0, (float) viewVector.x, (float) viewVector.y, (float) viewVector.z))
|
.rotate(new Quaternionf().rotateTo(0, 1, 0, (float) viewVector.x, (float) viewVector.y, (float) viewVector.z))
|
||||||
.setColor(0, 0, 255)
|
.color(0, 0, 255)
|
||||||
.setChanged();
|
.setChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ import dev.engine_room.flywheel.api.event.RenderStage;
|
||||||
import dev.engine_room.flywheel.api.instance.Instance;
|
import dev.engine_room.flywheel.api.instance.Instance;
|
||||||
import dev.engine_room.flywheel.api.task.Plan;
|
import dev.engine_room.flywheel.api.task.Plan;
|
||||||
import dev.engine_room.flywheel.api.task.TaskExecutor;
|
import dev.engine_room.flywheel.api.task.TaskExecutor;
|
||||||
|
import dev.engine_room.flywheel.api.visual.BlockEntityVisual;
|
||||||
import dev.engine_room.flywheel.api.visual.DynamicVisual;
|
import dev.engine_room.flywheel.api.visual.DynamicVisual;
|
||||||
import dev.engine_room.flywheel.api.visual.Effect;
|
import dev.engine_room.flywheel.api.visual.Effect;
|
||||||
import dev.engine_room.flywheel.api.visual.TickableVisual;
|
import dev.engine_room.flywheel.api.visual.TickableVisual;
|
||||||
|
@ -261,21 +262,23 @@ public class VisualizationManagerImpl implements VisualizationManager {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var visual = blockEntities.getStorage()
|
var visualList = blockEntities.getStorage()
|
||||||
.visualAtPos(entry.getLongKey());
|
.visualAtPos(entry.getLongKey());
|
||||||
|
|
||||||
if (visual == null) {
|
if (visualList == null || visualList.isEmpty()) {
|
||||||
// The block doesn't have a visual, this is probably the common case.
|
// The block doesn't have a visual, this is probably the common case.
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Instance> instances = new ArrayList<>();
|
List<Instance> instances = new ArrayList<>();
|
||||||
|
|
||||||
visual.collectCrumblingInstances(instance -> {
|
for (BlockEntityVisual<?> visual : visualList) {
|
||||||
if (instance != null) {
|
visual.collectCrumblingInstances(instance -> {
|
||||||
instances.add(instance);
|
if (instance != null) {
|
||||||
}
|
instances.add(instance);
|
||||||
});
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (instances.isEmpty()) {
|
if (instances.isEmpty()) {
|
||||||
// The visual doesn't want to render anything crumbling.
|
// The visual doesn't want to render anything crumbling.
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
package dev.engine_room.flywheel.impl.visualization.manager;
|
package dev.engine_room.flywheel.impl.visualization.manager;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import dev.engine_room.flywheel.api.visual.BlockEntityVisual;
|
import dev.engine_room.flywheel.api.visual.BlockEntityVisual;
|
||||||
import dev.engine_room.flywheel.api.visual.Visual;
|
|
||||||
import dev.engine_room.flywheel.api.visualization.VisualizationContext;
|
import dev.engine_room.flywheel.api.visualization.VisualizationContext;
|
||||||
import dev.engine_room.flywheel.impl.visualization.storage.Storage;
|
import dev.engine_room.flywheel.impl.visualization.storage.Storage;
|
||||||
import dev.engine_room.flywheel.lib.visual.VisualizationHelper;
|
import dev.engine_room.flywheel.lib.visual.VisualizationHelper;
|
||||||
|
@ -17,14 +17,14 @@ import net.minecraft.world.level.Level;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
|
|
||||||
public class BlockEntityStorage extends Storage<BlockEntity> {
|
public class BlockEntityStorage extends Storage<BlockEntity> {
|
||||||
private final Long2ObjectMap<BlockEntityVisual<?>> posLookup = new Long2ObjectOpenHashMap<>();
|
private final Long2ObjectMap<List<? extends BlockEntityVisual<?>>> posLookup = new Long2ObjectOpenHashMap<>();
|
||||||
|
|
||||||
public BlockEntityStorage(Supplier<VisualizationContext> visualizationContextSupplier) {
|
public BlockEntityStorage(Supplier<VisualizationContext> visualizationContextSupplier) {
|
||||||
super(visualizationContextSupplier);
|
super(visualizationContextSupplier);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public BlockEntityVisual<?> visualAtPos(long pos) {
|
public List<? extends BlockEntityVisual<?>> visualAtPos(long pos) {
|
||||||
return posLookup.get(pos);
|
return posLookup.get(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,19 +53,18 @@ public class BlockEntityStorage extends Storage<BlockEntity> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Nullable
|
protected List<? extends BlockEntityVisual<?>> createRaw(BlockEntity obj, float partialTick) {
|
||||||
protected Visual createRaw(BlockEntity obj) {
|
|
||||||
var visualizer = VisualizationHelper.getVisualizer(obj);
|
var visualizer = VisualizationHelper.getVisualizer(obj);
|
||||||
if (visualizer == null) {
|
if (visualizer == null) {
|
||||||
return null;
|
return List.of();
|
||||||
}
|
}
|
||||||
|
|
||||||
var visual = visualizer.createVisual(visualizationContextSupplier.get(), obj);
|
var visualList = visualizer.createVisual(visualizationContextSupplier.get(), obj, partialTick);
|
||||||
|
|
||||||
BlockPos blockPos = obj.getBlockPos();
|
BlockPos blockPos = obj.getBlockPos();
|
||||||
posLookup.put(blockPos.asLong(), visual);
|
posLookup.put(blockPos.asLong(), visualList);
|
||||||
|
|
||||||
return visual;
|
return visualList;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package dev.engine_room.flywheel.impl.visualization.manager;
|
package dev.engine_room.flywheel.impl.visualization.manager;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import dev.engine_room.flywheel.api.visual.Effect;
|
import dev.engine_room.flywheel.api.visual.Effect;
|
||||||
|
@ -13,8 +14,8 @@ public class EffectStorage extends Storage<Effect> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected EffectVisual<?> createRaw(Effect obj) {
|
protected List<? extends EffectVisual<?>> createRaw(Effect obj, float partialTick) {
|
||||||
return obj.visualize(visualizationContextSupplier.get());
|
return obj.visualize(visualizationContextSupplier.get(), partialTick);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
package dev.engine_room.flywheel.impl.visualization.manager;
|
package dev.engine_room.flywheel.impl.visualization.manager;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
import dev.engine_room.flywheel.api.visual.EntityVisual;
|
||||||
|
|
||||||
import dev.engine_room.flywheel.api.visual.Visual;
|
|
||||||
import dev.engine_room.flywheel.api.visualization.VisualizationContext;
|
import dev.engine_room.flywheel.api.visualization.VisualizationContext;
|
||||||
import dev.engine_room.flywheel.impl.visualization.storage.Storage;
|
import dev.engine_room.flywheel.impl.visualization.storage.Storage;
|
||||||
import dev.engine_room.flywheel.lib.visual.VisualizationHelper;
|
import dev.engine_room.flywheel.lib.visual.VisualizationHelper;
|
||||||
|
@ -17,14 +16,13 @@ public class EntityStorage extends Storage<Entity> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Nullable
|
protected List<? extends EntityVisual<?>> createRaw(Entity obj, float partialTick) {
|
||||||
protected Visual createRaw(Entity obj) {
|
|
||||||
var visualizer = VisualizationHelper.getVisualizer(obj);
|
var visualizer = VisualizationHelper.getVisualizer(obj);
|
||||||
if (visualizer == null) {
|
if (visualizer == null) {
|
||||||
return null;
|
return List.of();
|
||||||
}
|
}
|
||||||
|
|
||||||
return visualizer.createVisual(visualizationContextSupplier.get(), obj);
|
return visualizer.createVisual(visualizationContextSupplier.get(), obj, partialTick);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -26,7 +26,7 @@ public class VisualManagerImpl<T, S extends Storage<T>> implements VisualManager
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getVisualCount() {
|
public int getVisualCount() {
|
||||||
return getStorage().getAllVisuals().size();
|
return getStorage().visualCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -51,11 +51,12 @@ public class LitVisualStorage {
|
||||||
});
|
});
|
||||||
|
|
||||||
long updateId = getNextUpdateId();
|
long updateId = getNextUpdateId();
|
||||||
|
Updater.Context updaterContext = new Updater.Context(updateId, context.partialTick());
|
||||||
|
|
||||||
for (long section : sectionsUpdatedThisFrame) {
|
for (long section : sectionsUpdatedThisFrame) {
|
||||||
var visuals = sections2Visuals.get(section);
|
var visuals = sections2Visuals.get(section);
|
||||||
if (visuals != null && !visuals.isEmpty()) {
|
if (visuals != null && !visuals.isEmpty()) {
|
||||||
taskExecutor.execute(() -> Distribute.tasks(taskExecutor, updateId, sync, visuals, Updater::updateLight));
|
taskExecutor.execute(() -> Distribute.tasks(taskExecutor, updaterContext, sync, visuals, Updater::updateLight));
|
||||||
} else {
|
} else {
|
||||||
sync.decrementAndEventuallyRun();
|
sync.decrementAndEventuallyRun();
|
||||||
}
|
}
|
||||||
|
@ -89,8 +90,8 @@ public class LitVisualStorage {
|
||||||
return visuals2Sections.isEmpty();
|
return visuals2Sections.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addAndInitNotifier(LitVisual visual) {
|
public void setNotifierAndAdd(LitVisual visual) {
|
||||||
visual.initLightSectionNotifier(new LitVisualNotifierImpl(visual));
|
visual.setLightSectionNotifier(new LitVisualNotifierImpl(visual));
|
||||||
add(visual);
|
add(visual);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,15 +169,15 @@ public class LitVisualStorage {
|
||||||
|
|
||||||
// Breaking this into 2 separate cases allows us to avoid the overhead of atomics in the common case.
|
// Breaking this into 2 separate cases allows us to avoid the overhead of atomics in the common case.
|
||||||
sealed interface Updater {
|
sealed interface Updater {
|
||||||
void updateLight(long updateId);
|
void updateLight(Context ctx);
|
||||||
|
|
||||||
LitVisual visual();
|
LitVisual visual();
|
||||||
|
|
||||||
// The visual is only in one section. In this case, we can just update the visual directly.
|
// The visual is only in one section. In this case, we can just update the visual directly.
|
||||||
record Simple(LitVisual visual) implements Updater {
|
record Simple(LitVisual visual) implements Updater {
|
||||||
@Override
|
@Override
|
||||||
public void updateLight(long updateId) {
|
public void updateLight(Context ctx) {
|
||||||
visual.updateLight();
|
visual.updateLight(ctx.partialTick);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,14 +185,17 @@ public class LitVisualStorage {
|
||||||
// even when multiple sections it was contained in are updated at the same time.
|
// even when multiple sections it was contained in are updated at the same time.
|
||||||
record Synced(LitVisual visual, AtomicLong updateId) implements Updater {
|
record Synced(LitVisual visual, AtomicLong updateId) implements Updater {
|
||||||
@Override
|
@Override
|
||||||
public void updateLight(long updateId) {
|
public void updateLight(Context ctx) {
|
||||||
// Different update ID means we won, so we can update the visual.
|
// Different update ID means we won, so we can update the visual.
|
||||||
// Same update ID means another thread beat us to the update.
|
// Same update ID means another thread beat us to the update.
|
||||||
if (this.updateId.getAndSet(updateId) != updateId) {
|
if (this.updateId.getAndSet(ctx.updateId) != ctx.updateId) {
|
||||||
visual.updateLight();
|
visual.updateLight(ctx.partialTick);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
record Context(long updateId, float partialTick) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final class LitVisualNotifierImpl implements LitVisual.Notifier {
|
private final class LitVisualNotifierImpl implements LitVisual.Notifier {
|
||||||
|
|
|
@ -1,13 +1,10 @@
|
||||||
package dev.engine_room.flywheel.impl.visualization.storage;
|
package dev.engine_room.flywheel.impl.visualization.storage;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import dev.engine_room.flywheel.api.task.Plan;
|
import dev.engine_room.flywheel.api.task.Plan;
|
||||||
import dev.engine_room.flywheel.api.visual.DynamicVisual;
|
import dev.engine_room.flywheel.api.visual.DynamicVisual;
|
||||||
import dev.engine_room.flywheel.api.visual.LitVisual;
|
import dev.engine_room.flywheel.api.visual.LitVisual;
|
||||||
|
@ -29,31 +26,137 @@ public abstract class Storage<T> {
|
||||||
protected final List<SimpleTickableVisual> simpleTickableVisuals = new ArrayList<>();
|
protected final List<SimpleTickableVisual> simpleTickableVisuals = new ArrayList<>();
|
||||||
protected final LitVisualStorage litVisuals = new LitVisualStorage();
|
protected final LitVisualStorage litVisuals = new LitVisualStorage();
|
||||||
|
|
||||||
private final Map<T, Visual> visuals = new Reference2ObjectOpenHashMap<>();
|
private final Map<T, List<? extends Visual>> visuals = new Reference2ObjectOpenHashMap<>();
|
||||||
|
|
||||||
public Storage(Supplier<VisualizationContext> visualizationContextSupplier) {
|
public Storage(Supplier<VisualizationContext> visualizationContextSupplier) {
|
||||||
this.visualizationContextSupplier = visualizationContextSupplier;
|
this.visualizationContextSupplier = visualizationContextSupplier;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<Visual> getAllVisuals() {
|
public int visualCount() {
|
||||||
return visuals.values();
|
int out = 0;
|
||||||
|
for (var visualList : visuals.values()) {
|
||||||
|
out += visualList.size();
|
||||||
|
}
|
||||||
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void add(T obj, float partialTick) {
|
public void add(T obj, float partialTick) {
|
||||||
Visual visual = visuals.get(obj);
|
var visualList = this.visuals.get(obj);
|
||||||
|
|
||||||
if (visual == null) {
|
if (visualList == null) {
|
||||||
create(obj, partialTick);
|
create(obj, partialTick);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void remove(T obj) {
|
public void remove(T obj) {
|
||||||
Visual visual = visuals.remove(obj);
|
var visualList = this.visuals.remove(obj);
|
||||||
|
|
||||||
if (visual == null) {
|
if (visualList == null || visualList.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (Visual visual : visualList) {
|
||||||
|
remove(visual);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void update(T obj, float partialTick) {
|
||||||
|
var visualList = visuals.get(obj);
|
||||||
|
|
||||||
|
if (visualList == null || visualList.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Visual visual : visualList) {
|
||||||
|
visual.update(partialTick);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void recreateAll(float partialTick) {
|
||||||
|
tickableVisuals.clear();
|
||||||
|
dynamicVisuals.clear();
|
||||||
|
simpleTickableVisuals.clear();
|
||||||
|
simpleDynamicVisuals.clear();
|
||||||
|
litVisuals.clear();
|
||||||
|
visuals.replaceAll((obj, visuals) -> {
|
||||||
|
visuals.forEach(Visual::delete);
|
||||||
|
|
||||||
|
var out = createRaw(obj, partialTick);
|
||||||
|
|
||||||
|
if (out.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Visual visual : out) {
|
||||||
|
setup(visual);
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void invalidate() {
|
||||||
|
tickableVisuals.clear();
|
||||||
|
dynamicVisuals.clear();
|
||||||
|
litVisuals.clear();
|
||||||
|
for (var visualList : visuals.values()) {
|
||||||
|
for (Visual visual : visualList) {
|
||||||
|
visual.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
visuals.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void create(T obj, float partialTick) {
|
||||||
|
var visuals = createRaw(obj, partialTick);
|
||||||
|
|
||||||
|
if (visuals.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.visuals.put(obj, visuals);
|
||||||
|
|
||||||
|
for (Visual visual : visuals) {
|
||||||
|
setup(visual);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract List<? extends Visual> createRaw(T obj, float partialTick);
|
||||||
|
|
||||||
|
public Plan<DynamicVisual.Context> framePlan() {
|
||||||
|
return NestedPlan.of(dynamicVisuals, litVisuals.plan(), ForEachPlan.of(() -> simpleDynamicVisuals, SimpleDynamicVisual::beginFrame));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Plan<TickableVisual.Context> tickPlan() {
|
||||||
|
return NestedPlan.of(tickableVisuals, ForEachPlan.of(() -> simpleTickableVisuals, SimpleTickableVisual::tick));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void enqueueLightUpdateSection(long section) {
|
||||||
|
litVisuals.enqueueLightUpdateSection(section);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setup(Visual visual) {
|
||||||
|
if (visual instanceof TickableVisual tickable) {
|
||||||
|
if (visual instanceof SimpleTickableVisual simpleTickable) {
|
||||||
|
simpleTickableVisuals.add(simpleTickable);
|
||||||
|
} else {
|
||||||
|
tickableVisuals.add(tickable, tickable.planTick());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (visual instanceof DynamicVisual dynamic) {
|
||||||
|
if (visual instanceof SimpleDynamicVisual simpleDynamic) {
|
||||||
|
simpleDynamicVisuals.add(simpleDynamic);
|
||||||
|
} else {
|
||||||
|
dynamicVisuals.add(dynamic, dynamic.planFrame());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (visual instanceof LitVisual lit) {
|
||||||
|
litVisuals.setNotifierAndAdd(lit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void remove(Visual visual) {
|
||||||
if (visual instanceof TickableVisual tickable) {
|
if (visual instanceof TickableVisual tickable) {
|
||||||
if (visual instanceof SimpleTickableVisual simpleTickable) {
|
if (visual instanceof SimpleTickableVisual simpleTickable) {
|
||||||
simpleTickableVisuals.remove(simpleTickable);
|
simpleTickableVisuals.remove(simpleTickable);
|
||||||
|
@ -74,92 +177,6 @@ public abstract class Storage<T> {
|
||||||
visual.delete();
|
visual.delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update(T obj, float partialTick) {
|
|
||||||
Visual visual = visuals.get(obj);
|
|
||||||
|
|
||||||
if (visual == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
visual.update(partialTick);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void recreateAll(float partialTick) {
|
|
||||||
tickableVisuals.clear();
|
|
||||||
dynamicVisuals.clear();
|
|
||||||
simpleTickableVisuals.clear();
|
|
||||||
simpleDynamicVisuals.clear();
|
|
||||||
litVisuals.clear();
|
|
||||||
visuals.replaceAll((obj, visual) -> {
|
|
||||||
visual.delete();
|
|
||||||
|
|
||||||
Visual out = createRaw(obj);
|
|
||||||
|
|
||||||
if (out != null) {
|
|
||||||
setup(out, partialTick);
|
|
||||||
}
|
|
||||||
|
|
||||||
return out;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void invalidate() {
|
|
||||||
tickableVisuals.clear();
|
|
||||||
dynamicVisuals.clear();
|
|
||||||
litVisuals.clear();
|
|
||||||
visuals.values()
|
|
||||||
.forEach(Visual::delete);
|
|
||||||
visuals.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void create(T obj, float partialTick) {
|
|
||||||
Visual visual = createRaw(obj);
|
|
||||||
|
|
||||||
if (visual != null) {
|
|
||||||
setup(visual, partialTick);
|
|
||||||
visuals.put(obj, visual);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
protected abstract Visual createRaw(T obj);
|
|
||||||
|
|
||||||
public Plan<DynamicVisual.Context> framePlan() {
|
|
||||||
return NestedPlan.of(dynamicVisuals, litVisuals.plan(), ForEachPlan.of(() -> simpleDynamicVisuals, SimpleDynamicVisual::beginFrame));
|
|
||||||
}
|
|
||||||
|
|
||||||
public Plan<TickableVisual.Context> tickPlan() {
|
|
||||||
return NestedPlan.of(tickableVisuals, ForEachPlan.of(() -> simpleTickableVisuals, SimpleTickableVisual::tick));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void enqueueLightUpdateSection(long section) {
|
|
||||||
litVisuals.enqueueLightUpdateSection(section);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setup(Visual visual, float partialTick) {
|
|
||||||
visual.init(partialTick);
|
|
||||||
|
|
||||||
if (visual instanceof TickableVisual tickable) {
|
|
||||||
if (visual instanceof SimpleTickableVisual simpleTickable) {
|
|
||||||
simpleTickableVisuals.add(simpleTickable);
|
|
||||||
} else {
|
|
||||||
tickableVisuals.add(tickable, tickable.planTick());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (visual instanceof DynamicVisual dynamic) {
|
|
||||||
if (visual instanceof SimpleDynamicVisual simpleDynamic) {
|
|
||||||
simpleDynamicVisuals.add(simpleDynamic);
|
|
||||||
} else {
|
|
||||||
dynamicVisuals.add(dynamic, dynamic.planFrame());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (visual instanceof LitVisual lit) {
|
|
||||||
litVisuals.addAndInitNotifier(lit);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is the given object currently capable of being added?
|
* Is the given object currently capable of being added?
|
||||||
*
|
*
|
||||||
|
|
|
@ -26,24 +26,19 @@ public class BellVisual extends AbstractBlockEntityVisual<BellBlockEntity> imple
|
||||||
return new SingleMeshModel(ModelPartConverter.convert(ModelLayers.BELL, BellRenderer.BELL_RESOURCE_LOCATION.sprite(), "bell_body"), Materials.BELL);
|
return new SingleMeshModel(ModelPartConverter.convert(ModelLayers.BELL, BellRenderer.BELL_RESOURCE_LOCATION.sprite(), "bell_body"), Materials.BELL);
|
||||||
});
|
});
|
||||||
|
|
||||||
private OrientedInstance bell;
|
private final OrientedInstance bell;
|
||||||
|
|
||||||
private boolean wasShaking = false;
|
private boolean wasShaking = false;
|
||||||
|
|
||||||
public BellVisual(VisualizationContext ctx, BellBlockEntity blockEntity) {
|
public BellVisual(VisualizationContext ctx, BellBlockEntity blockEntity, float partialTick) {
|
||||||
super(ctx, blockEntity);
|
super(ctx, blockEntity, partialTick);
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void init(float partialTick) {
|
|
||||||
bell = createBellInstance().setPivot(0.5f, 0.75f, 0.5f)
|
bell = createBellInstance().setPivot(0.5f, 0.75f, 0.5f)
|
||||||
.setPosition(getVisualPosition());
|
.setPosition(getVisualPosition());
|
||||||
|
|
||||||
bell.setChanged();
|
bell.setChanged();
|
||||||
|
|
||||||
updateRotation(partialTick);
|
updateRotation(partialTick);
|
||||||
|
updateLight(partialTick);
|
||||||
super.init(partialTick);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private OrientedInstance createBellInstance() {
|
private OrientedInstance createBellInstance() {
|
||||||
|
@ -81,8 +76,8 @@ public class BellVisual extends AbstractBlockEntityVisual<BellBlockEntity> imple
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateLight() {
|
public void updateLight(float partialTick) {
|
||||||
relight(pos, bell);
|
relight(bell);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -51,22 +51,20 @@ public class ChestVisual<T extends BlockEntity & LidBlockEntity> extends Abstrac
|
||||||
return new SingleMeshModel(ModelPartConverter.convert(LAYER_LOCATIONS.get(key.first()), key.second().sprite(), "lock"), Materials.CHEST);
|
return new SingleMeshModel(ModelPartConverter.convert(LAYER_LOCATIONS.get(key.first()), key.second().sprite(), "lock"), Materials.CHEST);
|
||||||
});
|
});
|
||||||
|
|
||||||
private OrientedInstance bottom;
|
private final OrientedInstance bottom;
|
||||||
private TransformedInstance lid;
|
private final TransformedInstance lid;
|
||||||
private TransformedInstance lock;
|
private final TransformedInstance lock;
|
||||||
|
|
||||||
|
private final ChestType chestType;
|
||||||
|
private final Float2FloatFunction lidProgress;
|
||||||
|
|
||||||
private ChestType chestType;
|
|
||||||
private final Quaternionf baseRotation = new Quaternionf();
|
private final Quaternionf baseRotation = new Quaternionf();
|
||||||
private Float2FloatFunction lidProgress;
|
|
||||||
|
|
||||||
private float lastProgress = Float.NaN;
|
private float lastProgress = Float.NaN;
|
||||||
|
|
||||||
public ChestVisual(VisualizationContext ctx, T blockEntity) {
|
public ChestVisual(VisualizationContext ctx, T blockEntity, float partialTick) {
|
||||||
super(ctx, blockEntity);
|
super(ctx, blockEntity, partialTick);
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void init(float partialTick) {
|
|
||||||
chestType = blockState.hasProperty(ChestBlock.TYPE) ? blockState.getValue(ChestBlock.TYPE) : ChestType.SINGLE;
|
chestType = blockState.hasProperty(ChestBlock.TYPE) ? blockState.getValue(ChestBlock.TYPE) : ChestType.SINGLE;
|
||||||
Material texture = Sheets.chooseMaterial(blockEntity, chestType, isChristmas());
|
Material texture = Sheets.chooseMaterial(blockEntity, chestType, isChristmas());
|
||||||
|
|
||||||
|
@ -90,8 +88,7 @@ public class ChestVisual<T extends BlockEntity & LidBlockEntity> extends Abstrac
|
||||||
bottom.setChanged();
|
bottom.setChanged();
|
||||||
|
|
||||||
applyLidTransform(lidProgress.get(partialTick));
|
applyLidTransform(lidProgress.get(partialTick));
|
||||||
|
updateLight(partialTick);
|
||||||
super.init(partialTick);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private OrientedInstance createBottomInstance(Material texture) {
|
private OrientedInstance createBottomInstance(Material texture) {
|
||||||
|
@ -153,8 +150,8 @@ public class ChestVisual<T extends BlockEntity & LidBlockEntity> extends Abstrac
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateLight() {
|
public void updateLight(float partialTick) {
|
||||||
relight(pos, bottom, lid, lock);
|
relight(bottom, lid, lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -38,19 +38,32 @@ public class MinecartVisual<T extends AbstractMinecart> extends SimpleEntityVisu
|
||||||
public static final ModelHolder SPAWNER_BODY_MODEL = createBodyModelHolder(ModelLayers.SPAWNER_MINECART);
|
public static final ModelHolder SPAWNER_BODY_MODEL = createBodyModelHolder(ModelLayers.SPAWNER_MINECART);
|
||||||
public static final ModelHolder TNT_BODY_MODEL = createBodyModelHolder(ModelLayers.TNT_MINECART);
|
public static final ModelHolder TNT_BODY_MODEL = createBodyModelHolder(ModelLayers.TNT_MINECART);
|
||||||
|
|
||||||
private final ModelHolder bodyModel;
|
private final TransformedInstance body;
|
||||||
|
|
||||||
private TransformedInstance body;
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private TransformedInstance contents;
|
private TransformedInstance contents;
|
||||||
private BlockState blockState;
|
|
||||||
private boolean active;
|
private final ModelHolder bodyModel;
|
||||||
|
|
||||||
private final PoseStack stack = new PoseStack();
|
private final PoseStack stack = new PoseStack();
|
||||||
|
|
||||||
public MinecartVisual(VisualizationContext ctx, T entity, ModelHolder bodyModel) {
|
private BlockState blockState;
|
||||||
super(ctx, entity);
|
private boolean active;
|
||||||
|
|
||||||
|
public MinecartVisual(VisualizationContext ctx, T entity, float partialTick, ModelHolder bodyModel) {
|
||||||
|
super(ctx, entity, partialTick);
|
||||||
|
|
||||||
this.bodyModel = bodyModel;
|
this.bodyModel = bodyModel;
|
||||||
|
|
||||||
|
body = createBodyInstance();
|
||||||
|
blockState = entity.getDisplayBlockState();
|
||||||
|
contents = createContentsInstance();
|
||||||
|
|
||||||
|
addComponent(new ShadowComponent(visualizationContext, entity).radius(0.7f));
|
||||||
|
addComponent(new FireComponent(visualizationContext, entity));
|
||||||
|
addComponent(new HitboxComponent(visualizationContext, entity));
|
||||||
|
|
||||||
|
updateInstances(partialTick);
|
||||||
|
updateLight(partialTick);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ModelHolder createBodyModelHolder(ModelLayerLocation layer) {
|
private static ModelHolder createBodyModelHolder(ModelLayerLocation layer) {
|
||||||
|
@ -59,22 +72,6 @@ public class MinecartVisual<T extends AbstractMinecart> extends SimpleEntityVisu
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void init(float partialTick) {
|
|
||||||
addComponent(new ShadowComponent(visualizationContext, entity).radius(0.7f));
|
|
||||||
addComponent(new FireComponent(visualizationContext, entity));
|
|
||||||
addComponent(new HitboxComponent(visualizationContext, entity));
|
|
||||||
|
|
||||||
body = createBodyInstance();
|
|
||||||
blockState = entity.getDisplayBlockState();
|
|
||||||
contents = createContentsInstance();
|
|
||||||
|
|
||||||
updateInstances(partialTick);
|
|
||||||
updateLight();
|
|
||||||
|
|
||||||
super.init(partialTick);
|
|
||||||
}
|
|
||||||
|
|
||||||
private TransformedInstance createBodyInstance() {
|
private TransformedInstance createBodyInstance() {
|
||||||
return instancerProvider.instancer(InstanceTypes.TRANSFORMED, bodyModel.get())
|
return instancerProvider.instancer(InstanceTypes.TRANSFORMED, bodyModel.get())
|
||||||
.createInstance();
|
.createInstance();
|
||||||
|
@ -110,8 +107,6 @@ public class MinecartVisual<T extends AbstractMinecart> extends SimpleEntityVisu
|
||||||
}
|
}
|
||||||
contents = createContentsInstance();
|
contents = createContentsInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
updateLight();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -198,6 +193,9 @@ public class MinecartVisual<T extends AbstractMinecart> extends SimpleEntityVisu
|
||||||
stack.scale(-1.0F, -1.0F, 1.0F);
|
stack.scale(-1.0F, -1.0F, 1.0F);
|
||||||
body.setTransform(stack)
|
body.setTransform(stack)
|
||||||
.setChanged();
|
.setChanged();
|
||||||
|
|
||||||
|
// TODO: Use LitVisual if possible.
|
||||||
|
updateLight(partialTick);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void updateContents(TransformedInstance contents, PoseStack stack, float partialTick) {
|
protected void updateContents(TransformedInstance contents, PoseStack stack, float partialTick) {
|
||||||
|
@ -205,8 +203,8 @@ public class MinecartVisual<T extends AbstractMinecart> extends SimpleEntityVisu
|
||||||
.setChanged();
|
.setChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateLight() {
|
public void updateLight(float partialTick) {
|
||||||
relight(entity.blockPosition(), body, contents);
|
relight(partialTick, body, contents);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -34,19 +34,16 @@ public class ShulkerBoxVisual extends AbstractBlockEntityVisual<ShulkerBoxBlockE
|
||||||
return new SingleMeshModel(ModelPartConverter.convert(ModelLayers.SHULKER, texture.sprite(), "lid"), Materials.SHULKER);
|
return new SingleMeshModel(ModelPartConverter.convert(ModelLayers.SHULKER, texture.sprite(), "lid"), Materials.SHULKER);
|
||||||
});
|
});
|
||||||
|
|
||||||
private TransformedInstance base;
|
private final TransformedInstance base;
|
||||||
private TransformedInstance lid;
|
private final TransformedInstance lid;
|
||||||
|
|
||||||
private final PoseStack stack = new PoseStack();
|
private final PoseStack stack = new PoseStack();
|
||||||
|
|
||||||
private float lastProgress = Float.NaN;
|
private float lastProgress = Float.NaN;
|
||||||
|
|
||||||
public ShulkerBoxVisual(VisualizationContext ctx, ShulkerBoxBlockEntity blockEntity) {
|
public ShulkerBoxVisual(VisualizationContext ctx, ShulkerBoxBlockEntity blockEntity, float partialTick) {
|
||||||
super(ctx, blockEntity);
|
super(ctx, blockEntity, partialTick);
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void init(float partialTick) {
|
|
||||||
DyeColor color = blockEntity.getColor();
|
DyeColor color = blockEntity.getColor();
|
||||||
Material texture;
|
Material texture;
|
||||||
if (color == null) {
|
if (color == null) {
|
||||||
|
@ -67,12 +64,11 @@ public class ShulkerBoxVisual extends AbstractBlockEntityVisual<ShulkerBoxBlockE
|
||||||
.translateY(-1);
|
.translateY(-1);
|
||||||
|
|
||||||
base = createBaseInstance(texture).setTransform(stack);
|
base = createBaseInstance(texture).setTransform(stack);
|
||||||
lid = createLidInstance(texture).setTransform(stack);
|
|
||||||
|
|
||||||
base.setChanged();
|
base.setChanged();
|
||||||
|
lid = createLidInstance(texture).setTransform(stack);
|
||||||
lid.setChanged();
|
lid.setChanged();
|
||||||
|
|
||||||
super.init(partialTick);
|
updateLight(partialTick);
|
||||||
}
|
}
|
||||||
|
|
||||||
private TransformedInstance createBaseInstance(Material texture) {
|
private TransformedInstance createBaseInstance(Material texture) {
|
||||||
|
@ -119,8 +115,8 @@ public class ShulkerBoxVisual extends AbstractBlockEntityVisual<ShulkerBoxBlockE
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateLight() {
|
public void updateLight(float partialTick) {
|
||||||
relight(pos, base, lid);
|
relight(base, lid);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -11,8 +11,8 @@ import net.minecraft.world.entity.vehicle.MinecartTNT;
|
||||||
public class TntMinecartVisual<T extends MinecartTNT> extends MinecartVisual<T> {
|
public class TntMinecartVisual<T extends MinecartTNT> extends MinecartVisual<T> {
|
||||||
private static final int WHITE_OVERLAY = OverlayTexture.pack(OverlayTexture.u(1.0F), 10);
|
private static final int WHITE_OVERLAY = OverlayTexture.pack(OverlayTexture.u(1.0F), 10);
|
||||||
|
|
||||||
public TntMinecartVisual(VisualizationContext ctx, T entity) {
|
public TntMinecartVisual(VisualizationContext ctx, T entity, float partialTick) {
|
||||||
super(ctx, entity, TNT_BODY_MODEL);
|
super(ctx, entity, partialTick, TNT_BODY_MODEL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -35,7 +35,7 @@ public class TntMinecartVisual<T extends MinecartTNT> extends MinecartVisual<T>
|
||||||
}
|
}
|
||||||
|
|
||||||
contents.setTransform(stack)
|
contents.setTransform(stack)
|
||||||
.setOverlay(overlay)
|
.overlay(overlay)
|
||||||
.setChanged();
|
.setChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,27 +47,27 @@ public class VanillaVisuals {
|
||||||
.apply();
|
.apply();
|
||||||
|
|
||||||
builder(EntityType.CHEST_MINECART)
|
builder(EntityType.CHEST_MINECART)
|
||||||
.factory((ctx, entity) -> new MinecartVisual<>(ctx, entity, MinecartVisual.CHEST_BODY_MODEL))
|
.factory((ctx, entity, partialTick) -> new MinecartVisual<>(ctx, entity, partialTick, MinecartVisual.CHEST_BODY_MODEL))
|
||||||
.skipVanillaRender(MinecartVisual::shouldSkipRender)
|
.skipVanillaRender(MinecartVisual::shouldSkipRender)
|
||||||
.apply();
|
.apply();
|
||||||
builder(EntityType.COMMAND_BLOCK_MINECART)
|
builder(EntityType.COMMAND_BLOCK_MINECART)
|
||||||
.factory((ctx, entity) -> new MinecartVisual<>(ctx, entity, MinecartVisual.COMMAND_BLOCK_BODY_MODEL))
|
.factory((ctx, entity, partialTick) -> new MinecartVisual<>(ctx, entity, partialTick, MinecartVisual.COMMAND_BLOCK_BODY_MODEL))
|
||||||
.skipVanillaRender(MinecartVisual::shouldSkipRender)
|
.skipVanillaRender(MinecartVisual::shouldSkipRender)
|
||||||
.apply();
|
.apply();
|
||||||
builder(EntityType.FURNACE_MINECART)
|
builder(EntityType.FURNACE_MINECART)
|
||||||
.factory((ctx, entity) -> new MinecartVisual<>(ctx, entity, MinecartVisual.FURNACE_BODY_MODEL))
|
.factory((ctx, entity, partialTick) -> new MinecartVisual<>(ctx, entity, partialTick, MinecartVisual.FURNACE_BODY_MODEL))
|
||||||
.skipVanillaRender(MinecartVisual::shouldSkipRender)
|
.skipVanillaRender(MinecartVisual::shouldSkipRender)
|
||||||
.apply();
|
.apply();
|
||||||
builder(EntityType.HOPPER_MINECART)
|
builder(EntityType.HOPPER_MINECART)
|
||||||
.factory((ctx, entity) -> new MinecartVisual<>(ctx, entity, MinecartVisual.HOPPER_BODY_MODEL))
|
.factory((ctx, entity, partialTick) -> new MinecartVisual<>(ctx, entity, partialTick, MinecartVisual.HOPPER_BODY_MODEL))
|
||||||
.skipVanillaRender(MinecartVisual::shouldSkipRender)
|
.skipVanillaRender(MinecartVisual::shouldSkipRender)
|
||||||
.apply();
|
.apply();
|
||||||
builder(EntityType.MINECART)
|
builder(EntityType.MINECART)
|
||||||
.factory((ctx, entity) -> new MinecartVisual<>(ctx, entity, MinecartVisual.STANDARD_BODY_MODEL))
|
.factory((ctx, entity, partialTick) -> new MinecartVisual<>(ctx, entity, partialTick, MinecartVisual.STANDARD_BODY_MODEL))
|
||||||
.skipVanillaRender(MinecartVisual::shouldSkipRender)
|
.skipVanillaRender(MinecartVisual::shouldSkipRender)
|
||||||
.apply();
|
.apply();
|
||||||
builder(EntityType.SPAWNER_MINECART)
|
builder(EntityType.SPAWNER_MINECART)
|
||||||
.factory((ctx, entity) -> new MinecartVisual<>(ctx, entity, MinecartVisual.SPAWNER_BODY_MODEL))
|
.factory((ctx, entity, partialTick) -> new MinecartVisual<>(ctx, entity, partialTick, MinecartVisual.SPAWNER_BODY_MODEL))
|
||||||
.skipVanillaRender(MinecartVisual::shouldSkipRender)
|
.skipVanillaRender(MinecartVisual::shouldSkipRender)
|
||||||
.apply();
|
.apply();
|
||||||
builder(EntityType.TNT_MINECART)
|
builder(EntityType.TNT_MINECART)
|
||||||
|
|
|
@ -7,9 +7,9 @@ public class TestAtomicBitset {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testNextClearBit() {
|
void testNextClearBit() {
|
||||||
var segmentLength = 1 << AtomicBitset.DEFAULT_LOG2_SEGMENT_SIZE_IN_BITS;
|
var segmentLength = 1 << AtomicBitSet.DEFAULT_LOG2_SEGMENT_SIZE_IN_BITS;
|
||||||
var bitLength = 2 << AtomicBitset.DEFAULT_LOG2_SEGMENT_SIZE_IN_BITS;
|
var bitLength = 2 << AtomicBitSet.DEFAULT_LOG2_SEGMENT_SIZE_IN_BITS;
|
||||||
var bs = new AtomicBitset(AtomicBitset.DEFAULT_LOG2_SEGMENT_SIZE_IN_BITS, bitLength);
|
var bs = new AtomicBitSet(AtomicBitSet.DEFAULT_LOG2_SEGMENT_SIZE_IN_BITS, bitLength);
|
||||||
|
|
||||||
Assertions.assertEquals(0, bs.nextClearBit(0));
|
Assertions.assertEquals(0, bs.nextClearBit(0));
|
||||||
Assertions.assertEquals(1, bs.nextClearBit(1));
|
Assertions.assertEquals(1, bs.nextClearBit(1));
|
||||||
|
|
|
@ -19,7 +19,8 @@ neoforge_version_range = [20.4.234,)
|
||||||
|
|
||||||
# General build dependency versions
|
# General build dependency versions
|
||||||
java_version = 17
|
java_version = 17
|
||||||
arch_loom_version = 1.6-SNAPSHOT
|
# FIXME: This doesn't do anything.
|
||||||
|
# arch_loom_version = 1.6-SNAPSHOT
|
||||||
parchment_version = 2024.04.14
|
parchment_version = 2024.04.14
|
||||||
|
|
||||||
# Minecraft build dependency versions
|
# Minecraft build dependency versions
|
||||||
|
|
|
@ -12,10 +12,11 @@ pluginManagement {
|
||||||
maven("https://maven.parchmentmc.org")
|
maven("https://maven.parchmentmc.org")
|
||||||
}
|
}
|
||||||
|
|
||||||
plugins {
|
// FIXME: This doesn't do anything. The actual version is always the one defined in buildSrc/build.gradle.kts.
|
||||||
val arch_loom_version: String by settings
|
// plugins {
|
||||||
id("dev.architectury.loom") version arch_loom_version
|
// val arch_loom_version: String by settings
|
||||||
}
|
// id("dev.architectury.loom") version arch_loom_version
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
rootProject.name = "Flywheel"
|
rootProject.name = "Flywheel"
|
||||||
|
|
Loading…
Reference in a new issue