diff --git a/src/main/java/com/jozufozu/flywheel/backend/Loader.java b/src/main/java/com/jozufozu/flywheel/backend/Loader.java
index 15efd3bcb..de617646e 100644
--- a/src/main/java/com/jozufozu/flywheel/backend/Loader.java
+++ b/src/main/java/com/jozufozu/flywheel/backend/Loader.java
@@ -44,6 +44,8 @@ public class Loader implements ISelectiveResourceReloadListener {
private final Backend backend;
private boolean shouldCrash;
+ private boolean firstLoad = true;
+
public Loader(Backend backend) {
this.backend = backend;
@@ -72,7 +74,7 @@ public class Loader implements ISelectiveResourceReloadListener {
Resolver.INSTANCE.invalidate();
ModLoader.get()
- .postEvent(new GatherContextEvent(backend));
+ .postEvent(new GatherContextEvent(backend, firstLoad));
ShaderSources sources = new ShaderSources(manager);
@@ -97,6 +99,8 @@ public class Loader implements ISelectiveResourceReloadListener {
CrumblingRenderer.reset();
}
}
+
+ firstLoad = false;
}
}
diff --git a/src/main/java/com/jozufozu/flywheel/backend/OptifineHandler.java b/src/main/java/com/jozufozu/flywheel/backend/OptifineHandler.java
index 37ac4451c..0cca30b39 100644
--- a/src/main/java/com/jozufozu/flywheel/backend/OptifineHandler.java
+++ b/src/main/java/com/jozufozu/flywheel/backend/OptifineHandler.java
@@ -4,6 +4,7 @@ import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
+import java.io.IOException;
import java.util.Optional;
import net.minecraft.client.Minecraft;
@@ -55,13 +56,18 @@ public class OptifineHandler {
public static void refresh() {
if (optifine == null) return;
+ boolean shadersOff = areShadersDisabledInOptifineConfigFile();
+
+ handler = new OptifineHandler(!shadersOff);
+ }
+
+ private static boolean areShadersDisabledInOptifineConfigFile() {
File dir = Minecraft.getInstance().gameDirectory;
File shaderOptions = new File(dir, "optionsshaders.txt");
boolean shadersOff = true;
- try {
- BufferedReader reader = new BufferedReader(new FileReader(shaderOptions));
+ try (BufferedReader reader = new BufferedReader(new FileReader(shaderOptions))) {
shadersOff = reader.lines()
.anyMatch(it -> {
@@ -73,11 +79,10 @@ public class OptifineHandler {
}
return false;
});
- } catch (FileNotFoundException e) {
+ } catch (IOException e) {
Backend.log.info("No shader config found.");
}
-
- handler = new OptifineHandler(!shadersOff);
+ return shadersOff;
}
public boolean isUsingShaders() {
diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceWorld.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceWorld.java
index 26ddbbb67..e2c54a561 100644
--- a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceWorld.java
+++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceWorld.java
@@ -18,8 +18,9 @@ import net.minecraftforge.event.TickEvent;
/**
* A manager class for a single world where instancing is supported.
- *
- * The material manager is shared between the different instance managers.
+ *
+ * The material manager is shared between the different instance managers.
+ *
*/
public class InstanceWorld {
protected final MaterialManager materialManager;
@@ -63,11 +64,12 @@ public class InstanceWorld {
}
/**
- * Get ready to render a frame:
- *
- * Check and shift the origin coordinate.
- *
- * Call {@link IDynamicInstance#beginFrame()} on all instances in this world.
+ * Get ready to render a frame.
+ *
+ * Check and shift the origin coordinate.
+ *
+ * Call {@link IDynamicInstance#beginFrame()} on all instances in this world.
+ *
*/
public void beginFrame(BeginFrameEvent event) {
materialManager.checkAndShiftOrigin(event.getInfo());
@@ -78,8 +80,9 @@ public class InstanceWorld {
/**
* Tick the renderers after the game has ticked:
- *
- * Call {@link ITickableInstance#tick()} on all instances in this world.
+ *
+ * Call {@link ITickableInstance#tick()} on all instances in this world.
+ *
*/
public void tick() {
Minecraft mc = Minecraft.getInstance();
diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java
index 1186d7ea3..708582ae5 100644
--- a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java
+++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java
@@ -28,13 +28,17 @@ public class InstancedRenderDispatcher {
private static final WorldAttached instanceWorlds = new WorldAttached<>($ -> new InstanceWorld());
/**
- * Call this when you want to invoke
- * @param te
+ * Call this when you want to manually run {@link IInstance#update()}.
+ * @param te The tile whose instance you want to update.
*/
public static void enqueueUpdate(TileEntity te) {
getTiles(te.getLevel()).queueUpdate(te);
}
+ /**
+ * Call this when you want to manually run {@link IInstance#update()}.
+ * @param entity The entity whose instance you want to update.
+ */
public static void enqueueUpdate(Entity entity) {
getEntities(entity.level).queueUpdate(entity);
}
@@ -66,7 +70,10 @@ public class InstancedRenderDispatcher {
@SubscribeEvent
public static void onBeginFrame(BeginFrameEvent event) {
- instanceWorlds.get(event.getWorld()).beginFrame(event);
+ if (Backend.isGameActive()) {
+ instanceWorlds.get(event.getWorld())
+ .beginFrame(event);
+ }
}
@SubscribeEvent
diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/Instancer.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/Instancer.java
index 132cbd9f2..c2b3dd720 100644
--- a/src/main/java/com/jozufozu/flywheel/backend/instancing/Instancer.java
+++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/Instancer.java
@@ -37,10 +37,10 @@ import com.jozufozu.flywheel.util.AttribUtil;
public class Instancer {
protected final Supplier gen;
- protected IBufferedModel model;
-
protected final VertexFormat instanceFormat;
protected final IInstanceFactory factory;
+
+ protected IBufferedModel model;
protected GlVertexArray vao;
protected GlBuffer instanceVBO;
protected int glBufferSize = -1;
@@ -81,7 +81,7 @@ public class Instancer {
public void render() {
if (!isInitialized()) init();
- if (deleted) return;
+ if (invalid()) return;
vao.bind();
renderSetup();
@@ -91,13 +91,19 @@ public class Instancer {
vao.unbind();
}
+ private boolean invalid() {
+ return deleted || model == null;
+ }
+
private void init() {
- model = new IndexedModel(gen.get());
initialized = true;
+ IModel iModel = gen.get();
- if (model.getVertexCount() <= 0)
- throw new IllegalArgumentException("Refusing to instance a model with no vertices.");
+ if (iModel.empty()) {
+ return;
+ }
+ model = new IndexedModel(iModel);
vao = new GlVertexArray();
instanceVBO = new GlBuffer(GlBufferType.ARRAY_BUFFER);
@@ -133,16 +139,14 @@ public class Instancer {
* Free acquired resources. All other Instancer methods are undefined behavior after calling delete.
*/
public void delete() {
- if (deleted) return;
+ if (invalid()) return;
deleted = true;
- if (isInitialized()) {
- model.delete();
+ model.delete();
- instanceVBO.delete();
- vao.delete();
- }
+ instanceVBO.delete();
+ vao.delete();
}
private D _add(D instanceData) {
diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/entity/EntityInstance.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/entity/EntityInstance.java
index c3e93fcdb..d3370626e 100644
--- a/src/main/java/com/jozufozu/flywheel/backend/instancing/entity/EntityInstance.java
+++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/entity/EntityInstance.java
@@ -17,6 +17,7 @@ import com.jozufozu.flywheel.core.materials.OrientedData;
import net.minecraft.entity.Entity;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.BlockPos;
+import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.vector.Vector3d;
import net.minecraft.util.math.vector.Vector3f;
import net.minecraft.util.math.vector.Vector3i;
@@ -89,8 +90,7 @@ public abstract class EntityInstance implements IInstance {
* {@link TileInstanceManager}s are allowed to arbitrarily adjust the origin, and
* shift the world matrix provided as a shader uniform accordingly.
*
- * @return The {@link BlockPos position} of the {@link Entity} this instance
- * represents should be rendered at to appear in the correct location.
+ * @return The position this instance should be rendered at to appear in the correct location.
*/
public Vector3f getInstancePosition() {
Vector3d pos = entity.position();
@@ -98,6 +98,23 @@ public abstract class EntityInstance implements IInstance {
return new Vector3f((float) (pos.x - origin.getX()), (float) (pos.y - origin.getY()), (float) (pos.z - origin.getZ()));
}
+ /**
+ * In order to accommodate for floating point precision errors at high coordinates,
+ * {@link TileInstanceManager}s are allowed to arbitrarily adjust the origin, and
+ * shift the world matrix provided as a shader uniform accordingly.
+ *
+ * @return The position this instance should be rendered at to appear in the correct location.
+ */
+ public Vector3f getInstancePosition(float partialTicks) {
+ Vector3d pos = entity.position();
+ Vector3i origin = materialManager.getOriginCoordinate();
+ return new Vector3f(
+ (float) (MathHelper.lerp(partialTicks, entity.xOld, pos.x) - origin.getX()),
+ (float) (MathHelper.lerp(partialTicks, entity.yOld, pos.y) - origin.getY()),
+ (float) (MathHelper.lerp(partialTicks, entity.zOld, pos.z) - origin.getZ())
+ );
+ }
+
@Override
public BlockPos getWorldPosition() {
return entity.blockPosition();
diff --git a/src/main/java/com/jozufozu/flywheel/core/materials/ModelData.java b/src/main/java/com/jozufozu/flywheel/core/materials/ModelData.java
index f7c99122a..9c15d99cd 100644
--- a/src/main/java/com/jozufozu/flywheel/core/materials/ModelData.java
+++ b/src/main/java/com/jozufozu/flywheel/core/materials/ModelData.java
@@ -20,6 +20,19 @@ public class ModelData extends BasicData {
return this;
}
+ /**
+ * Sets the transform matrices to be all zeros.
+ *
+ *
+ * This will allow the gpu to quickly discard all geometry for this instance, effectively "turning it off".
+ *
+ */
+ public ModelData setEmptyTransform() {
+ matrices = empty;
+ markDirty();
+ return this;
+ }
+
@Override
public void write(MappedBuffer buf) {
super.write(buf);
diff --git a/src/main/java/com/jozufozu/flywheel/core/model/BakedModelModel.java b/src/main/java/com/jozufozu/flywheel/core/model/BakedModelModel.java
new file mode 100644
index 000000000..f5eead908
--- /dev/null
+++ b/src/main/java/com/jozufozu/flywheel/core/model/BakedModelModel.java
@@ -0,0 +1,139 @@
+package com.jozufozu.flywheel.core.model;
+
+import static com.jozufozu.flywheel.util.RenderMath.nb;
+
+import java.nio.Buffer;
+import java.nio.ByteBuffer;
+import java.nio.IntBuffer;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Random;
+
+import org.lwjgl.system.MemoryStack;
+
+import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
+import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer;
+import com.jozufozu.flywheel.core.Formats;
+import com.jozufozu.flywheel.util.VirtualEmptyModelData;
+import com.mojang.blaze3d.matrix.MatrixStack;
+
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.renderer.ItemRenderer;
+import net.minecraft.client.renderer.color.ItemColors;
+import net.minecraft.client.renderer.model.BakedQuad;
+import net.minecraft.client.renderer.model.IBakedModel;
+import net.minecraft.client.renderer.model.ItemCameraTransforms;
+import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.Direction;
+import net.minecraft.util.math.vector.Vector3f;
+import net.minecraft.util.math.vector.Vector3i;
+import net.minecraftforge.client.ForgeHooksClient;
+
+public class BakedModelModel implements IModel {
+ // DOWN, UP, NORTH, SOUTH, WEST, EAST, null
+ private static final Direction[] dirs;
+
+ static {
+ Direction[] directions = Direction.values();
+
+ dirs = Arrays.copyOf(directions, directions.length + 1);
+ }
+
+
+ public final IBakedModel model;
+ private final int numQuads;
+
+ public BakedModelModel(IBakedModel model) {
+ this.model = model;
+
+ Random random = new Random();
+
+ int numQuads = 0;
+
+ for (Direction dir : dirs) {
+ random.setSeed(42);
+ List quads = model.getQuads(null, dir, random, VirtualEmptyModelData.INSTANCE);
+
+ numQuads += quads.size();
+ }
+
+ this.numQuads = numQuads;
+ }
+
+ @Override
+ public void buffer(VecBuffer buffer) {
+
+ Minecraft mc = Minecraft.getInstance();
+
+ ItemColors itemColors = mc.getItemColors();
+
+ Random random = new Random();
+
+ for (Direction dir : dirs) {
+ random.setSeed(42);
+ List quads = model.getQuads(null, dir, random, VirtualEmptyModelData.INSTANCE);
+
+ for (BakedQuad bakedQuad : quads) {
+// int i = -1;
+// if (!itemStack.isEmpty() && bakedQuad.isTinted()) {
+// i = itemColors.getColor(itemStack, bakedQuad.getTintIndex());
+// }
+//
+// byte red = (byte)(i >> 16 & 255);
+// byte green = (byte)(i >> 8 & 255);
+// byte blue = (byte)(i & 255);
+
+ int[] aint = bakedQuad.getVertices();
+ Vector3i faceNormal = bakedQuad.getDirection().getNormal();
+ Vector3f normal = new Vector3f((float)faceNormal.getX(), (float)faceNormal.getY(), (float)faceNormal.getZ());
+ int intSize = DefaultVertexFormats.BLOCK.getIntegerSize();
+ int vertexCount = aint.length / intSize;
+
+ try (MemoryStack memorystack = MemoryStack.stackPush()) {
+ ByteBuffer bytebuffer = memorystack.malloc(DefaultVertexFormats.BLOCK.getVertexSize());
+ IntBuffer intbuffer = bytebuffer.asIntBuffer();
+
+ for(int j = 0; j < vertexCount; ++j) {
+ ((Buffer)intbuffer).clear();
+ intbuffer.put(aint, j * 8, 8);
+ float f = bytebuffer.getFloat(0);
+ float f1 = bytebuffer.getFloat(4);
+ float f2 = bytebuffer.getFloat(8);
+// float cr;
+// float cg;
+// float cb;
+// float ca;
+// {
+// float r = (float)(bytebuffer.get(12) & 255) / 255.0F;
+// float g = (float)(bytebuffer.get(13) & 255) / 255.0F;
+// float b = (float)(bytebuffer.get(14) & 255) / 255.0F;
+// float a = (float)(bytebuffer.get(15) & 255) / 255.0F;
+// cr = r * red;
+// cg = g * green;
+// cb = b * blue;
+// ca = a;
+// }
+
+ float u = bytebuffer.getFloat(16);
+ float v = bytebuffer.getFloat(20);
+
+ buffer.putVec3(f, f1, f2);
+ buffer.putVec3(nb(normal.x()), nb(normal.y()), nb(normal.z()));
+ buffer.putVec2(u, v);
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ public int vertexCount() {
+ return numQuads * 4;
+ }
+
+ @Override
+ public VertexFormat format() {
+ return Formats.UNLIT_MODEL;
+ }
+}
diff --git a/src/main/java/com/jozufozu/flywheel/event/GatherContextEvent.java b/src/main/java/com/jozufozu/flywheel/event/GatherContextEvent.java
index a409d4363..c7891abfb 100644
--- a/src/main/java/com/jozufozu/flywheel/event/GatherContextEvent.java
+++ b/src/main/java/com/jozufozu/flywheel/event/GatherContextEvent.java
@@ -8,12 +8,21 @@ import net.minecraftforge.fml.event.lifecycle.IModBusEvent;
public class GatherContextEvent extends Event implements IModBusEvent {
private final Backend backend;
+ private final boolean firstLoad;
- public GatherContextEvent(Backend backend) {
+ public GatherContextEvent(Backend backend, boolean firstLoad) {
this.backend = backend;
+ this.firstLoad = firstLoad;
}
public Backend getBackend() {
return backend;
}
+
+ /**
+ * @return true iff it is the first time the event is fired.
+ */
+ public boolean isFirstLoad() {
+ return firstLoad;
+ }
}
diff --git a/src/main/java/com/jozufozu/flywheel/util/transform/MatrixTransformStack.java b/src/main/java/com/jozufozu/flywheel/util/transform/MatrixTransformStack.java
index ed08b5dc7..52cbdb5ab 100644
--- a/src/main/java/com/jozufozu/flywheel/util/transform/MatrixTransformStack.java
+++ b/src/main/java/com/jozufozu/flywheel/util/transform/MatrixTransformStack.java
@@ -24,6 +24,22 @@ public class MatrixTransformStack implements TransformStack {
return internal;
}
+ public MatrixTransformStack setIdentity() {
+ if (internal.clear()) {
+ MatrixStack.Entry last = internal.last();
+
+ last.normal()
+ .setIdentity();
+ last.pose()
+ .setIdentity();
+ } else {
+ internal.popPose();
+ internal.pushPose();
+ }
+
+ return this;
+ }
+
@Override
public TransformStack translate(double x, double y, double z) {
internal.translate(x, y, z);
diff --git a/src/main/java/com/jozufozu/flywheel/util/transform/TransformStack.java b/src/main/java/com/jozufozu/flywheel/util/transform/TransformStack.java
index 1962bcf26..1066446cd 100644
--- a/src/main/java/com/jozufozu/flywheel/util/transform/TransformStack.java
+++ b/src/main/java/com/jozufozu/flywheel/util/transform/TransformStack.java
@@ -44,6 +44,18 @@ public interface TransformStack {
return multiply(Vector3f.ZP, angle);
}
+ default TransformStack rotateXRadians(double angle) {
+ return multiplyRadians(Vector3f.XP, angle);
+ }
+
+ default TransformStack rotateYRadians(double angle) {
+ return multiplyRadians(Vector3f.YP, angle);
+ }
+
+ default TransformStack rotateZRadians(double angle) {
+ return multiplyRadians(Vector3f.ZP, angle);
+ }
+
default TransformStack centre() {
return translateAll(0.5);
}
@@ -76,6 +88,10 @@ public interface TransformStack {
return translate(vec.x, vec.y, vec.z);
}
+ default TransformStack translate(Vector3f vec) {
+ return translate(vec.x(), vec.y(), vec.z());
+ }
+
default TransformStack translateBack(Vector3d vec) {
return translate(-vec.x, -vec.y, -vec.z);
}
@@ -94,4 +110,34 @@ public interface TransformStack {
return this;
return multiply(axis.rotationDegrees((float) angle));
}
+
+ default TransformStack multiplyRadians(Vector3f axis, double angle) {
+ if (angle == 0)
+ return this;
+ return multiply(axis.rotation((float) angle));
+ }
+
+ default TransformStack rotateToFace(Direction facing) {
+ switch (facing) {
+ case SOUTH:
+ multiply(Vector3f.YP.rotationDegrees(180));
+ break;
+ case WEST:
+ multiply(Vector3f.YP.rotationDegrees(90));
+ break;
+ case NORTH:
+ multiply(Vector3f.YP.rotationDegrees(0));
+ break;
+ case EAST:
+ multiply(Vector3f.YP.rotationDegrees(270));
+ break;
+ case UP:
+ multiply(Vector3f.XP.rotationDegrees(90));
+ break;
+ case DOWN:
+ multiply(Vector3f.XN.rotationDegrees(90));
+ break;
+ }
+ return this;
+ }
}