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 final Backend backend;
|
||||||
private boolean shouldCrash;
|
private boolean shouldCrash;
|
||||||
|
|
||||||
|
private boolean firstLoad = true;
|
||||||
|
|
||||||
public Loader(Backend backend) {
|
public Loader(Backend backend) {
|
||||||
this.backend = backend;
|
this.backend = backend;
|
||||||
|
|
||||||
|
@ -72,7 +74,7 @@ public class Loader implements ISelectiveResourceReloadListener {
|
||||||
|
|
||||||
Resolver.INSTANCE.invalidate();
|
Resolver.INSTANCE.invalidate();
|
||||||
ModLoader.get()
|
ModLoader.get()
|
||||||
.postEvent(new GatherContextEvent(backend));
|
.postEvent(new GatherContextEvent(backend, firstLoad));
|
||||||
|
|
||||||
ShaderSources sources = new ShaderSources(manager);
|
ShaderSources sources = new ShaderSources(manager);
|
||||||
|
|
||||||
|
@ -97,6 +99,8 @@ public class Loader implements ISelectiveResourceReloadListener {
|
||||||
CrumblingRenderer.reset();
|
CrumblingRenderer.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
firstLoad = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import java.io.BufferedReader;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.FileReader;
|
import java.io.FileReader;
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
|
@ -55,13 +56,18 @@ public class OptifineHandler {
|
||||||
public static void refresh() {
|
public static void refresh() {
|
||||||
if (optifine == null) return;
|
if (optifine == null) return;
|
||||||
|
|
||||||
|
boolean shadersOff = areShadersDisabledInOptifineConfigFile();
|
||||||
|
|
||||||
|
handler = new OptifineHandler(!shadersOff);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean areShadersDisabledInOptifineConfigFile() {
|
||||||
File dir = Minecraft.getInstance().gameDirectory;
|
File dir = Minecraft.getInstance().gameDirectory;
|
||||||
|
|
||||||
File shaderOptions = new File(dir, "optionsshaders.txt");
|
File shaderOptions = new File(dir, "optionsshaders.txt");
|
||||||
|
|
||||||
boolean shadersOff = true;
|
boolean shadersOff = true;
|
||||||
try {
|
try (BufferedReader reader = new BufferedReader(new FileReader(shaderOptions))) {
|
||||||
BufferedReader reader = new BufferedReader(new FileReader(shaderOptions));
|
|
||||||
|
|
||||||
shadersOff = reader.lines()
|
shadersOff = reader.lines()
|
||||||
.anyMatch(it -> {
|
.anyMatch(it -> {
|
||||||
|
@ -73,11 +79,10 @@ public class OptifineHandler {
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
} catch (FileNotFoundException e) {
|
} catch (IOException e) {
|
||||||
Backend.log.info("No shader config found.");
|
Backend.log.info("No shader config found.");
|
||||||
}
|
}
|
||||||
|
return shadersOff;
|
||||||
handler = new OptifineHandler(!shadersOff);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isUsingShaders() {
|
public boolean isUsingShaders() {
|
||||||
|
|
|
@ -18,8 +18,9 @@ import net.minecraftforge.event.TickEvent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A manager class for a single world where instancing is supported.
|
* A manager class for a single world where instancing is supported.
|
||||||
* <br>
|
* <p>
|
||||||
* The material manager is shared between the different instance managers.
|
* The material manager is shared between the different instance managers.
|
||||||
|
* </p>
|
||||||
*/
|
*/
|
||||||
public class InstanceWorld {
|
public class InstanceWorld {
|
||||||
protected final MaterialManager<WorldProgram> materialManager;
|
protected final MaterialManager<WorldProgram> materialManager;
|
||||||
|
@ -63,11 +64,12 @@ public class InstanceWorld {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get ready to render a frame:
|
* Get ready to render a frame.
|
||||||
* <br>
|
* <p>
|
||||||
* Check and shift the origin coordinate.
|
* Check and shift the origin coordinate.
|
||||||
* <br>
|
* <br>
|
||||||
* Call {@link IDynamicInstance#beginFrame()} on all instances in this world.
|
* Call {@link IDynamicInstance#beginFrame()} on all instances in this world.
|
||||||
|
* </p>
|
||||||
*/
|
*/
|
||||||
public void beginFrame(BeginFrameEvent event) {
|
public void beginFrame(BeginFrameEvent event) {
|
||||||
materialManager.checkAndShiftOrigin(event.getInfo());
|
materialManager.checkAndShiftOrigin(event.getInfo());
|
||||||
|
@ -78,8 +80,9 @@ public class InstanceWorld {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tick the renderers after the game has ticked:
|
* Tick the renderers after the game has ticked:
|
||||||
* <br>
|
* <p>
|
||||||
* Call {@link ITickableInstance#tick()} on all instances in this world.
|
* Call {@link ITickableInstance#tick()} on all instances in this world.
|
||||||
|
* </p>
|
||||||
*/
|
*/
|
||||||
public void tick() {
|
public void tick() {
|
||||||
Minecraft mc = Minecraft.getInstance();
|
Minecraft mc = Minecraft.getInstance();
|
||||||
|
|
|
@ -28,13 +28,17 @@ public class InstancedRenderDispatcher {
|
||||||
private static final WorldAttached<InstanceWorld> instanceWorlds = new WorldAttached<>($ -> new InstanceWorld());
|
private static final WorldAttached<InstanceWorld> instanceWorlds = new WorldAttached<>($ -> new InstanceWorld());
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Call this when you want to invoke
|
* Call this when you want to manually run {@link IInstance#update()}.
|
||||||
* @param te
|
* @param te The tile whose instance you want to update.
|
||||||
*/
|
*/
|
||||||
public static void enqueueUpdate(TileEntity te) {
|
public static void enqueueUpdate(TileEntity te) {
|
||||||
getTiles(te.getLevel()).queueUpdate(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) {
|
public static void enqueueUpdate(Entity entity) {
|
||||||
getEntities(entity.level).queueUpdate(entity);
|
getEntities(entity.level).queueUpdate(entity);
|
||||||
}
|
}
|
||||||
|
@ -66,7 +70,10 @@ public class InstancedRenderDispatcher {
|
||||||
|
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
public static void onBeginFrame(BeginFrameEvent event) {
|
public static void onBeginFrame(BeginFrameEvent event) {
|
||||||
instanceWorlds.get(event.getWorld()).beginFrame(event);
|
if (Backend.isGameActive()) {
|
||||||
|
instanceWorlds.get(event.getWorld())
|
||||||
|
.beginFrame(event);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
|
|
|
@ -37,10 +37,10 @@ import com.jozufozu.flywheel.util.AttribUtil;
|
||||||
public class Instancer<D extends InstanceData> {
|
public class Instancer<D extends InstanceData> {
|
||||||
|
|
||||||
protected final Supplier<IModel> gen;
|
protected final Supplier<IModel> gen;
|
||||||
protected IBufferedModel model;
|
|
||||||
|
|
||||||
protected final VertexFormat instanceFormat;
|
protected final VertexFormat instanceFormat;
|
||||||
protected final IInstanceFactory<D> factory;
|
protected final IInstanceFactory<D> factory;
|
||||||
|
|
||||||
|
protected IBufferedModel model;
|
||||||
protected GlVertexArray vao;
|
protected GlVertexArray vao;
|
||||||
protected GlBuffer instanceVBO;
|
protected GlBuffer instanceVBO;
|
||||||
protected int glBufferSize = -1;
|
protected int glBufferSize = -1;
|
||||||
|
@ -81,7 +81,7 @@ public class Instancer<D extends InstanceData> {
|
||||||
|
|
||||||
public void render() {
|
public void render() {
|
||||||
if (!isInitialized()) init();
|
if (!isInitialized()) init();
|
||||||
if (deleted) return;
|
if (invalid()) return;
|
||||||
|
|
||||||
vao.bind();
|
vao.bind();
|
||||||
renderSetup();
|
renderSetup();
|
||||||
|
@ -91,13 +91,19 @@ public class Instancer<D extends InstanceData> {
|
||||||
vao.unbind();
|
vao.unbind();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean invalid() {
|
||||||
|
return deleted || model == null;
|
||||||
|
}
|
||||||
|
|
||||||
private void init() {
|
private void init() {
|
||||||
model = new IndexedModel(gen.get());
|
|
||||||
initialized = true;
|
initialized = true;
|
||||||
|
IModel iModel = gen.get();
|
||||||
|
|
||||||
if (model.getVertexCount() <= 0)
|
if (iModel.empty()) {
|
||||||
throw new IllegalArgumentException("Refusing to instance a model with no vertices.");
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
model = new IndexedModel(iModel);
|
||||||
vao = new GlVertexArray();
|
vao = new GlVertexArray();
|
||||||
instanceVBO = new GlBuffer(GlBufferType.ARRAY_BUFFER);
|
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.
|
* Free acquired resources. All other Instancer methods are undefined behavior after calling delete.
|
||||||
*/
|
*/
|
||||||
public void delete() {
|
public void delete() {
|
||||||
if (deleted) return;
|
if (invalid()) return;
|
||||||
|
|
||||||
deleted = true;
|
deleted = true;
|
||||||
|
|
||||||
if (isInitialized()) {
|
model.delete();
|
||||||
model.delete();
|
|
||||||
|
|
||||||
instanceVBO.delete();
|
instanceVBO.delete();
|
||||||
vao.delete();
|
vao.delete();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private D _add(D instanceData) {
|
private D _add(D instanceData) {
|
||||||
|
|
|
@ -17,6 +17,7 @@ import com.jozufozu.flywheel.core.materials.OrientedData;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.tileentity.TileEntity;
|
import net.minecraft.tileentity.TileEntity;
|
||||||
import net.minecraft.util.math.BlockPos;
|
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.Vector3d;
|
||||||
import net.minecraft.util.math.vector.Vector3f;
|
import net.minecraft.util.math.vector.Vector3f;
|
||||||
import net.minecraft.util.math.vector.Vector3i;
|
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
|
* {@link TileInstanceManager}s are allowed to arbitrarily adjust the origin, and
|
||||||
* shift the world matrix provided as a shader uniform accordingly.
|
* shift the world matrix provided as a shader uniform accordingly.
|
||||||
*
|
*
|
||||||
* @return The {@link BlockPos position} of the {@link Entity} this instance
|
* @return The position this instance should be rendered at to appear in the correct location.
|
||||||
* represents should be rendered at to appear in the correct location.
|
|
||||||
*/
|
*/
|
||||||
public Vector3f getInstancePosition() {
|
public Vector3f getInstancePosition() {
|
||||||
Vector3d pos = entity.position();
|
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()));
|
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
|
@Override
|
||||||
public BlockPos getWorldPosition() {
|
public BlockPos getWorldPosition() {
|
||||||
return entity.blockPosition();
|
return entity.blockPosition();
|
||||||
|
|
|
@ -20,6 +20,19 @@ public class ModelData extends BasicData {
|
||||||
return this;
|
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
|
@Override
|
||||||
public void write(MappedBuffer buf) {
|
public void write(MappedBuffer buf) {
|
||||||
super.write(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 {
|
public class GatherContextEvent extends Event implements IModBusEvent {
|
||||||
|
|
||||||
private final Backend backend;
|
private final Backend backend;
|
||||||
|
private final boolean firstLoad;
|
||||||
|
|
||||||
public GatherContextEvent(Backend backend) {
|
public GatherContextEvent(Backend backend, boolean firstLoad) {
|
||||||
this.backend = backend;
|
this.backend = backend;
|
||||||
|
this.firstLoad = firstLoad;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Backend getBackend() {
|
public Backend getBackend() {
|
||||||
return backend;
|
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;
|
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
|
@Override
|
||||||
public TransformStack translate(double x, double y, double z) {
|
public TransformStack translate(double x, double y, double z) {
|
||||||
internal.translate(x, y, z);
|
internal.translate(x, y, z);
|
||||||
|
|
|
@ -44,6 +44,18 @@ public interface TransformStack {
|
||||||
return multiply(Vector3f.ZP, angle);
|
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() {
|
default TransformStack centre() {
|
||||||
return translateAll(0.5);
|
return translateAll(0.5);
|
||||||
}
|
}
|
||||||
|
@ -76,6 +88,10 @@ public interface TransformStack {
|
||||||
return translate(vec.x, vec.y, vec.z);
|
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) {
|
default TransformStack translateBack(Vector3d vec) {
|
||||||
return translate(-vec.x, -vec.y, -vec.z);
|
return translate(-vec.x, -vec.y, -vec.z);
|
||||||
}
|
}
|
||||||
|
@ -94,4 +110,34 @@ public interface TransformStack {
|
||||||
return this;
|
return this;
|
||||||
return multiply(axis.rotationDegrees((float) angle));
|
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