mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2024-12-28 16:06:28 +01:00
Random utilities from a messy workspace
- More documentation/clean up some old docs - isFirstLoad check on GatherContextEvent - Instancers no longer crash on empty model - setIdentity on MatrixTransformStack - more utilities for TransformStack - ModelData "nullification"
This commit is contained in:
parent
9ac7a79d69
commit
550f567190
11 changed files with 296 additions and 33 deletions
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -18,8 +18,9 @@ import net.minecraftforge.event.TickEvent;
|
|||
|
||||
/**
|
||||
* A manager class for a single world where instancing is supported.
|
||||
* <br>
|
||||
* The material manager is shared between the different instance managers.
|
||||
* <p>
|
||||
* The material manager is shared between the different instance managers.
|
||||
* </p>
|
||||
*/
|
||||
public class InstanceWorld {
|
||||
protected final MaterialManager<WorldProgram> materialManager;
|
||||
|
@ -63,11 +64,12 @@ public class InstanceWorld {
|
|||
}
|
||||
|
||||
/**
|
||||
* Get ready to render a frame:
|
||||
* <br>
|
||||
* Check and shift the origin coordinate.
|
||||
* <br>
|
||||
* Call {@link IDynamicInstance#beginFrame()} on all instances in this world.
|
||||
* Get ready to render a frame.
|
||||
* <p>
|
||||
* Check and shift the origin coordinate.
|
||||
* <br>
|
||||
* Call {@link IDynamicInstance#beginFrame()} on all instances in this world.
|
||||
* </p>
|
||||
*/
|
||||
public void beginFrame(BeginFrameEvent event) {
|
||||
materialManager.checkAndShiftOrigin(event.getInfo());
|
||||
|
@ -78,8 +80,9 @@ public class InstanceWorld {
|
|||
|
||||
/**
|
||||
* Tick the renderers after the game has ticked:
|
||||
* <br>
|
||||
* Call {@link ITickableInstance#tick()} on all instances in this world.
|
||||
* <p>
|
||||
* Call {@link ITickableInstance#tick()} on all instances in this world.
|
||||
* </p>
|
||||
*/
|
||||
public void tick() {
|
||||
Minecraft mc = Minecraft.getInstance();
|
||||
|
|
|
@ -28,13 +28,17 @@ public class InstancedRenderDispatcher {
|
|||
private static final WorldAttached<InstanceWorld> 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
|
||||
|
|
|
@ -37,10 +37,10 @@ import com.jozufozu.flywheel.util.AttribUtil;
|
|||
public class Instancer<D extends InstanceData> {
|
||||
|
||||
protected final Supplier<IModel> gen;
|
||||
protected IBufferedModel model;
|
||||
|
||||
protected final VertexFormat instanceFormat;
|
||||
protected final IInstanceFactory<D> factory;
|
||||
|
||||
protected IBufferedModel model;
|
||||
protected GlVertexArray vao;
|
||||
protected GlBuffer instanceVBO;
|
||||
protected int glBufferSize = -1;
|
||||
|
@ -81,7 +81,7 @@ public class Instancer<D extends InstanceData> {
|
|||
|
||||
public void render() {
|
||||
if (!isInitialized()) init();
|
||||
if (deleted) return;
|
||||
if (invalid()) return;
|
||||
|
||||
vao.bind();
|
||||
renderSetup();
|
||||
|
@ -91,13 +91,19 @@ public class Instancer<D extends InstanceData> {
|
|||
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<D extends InstanceData> {
|
|||
* 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) {
|
||||
|
|
|
@ -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<E extends Entity> 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<E extends Entity> 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();
|
||||
|
|
|
@ -20,6 +20,19 @@ public class ModelData extends BasicData {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the transform matrices to be all zeros.
|
||||
*
|
||||
* <p>
|
||||
* This will allow the gpu to quickly discard all geometry for this instance, effectively "turning it off".
|
||||
* </p>
|
||||
*/
|
||||
public ModelData setEmptyTransform() {
|
||||
matrices = empty;
|
||||
markDirty();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(MappedBuffer buf) {
|
||||
super.write(buf);
|
||||
|
|
|
@ -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<BakedQuad> 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<BakedQuad> 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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue