mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2024-12-27 07:26:48 +01:00
4d chest
- Refactor InstancedRenderRegistry to allow for 3rd party TEs to have instances - Add ChestInstance, incomplete but there - Add basic api for building vanilla formatted models - Better instance factory registration
This commit is contained in:
parent
c79c41c16f
commit
60d7ca6e91
16 changed files with 788 additions and 18 deletions
|
@ -5,6 +5,8 @@ import com.jozufozu.flywheel.core.AtlasStitcher;
|
|||
import com.jozufozu.flywheel.core.Contexts;
|
||||
import com.jozufozu.flywheel.core.Materials;
|
||||
|
||||
import com.jozufozu.flywheel.vanilla.VanillaInstances;
|
||||
|
||||
import net.minecraftforge.eventbus.api.IEventBus;
|
||||
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
|
||||
|
||||
|
@ -20,5 +22,7 @@ public class FlywheelClient {
|
|||
|
||||
modEventBus.addListener(Contexts::flwInit);
|
||||
modEventBus.addListener(Materials::flwInit);
|
||||
|
||||
VanillaInstances.init();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,6 +40,12 @@ public abstract class InstanceManager<T> implements MaterialManager.OriginShiftL
|
|||
materialManager.addListener(this);
|
||||
}
|
||||
|
||||
protected abstract boolean canInstance(T obj);
|
||||
|
||||
protected abstract IInstance createRaw(T obj);
|
||||
|
||||
protected abstract boolean canCreateInstance(T entity);
|
||||
|
||||
public void tick(double cameraX, double cameraY, double cameraZ) {
|
||||
tick++;
|
||||
|
||||
|
@ -100,7 +106,7 @@ public abstract class InstanceManager<T> implements MaterialManager.OriginShiftL
|
|||
if (!Backend.getInstance()
|
||||
.canUseInstancing()) return;
|
||||
|
||||
if (obj instanceof IInstanceRendered) {
|
||||
if (canInstance(obj)) {
|
||||
addInternal(obj);
|
||||
}
|
||||
}
|
||||
|
@ -116,7 +122,7 @@ public abstract class InstanceManager<T> implements MaterialManager.OriginShiftL
|
|||
if (!Backend.getInstance()
|
||||
.canUseInstancing()) return;
|
||||
|
||||
if (obj instanceof IInstanceRendered) {
|
||||
if (canInstance(obj)) {
|
||||
IInstance instance = getInstance(obj, false);
|
||||
|
||||
if (instance != null) {
|
||||
|
@ -143,7 +149,7 @@ public abstract class InstanceManager<T> implements MaterialManager.OriginShiftL
|
|||
if (!Backend.getInstance()
|
||||
.canUseInstancing()) return;
|
||||
|
||||
if (obj instanceof IInstanceRendered) {
|
||||
if (canInstance(obj)) {
|
||||
IInstance instance = getInstance(obj, false);
|
||||
|
||||
if (instance != null) instance.updateLight();
|
||||
|
@ -154,7 +160,7 @@ public abstract class InstanceManager<T> implements MaterialManager.OriginShiftL
|
|||
if (!Backend.getInstance()
|
||||
.canUseInstancing()) return;
|
||||
|
||||
if (obj instanceof IInstanceRendered) {
|
||||
if (canInstance(obj)) {
|
||||
IInstance instance = getInstance(obj, false);
|
||||
if (instance != null) removeInternal(obj, instance);
|
||||
}
|
||||
|
@ -241,8 +247,4 @@ public abstract class InstanceManager<T> implements MaterialManager.OriginShiftL
|
|||
invalidate();
|
||||
instancedTiles.forEach(this::add);
|
||||
}
|
||||
|
||||
protected abstract IInstance createRaw(T obj);
|
||||
|
||||
protected abstract boolean canCreateInstance(T entity);
|
||||
}
|
||||
|
|
|
@ -10,6 +10,8 @@ import com.jozufozu.flywheel.backend.instancing.entity.IEntityInstanceFactory;
|
|||
import com.jozufozu.flywheel.backend.instancing.tile.ITileInstanceFactory;
|
||||
import com.jozufozu.flywheel.backend.instancing.tile.TileEntityInstance;
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.Object2BooleanLinkedOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2BooleanMap;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityType;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
|
@ -22,15 +24,36 @@ public class InstancedRenderRegistry {
|
|||
return INSTANCE;
|
||||
}
|
||||
|
||||
private final Object2BooleanMap<Object> skipRender = new Object2BooleanLinkedOpenHashMap<>();
|
||||
private final Map<TileEntityType<?>, ITileInstanceFactory<?>> tiles = Maps.newHashMap();
|
||||
private final Map<EntityType<?>, IEntityInstanceFactory<?>> entities = Maps.newHashMap();
|
||||
|
||||
public <T extends TileEntity> void register(TileEntityType<? extends T> type, ITileInstanceFactory<? super T> rendererFactory) {
|
||||
this.tiles.put(type, rendererFactory);
|
||||
protected InstancedRenderRegistry() {
|
||||
skipRender.defaultReturnValue(false);
|
||||
}
|
||||
|
||||
public <T extends Entity> void register(EntityType<? extends T> type, IEntityInstanceFactory<? super T> rendererFactory) {
|
||||
this.entities.put(type, rendererFactory);
|
||||
public <T extends TileEntity> boolean shouldSkipRender(T type) {
|
||||
return _skipRender(type.getType()) || ((type instanceof IInstanceRendered) && !((IInstanceRendered) type).shouldRenderNormally());
|
||||
}
|
||||
|
||||
public <T extends Entity> boolean shouldSkipRender(T type) {
|
||||
return _skipRender(type.getType()) || ((type instanceof IInstanceRendered) && !((IInstanceRendered) type).shouldRenderNormally());
|
||||
}
|
||||
|
||||
public <T extends TileEntity> boolean canInstance(TileEntityType<? extends T> type) {
|
||||
return tiles.containsKey(type);
|
||||
}
|
||||
|
||||
public <T extends Entity> boolean canInstance(EntityType<? extends T> type) {
|
||||
return entities.containsKey(type);
|
||||
}
|
||||
|
||||
public <T extends TileEntity> TileRegistrater<? extends T> tile(TileEntityType<? extends T> type) {
|
||||
return new TileRegistrater<>(type);
|
||||
}
|
||||
|
||||
public <T extends Entity> EntityRegistrater<? extends T> entity(EntityType<? extends T> type) {
|
||||
return new EntityRegistrater<>(type);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
@ -54,4 +77,64 @@ public class InstancedRenderRegistry {
|
|||
else return factory.create(manager, tile);
|
||||
}
|
||||
|
||||
private boolean _skipRender(Object o) {
|
||||
return skipRender.getBoolean(o);
|
||||
}
|
||||
|
||||
public class TileRegistrater<T extends TileEntity> {
|
||||
|
||||
private final TileEntityType<T> type;
|
||||
private ITileInstanceFactory<? super T> factory;
|
||||
private boolean skipRender = false;
|
||||
|
||||
public TileRegistrater(TileEntityType<T> type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public TileRegistrater<T> factory(ITileInstanceFactory<? super T> rendererFactory) {
|
||||
factory = rendererFactory;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TileRegistrater<T> setSkipRender(boolean skipRender) {
|
||||
this.skipRender = skipRender;
|
||||
return this;
|
||||
}
|
||||
|
||||
public InstancedRenderRegistry build() {
|
||||
tiles.put(type, factory);
|
||||
InstancedRenderRegistry.this.skipRender.put(type, skipRender);
|
||||
|
||||
return InstancedRenderRegistry.this;
|
||||
}
|
||||
}
|
||||
|
||||
public class EntityRegistrater<T extends Entity> {
|
||||
|
||||
private final EntityType<T> type;
|
||||
private IEntityInstanceFactory<? super T> factory;
|
||||
private boolean skipRender = false;
|
||||
|
||||
public EntityRegistrater(EntityType<T> type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public EntityRegistrater<T> factory(IEntityInstanceFactory<? super T> rendererFactory) {
|
||||
factory = rendererFactory;
|
||||
return this;
|
||||
}
|
||||
|
||||
public EntityRegistrater<T> setSkipRender(boolean skipRender) {
|
||||
this.skipRender = skipRender;
|
||||
return this;
|
||||
}
|
||||
|
||||
public InstancedRenderRegistry build() {
|
||||
entities.put(type, factory);
|
||||
InstancedRenderRegistry.this.skipRender.put(type, skipRender);
|
||||
|
||||
return InstancedRenderRegistry.this;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import com.jozufozu.flywheel.backend.instancing.InstancedRenderRegistry;
|
|||
import com.jozufozu.flywheel.backend.instancing.MaterialManager;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.IBlockReader;
|
||||
import net.minecraft.world.World;
|
||||
|
@ -17,6 +18,11 @@ public class EntityInstanceManager extends InstanceManager<Entity> {
|
|||
super(materialManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canInstance(Entity obj) {
|
||||
return obj != null && InstancedRenderRegistry.getInstance().canInstance(obj.getType());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IInstance createRaw(Entity obj) {
|
||||
return InstancedRenderRegistry.getInstance()
|
||||
|
|
|
@ -17,6 +17,11 @@ public class TileInstanceManager extends InstanceManager<TileEntity> {
|
|||
super(materialManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canInstance(TileEntity obj) {
|
||||
return obj != null && InstancedRenderRegistry.getInstance().canInstance(obj.getType());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IInstance createRaw(TileEntity obj) {
|
||||
return InstancedRenderRegistry.getInstance()
|
||||
|
|
|
@ -19,7 +19,7 @@ public class OrientedData extends BasicData {
|
|||
private float qX;
|
||||
private float qY;
|
||||
private float qZ;
|
||||
private float qW;
|
||||
private float qW = 1;
|
||||
|
||||
public OrientedData(Instancer<?> owner) {
|
||||
super(owner);
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
package com.jozufozu.flywheel.core.model;
|
||||
|
||||
public class ModelPart {
|
||||
|
||||
public static PartBuilder builder(int sizeU, int sizeV) {
|
||||
return new PartBuilder(sizeU, sizeV);
|
||||
}
|
||||
}
|
199
src/main/java/com/jozufozu/flywheel/core/model/PartBuilder.java
Normal file
199
src/main/java/com/jozufozu/flywheel/core/model/PartBuilder.java
Normal file
|
@ -0,0 +1,199 @@
|
|||
package com.jozufozu.flywheel.core.model;
|
||||
|
||||
import static com.jozufozu.flywheel.util.RenderMath.*;
|
||||
|
||||
import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer;
|
||||
import com.jozufozu.flywheel.backend.model.BufferedModel;
|
||||
|
||||
import com.jozufozu.flywheel.backend.model.IndexedModel;
|
||||
|
||||
import com.jozufozu.flywheel.core.Formats;
|
||||
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.vector.Vector3f;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class PartBuilder {
|
||||
|
||||
private float sizeU = 64.0F;
|
||||
private float sizeV = 32.0F;
|
||||
|
||||
private TextureAtlasSprite sprite;
|
||||
|
||||
private final List<CuboidBuilder> cuboids = new ArrayList<>();
|
||||
|
||||
public PartBuilder() { }
|
||||
|
||||
public PartBuilder(int sizeU, int sizeV) {
|
||||
this.setTextureSize(sizeU, sizeV);
|
||||
}
|
||||
|
||||
public PartBuilder setTextureSize(int textureWidth, int textureHeight) {
|
||||
this.sizeU = (float)textureWidth;
|
||||
this.sizeV = (float)textureHeight;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PartBuilder sprite(TextureAtlasSprite sprite) {
|
||||
this.sprite = sprite;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CuboidBuilder cuboid() {
|
||||
return new CuboidBuilder(this);
|
||||
}
|
||||
|
||||
public BufferedModel build() {
|
||||
int vertices = 0;
|
||||
|
||||
for (CuboidBuilder cuboid : cuboids) {
|
||||
vertices += cuboid.vertices();
|
||||
}
|
||||
|
||||
VecBuffer buffer = VecBuffer.allocate(vertices * Formats.UNLIT_MODEL.getStride());
|
||||
|
||||
for (CuboidBuilder cuboid : cuboids) {
|
||||
cuboid.buffer(buffer);
|
||||
}
|
||||
|
||||
buffer.rewind();
|
||||
|
||||
return IndexedModel.fromSequentialQuads(Formats.UNLIT_MODEL, buffer.unwrap(), vertices);
|
||||
}
|
||||
|
||||
private PartBuilder addCuboid(CuboidBuilder builder) {
|
||||
cuboids.add(builder);
|
||||
return this;
|
||||
}
|
||||
|
||||
public static class CuboidBuilder {
|
||||
|
||||
TextureAtlasSprite sprite;
|
||||
|
||||
Set<Direction> visibleFaces = EnumSet.allOf(Direction.class);
|
||||
int textureOffsetU;
|
||||
int textureOffsetV;
|
||||
|
||||
float posX1;
|
||||
float posY1;
|
||||
float posZ1;
|
||||
float posX2;
|
||||
float posY2;
|
||||
float posZ2;
|
||||
|
||||
final PartBuilder partBuilder;
|
||||
|
||||
CuboidBuilder(PartBuilder partBuilder) {
|
||||
this.partBuilder = partBuilder;
|
||||
this.sprite = partBuilder.sprite;
|
||||
}
|
||||
|
||||
public CuboidBuilder textureOffset(int u, int v) {
|
||||
this.textureOffsetU = u;
|
||||
this.textureOffsetV = v;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CuboidBuilder start(float x, float y, float z) {
|
||||
this.posX1 = x;
|
||||
this.posY1 = y;
|
||||
this.posZ1 = z;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CuboidBuilder end(float x, float y, float z) {
|
||||
this.posX2 = x;
|
||||
this.posY2 = y;
|
||||
this.posZ2 = z;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CuboidBuilder size(float x, float y, float z) {
|
||||
this.posX2 = posX1 + x;
|
||||
this.posY2 = posY1 + y;
|
||||
this.posZ2 = posZ1 + z;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CuboidBuilder sprite(TextureAtlasSprite sprite) {
|
||||
this.sprite = sprite;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PartBuilder endCuboid() {
|
||||
return partBuilder.addCuboid(this);
|
||||
}
|
||||
|
||||
public int vertices() {
|
||||
return visibleFaces.size() * 4;
|
||||
}
|
||||
|
||||
public void buffer(VecBuffer buffer) {
|
||||
|
||||
float sizeX = posX2 - posX1;
|
||||
float sizeY = posY2 - posY1;
|
||||
float sizeZ = posZ2 - posZ1;
|
||||
|
||||
Vector3f lll = new Vector3f(posX1 / 16f, posY1 / 16f, posZ1 / 16f);
|
||||
Vector3f hll = new Vector3f(posX2 / 16f, posY1 / 16f, posZ1 / 16f);
|
||||
Vector3f hhl = new Vector3f(posX2 / 16f, posY2 / 16f, posZ1 / 16f);
|
||||
Vector3f lhl = new Vector3f(posX1 / 16f, posY2 / 16f, posZ1 / 16f);
|
||||
Vector3f llh = new Vector3f(posX1 / 16f, posY1 / 16f, posZ2 / 16f);
|
||||
Vector3f hlh = new Vector3f(posX2 / 16f, posY1 / 16f, posZ2 / 16f);
|
||||
Vector3f hhh = new Vector3f(posX2 / 16f, posY2 / 16f, posZ2 / 16f);
|
||||
Vector3f lhh = new Vector3f(posX1 / 16f, posY2 / 16f, posZ2 / 16f);
|
||||
float f4 = getU((float)textureOffsetU);
|
||||
float f5 = getU((float)textureOffsetU + sizeZ);
|
||||
float f6 = getU((float)textureOffsetU + sizeZ + sizeX);
|
||||
float f7 = getU((float)textureOffsetU + sizeZ + sizeX + sizeX);
|
||||
float f8 = getU((float)textureOffsetU + sizeZ + sizeX + sizeZ);
|
||||
float f9 = getU((float)textureOffsetU + sizeZ + sizeX + sizeZ + sizeX);
|
||||
float f10 = getV((float)textureOffsetV);
|
||||
float f11 = getV((float)textureOffsetV + sizeZ);
|
||||
float f12 = getV((float)textureOffsetV + sizeZ + sizeY);
|
||||
|
||||
|
||||
float textureWidth = partBuilder.sizeU;
|
||||
float textureHeight = partBuilder.sizeV;
|
||||
quad(buffer, new Vector3f[]{hlh, llh, lll, hll}, f5, f10, f6, f11, textureWidth, textureHeight, Direction.DOWN);
|
||||
quad(buffer, new Vector3f[]{hhl, lhl, lhh, hhh}, f6, f11, f7, f10, textureWidth, textureHeight, Direction.UP);
|
||||
quad(buffer, new Vector3f[]{lll, llh, lhh, lhl}, f4, f11, f5, f12, textureWidth, textureHeight, Direction.WEST);
|
||||
quad(buffer, new Vector3f[]{hll, lll, lhl, hhl}, f5, f11, f6, f12, textureWidth, textureHeight, Direction.NORTH);
|
||||
quad(buffer, new Vector3f[]{hlh, hll, hhl, hhh}, f6, f11, f8, f12, textureWidth, textureHeight, Direction.EAST);
|
||||
quad(buffer, new Vector3f[]{llh, hlh, hhh, lhh}, f8, f11, f9, f12, textureWidth, textureHeight, Direction.SOUTH);
|
||||
}
|
||||
|
||||
|
||||
public void quad(VecBuffer buffer, Vector3f[] vertices, float minU, float minV, float maxU, float maxV, float texWidth, float texHeight, Direction dir) {
|
||||
|
||||
Vector3f normal = dir.getUnitVector();
|
||||
|
||||
buffer.putVec3(vertices[0].getX(), vertices[0].getY(), vertices[0].getZ()).putVec3(nb(normal.getX()), nb(normal.getY()), nb(normal.getZ())).putVec2(maxU, minV);
|
||||
buffer.putVec3(vertices[1].getX(), vertices[1].getY(), vertices[1].getZ()).putVec3(nb(normal.getX()), nb(normal.getY()), nb(normal.getZ())).putVec2(minU, minV);
|
||||
buffer.putVec3(vertices[2].getX(), vertices[2].getY(), vertices[2].getZ()).putVec3(nb(normal.getX()), nb(normal.getY()), nb(normal.getZ())).putVec2(minU, maxV);
|
||||
buffer.putVec3(vertices[3].getX(), vertices[3].getY(), vertices[3].getZ()).putVec3(nb(normal.getX()), nb(normal.getY()), nb(normal.getZ())).putVec2(maxU, maxV);
|
||||
|
||||
}
|
||||
|
||||
public float getU(float u) {
|
||||
if (sprite != null)
|
||||
return sprite.getInterpolatedU(u / 4.);
|
||||
else
|
||||
return u;
|
||||
}
|
||||
|
||||
public float getV(float v) {
|
||||
if (sprite != null)
|
||||
return sprite.getInterpolatedV(v / 4.);
|
||||
else
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
118
src/main/java/com/jozufozu/flywheel/core/model/Readable.java
Normal file
118
src/main/java/com/jozufozu/flywheel/core/model/Readable.java
Normal file
|
@ -0,0 +1,118 @@
|
|||
package com.jozufozu.flywheel.core.model;
|
||||
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.vector.Vector3f;
|
||||
|
||||
public class Readable {
|
||||
public static class ModelBox {
|
||||
private final TexturedQuad[] quads;
|
||||
public final float posX1;
|
||||
public final float posY1;
|
||||
public final float posZ1;
|
||||
public final float posX2;
|
||||
public final float posY2;
|
||||
public final float posZ2;
|
||||
|
||||
public ModelBox(int texOffU, int texOffV, float posX1, float posY1, float posZ1, float sizeX, float sizeY, float sizeZ, float growX, float growY, float growZ, boolean mirror, float texWidth, float texHeight) {
|
||||
this.posX1 = posX1;
|
||||
this.posY1 = posY1;
|
||||
this.posZ1 = posZ1;
|
||||
this.posX2 = posX1 + sizeX;
|
||||
this.posY2 = posY1 + sizeY;
|
||||
this.posZ2 = posZ1 + sizeZ;
|
||||
this.quads = new TexturedQuad[6];
|
||||
float posX2 = posX1 + sizeX;
|
||||
float posY2 = posY1 + sizeY;
|
||||
float posZ2 = posZ1 + sizeZ;
|
||||
posX1 = posX1 - growX;
|
||||
posY1 = posY1 - growY;
|
||||
posZ1 = posZ1 - growZ;
|
||||
posX2 = posX2 + growX;
|
||||
posY2 = posY2 + growY;
|
||||
posZ2 = posZ2 + growZ;
|
||||
if (mirror) {
|
||||
float tmp = posX2;
|
||||
posX2 = posX1;
|
||||
posX1 = tmp;
|
||||
}
|
||||
|
||||
PositionTextureVertex lll = new PositionTextureVertex(posX1, posY1, posZ1, 0.0F, 0.0F);
|
||||
PositionTextureVertex hll = new PositionTextureVertex(posX2, posY1, posZ1, 0.0F, 8.0F);
|
||||
PositionTextureVertex hhl = new PositionTextureVertex(posX2, posY2, posZ1, 8.0F, 8.0F);
|
||||
PositionTextureVertex lhl = new PositionTextureVertex(posX1, posY2, posZ1, 8.0F, 0.0F);
|
||||
PositionTextureVertex llh = new PositionTextureVertex(posX1, posY1, posZ2, 0.0F, 0.0F);
|
||||
PositionTextureVertex hlh = new PositionTextureVertex(posX2, posY1, posZ2, 0.0F, 8.0F);
|
||||
PositionTextureVertex hhh = new PositionTextureVertex(posX2, posY2, posZ2, 8.0F, 8.0F);
|
||||
PositionTextureVertex lhh = new PositionTextureVertex(posX1, posY2, posZ2, 8.0F, 0.0F);
|
||||
float f4 = (float)texOffU;
|
||||
float f5 = (float)texOffU + sizeZ;
|
||||
float f6 = (float)texOffU + sizeZ + sizeX;
|
||||
float f7 = (float)texOffU + sizeZ + sizeX + sizeX;
|
||||
float f8 = (float)texOffU + sizeZ + sizeX + sizeZ;
|
||||
float f9 = (float)texOffU + sizeZ + sizeX + sizeZ + sizeX;
|
||||
float f10 = (float)texOffV;
|
||||
float f11 = (float)texOffV + sizeZ;
|
||||
float f12 = (float)texOffV + sizeZ + sizeY;
|
||||
this.quads[2] = new TexturedQuad(new PositionTextureVertex[]{hlh, llh, lll, hll}, f5, f10, f6, f11, texWidth, texHeight, mirror, Direction.DOWN);
|
||||
this.quads[3] = new TexturedQuad(new PositionTextureVertex[]{hhl, lhl, lhh, hhh}, f6, f11, f7, f10, texWidth, texHeight, mirror, Direction.UP);
|
||||
this.quads[1] = new TexturedQuad(new PositionTextureVertex[]{lll, llh, lhh, lhl}, f4, f11, f5, f12, texWidth, texHeight, mirror, Direction.WEST);
|
||||
this.quads[4] = new TexturedQuad(new PositionTextureVertex[]{hll, lll, lhl, hhl}, f5, f11, f6, f12, texWidth, texHeight, mirror, Direction.NORTH);
|
||||
this.quads[0] = new TexturedQuad(new PositionTextureVertex[]{hlh, hll, hhl, hhh}, f6, f11, f8, f12, texWidth, texHeight, mirror, Direction.EAST);
|
||||
this.quads[5] = new TexturedQuad(new PositionTextureVertex[]{llh, hlh, hhh, lhh}, f8, f11, f9, f12, texWidth, texHeight, mirror, Direction.SOUTH);
|
||||
}
|
||||
}
|
||||
|
||||
public static class PositionTextureVertex {
|
||||
public final float x;
|
||||
public final float y;
|
||||
public final float z;
|
||||
public final float u;
|
||||
public final float v;
|
||||
|
||||
public PositionTextureVertex(float x, float y, float z) {
|
||||
this(x, y, z, 0, 0);
|
||||
}
|
||||
|
||||
public PositionTextureVertex(float x, float y, float z, float u, float v) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.u = u;
|
||||
this.v = v;
|
||||
}
|
||||
|
||||
public PositionTextureVertex setTexturePosition(float u, float v) {
|
||||
return new PositionTextureVertex(x, y, z, u, v);
|
||||
}
|
||||
}
|
||||
|
||||
public static class TexturedQuad {
|
||||
public final PositionTextureVertex[] vertices;
|
||||
public final Vector3f normal;
|
||||
|
||||
public TexturedQuad(PositionTextureVertex[] vertices, float minU, float minV, float maxU, float maxV, float texWidth, float texHeight, boolean p_i225951_8_, Direction p_i225951_9_) {
|
||||
this.vertices = vertices;
|
||||
float w = 0.0F / texWidth;
|
||||
float h = 0.0F / texHeight;
|
||||
vertices[0] = vertices[0].setTexturePosition(maxU / texWidth - w, minV / texHeight + h);
|
||||
vertices[1] = vertices[1].setTexturePosition(minU / texWidth + w, minV / texHeight + h);
|
||||
vertices[2] = vertices[2].setTexturePosition(minU / texWidth + w, maxV / texHeight - h);
|
||||
vertices[3] = vertices[3].setTexturePosition(maxU / texWidth - w, maxV / texHeight - h);
|
||||
if (p_i225951_8_) {
|
||||
int i = vertices.length;
|
||||
|
||||
for(int j = 0; j < i / 2; ++j) {
|
||||
PositionTextureVertex modelrenderer$positiontexturevertex = vertices[j];
|
||||
vertices[j] = vertices[i - 1 - j];
|
||||
vertices[i - 1 - j] = modelrenderer$positiontexturevertex;
|
||||
}
|
||||
}
|
||||
|
||||
this.normal = p_i225951_9_.getUnitVector();
|
||||
if (p_i225951_8_) {
|
||||
this.normal.multiplyComponentwise(-1.0F, 1.0F, 1.0F);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,6 +3,8 @@ package com.jozufozu.flywheel.mixin;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
|
||||
import com.jozufozu.flywheel.backend.instancing.InstancedRenderRegistry;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Group;
|
||||
|
@ -10,7 +12,6 @@ import org.spongepowered.asm.mixin.injection.Redirect;
|
|||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.jozufozu.flywheel.backend.Backend;
|
||||
import com.jozufozu.flywheel.backend.instancing.IInstanceRendered;
|
||||
|
||||
import net.minecraft.client.renderer.WorldRenderer;
|
||||
import net.minecraft.client.world.ClientWorld;
|
||||
|
@ -28,7 +29,9 @@ public class CancelEntityRenderMixin {
|
|||
.canUseInstancing()) {
|
||||
|
||||
ArrayList<Entity> filtered = Lists.newArrayList(entities);
|
||||
filtered.removeIf(entity -> entity instanceof IInstanceRendered && !((IInstanceRendered) entity).shouldRenderNormally());
|
||||
|
||||
InstancedRenderRegistry r = InstancedRenderRegistry.getInstance();
|
||||
filtered.removeIf(r::shouldSkipRender);
|
||||
|
||||
return filtered;
|
||||
}
|
||||
|
@ -42,7 +45,9 @@ public class CancelEntityRenderMixin {
|
|||
.canUseInstancing()) {
|
||||
|
||||
ArrayList<Entity> filtered = Lists.newArrayList(classInheritanceMultiMap);
|
||||
filtered.removeIf(entity -> entity instanceof IInstanceRendered && !((IInstanceRendered) entity).shouldRenderNormally());
|
||||
|
||||
InstancedRenderRegistry r = InstancedRenderRegistry.getInstance();
|
||||
filtered.removeIf(r::shouldSkipRender);
|
||||
|
||||
return filtered.iterator();
|
||||
}
|
||||
|
|
|
@ -2,13 +2,14 @@ package com.jozufozu.flywheel.mixin;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import com.jozufozu.flywheel.backend.instancing.InstancedRenderRegistry;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import com.jozufozu.flywheel.backend.Backend;
|
||||
import com.jozufozu.flywheel.backend.instancing.IInstanceRendered;
|
||||
|
||||
import net.minecraft.client.renderer.chunk.ChunkRenderDispatcher;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
|
@ -31,7 +32,8 @@ public class CancelTileEntityRenderMixin {
|
|||
.canUseInstancing()) {
|
||||
List<TileEntity> tiles = cir.getReturnValue();
|
||||
|
||||
tiles.removeIf(tile -> tile instanceof IInstanceRendered && !((IInstanceRendered) tile).shouldRenderNormally());
|
||||
InstancedRenderRegistry r = InstancedRenderRegistry.getInstance();
|
||||
tiles.removeIf(r::shouldSkipRender);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
8
src/main/java/com/jozufozu/flywheel/util/RenderMath.java
Normal file
8
src/main/java/com/jozufozu/flywheel/util/RenderMath.java
Normal file
|
@ -0,0 +1,8 @@
|
|||
package com.jozufozu.flywheel.util;
|
||||
|
||||
public class RenderMath {
|
||||
|
||||
public static byte nb(float f) {
|
||||
return (byte) (f * 127);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
package com.jozufozu.flywheel.util.transform;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import net.minecraft.util.math.vector.Quaternion;
|
||||
import net.minecraft.util.math.vector.Vector3d;
|
||||
import net.minecraft.util.math.vector.Vector3f;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Deque;
|
||||
import java.util.Stack;
|
||||
import java.util.Vector;
|
||||
|
||||
public class QuaternionTransformStack implements TransformStack {
|
||||
|
||||
private final Deque<Transform> stack;
|
||||
|
||||
public QuaternionTransformStack() {
|
||||
stack = new ArrayDeque<>();
|
||||
stack.add(new Transform());
|
||||
}
|
||||
|
||||
@Override
|
||||
public TransformStack translate(double x, double y, double z) {
|
||||
|
||||
Transform peek = stack.peek();
|
||||
|
||||
double qx = peek.qx;
|
||||
double qy = peek.qy;
|
||||
double qz = peek.qz;
|
||||
double qw = peek.qw;
|
||||
peek.x += qw * x + qy * z - qz * y;
|
||||
peek.y += qw * y - qx * z + qz * x;
|
||||
peek.z += qw * z + qx * y - qy * x;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TransformStack multiply(Quaternion quaternion) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TransformStack push() {
|
||||
stack.push(stack.peek().copy());
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TransformStack pop() {
|
||||
|
||||
if (stack.size() == 1) {
|
||||
stack.peek().loadIdentity();
|
||||
} else {
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
private static class Transform {
|
||||
public double qx;
|
||||
public double qy;
|
||||
public double qz;
|
||||
public double qw;
|
||||
public double x;
|
||||
public double y;
|
||||
public double z;
|
||||
|
||||
public Transform() {
|
||||
qw = 1.0;
|
||||
}
|
||||
|
||||
public void loadIdentity() {
|
||||
x = y = z = 0.0;
|
||||
|
||||
qx = qy = qz = 0.0;
|
||||
qw = 1.0;
|
||||
}
|
||||
|
||||
public Transform copy() {
|
||||
Transform transform = new Transform();
|
||||
|
||||
transform.qx = this.qx;
|
||||
transform.qy = this.qy;
|
||||
transform.qz = this.qz;
|
||||
transform.qw = this.qw;
|
||||
transform.x = this.x;
|
||||
transform.y = this.y;
|
||||
transform.z = this.z;
|
||||
|
||||
return transform;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
package com.jozufozu.flywheel.util.transform;
|
||||
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.vector.Quaternion;
|
||||
import net.minecraft.util.math.vector.Vector3d;
|
||||
import net.minecraft.util.math.vector.Vector3f;
|
||||
import net.minecraft.util.math.vector.Vector3i;
|
||||
|
||||
public interface TransformStack {
|
||||
public static final Vector3d center = new Vector3d(0.5, 0.5, 0.5);
|
||||
|
||||
TransformStack translate(double x, double y, double z);
|
||||
|
||||
TransformStack multiply(Quaternion quaternion);
|
||||
|
||||
TransformStack push();
|
||||
|
||||
TransformStack pop();
|
||||
|
||||
default TransformStack rotate(Direction axis, float radians) {
|
||||
if (radians == 0)
|
||||
return this;
|
||||
return multiply(axis.getUnitVector()
|
||||
.getRadialQuaternion(radians));
|
||||
}
|
||||
|
||||
default TransformStack rotate(double angle, Direction.Axis axis) {
|
||||
Vector3f vec =
|
||||
axis == Direction.Axis.X ? Vector3f.POSITIVE_X : axis == Direction.Axis.Y ? Vector3f.POSITIVE_Y : Vector3f.POSITIVE_Z;
|
||||
return multiply(vec, angle);
|
||||
}
|
||||
|
||||
default TransformStack rotateX(double angle) {
|
||||
return multiply(Vector3f.POSITIVE_X, angle);
|
||||
}
|
||||
|
||||
default TransformStack rotateY(double angle) {
|
||||
return multiply(Vector3f.POSITIVE_Y, angle);
|
||||
}
|
||||
|
||||
default TransformStack rotateZ(double angle) {
|
||||
return multiply(Vector3f.POSITIVE_Z, angle);
|
||||
}
|
||||
|
||||
default TransformStack centre() {
|
||||
return translate(center);
|
||||
}
|
||||
|
||||
default TransformStack unCentre() {
|
||||
return translateBack(center);
|
||||
}
|
||||
|
||||
default TransformStack translate(Vector3i vec) {
|
||||
return translate(vec.getX(), vec.getY(), vec.getZ());
|
||||
}
|
||||
|
||||
default TransformStack translate(Vector3d vec) {
|
||||
return translate(vec.x, vec.y, vec.z);
|
||||
}
|
||||
|
||||
default TransformStack translateBack(Vector3d vec) {
|
||||
return translate(-vec.x, -vec.y, -vec.z);
|
||||
}
|
||||
|
||||
default TransformStack nudge(int id) {
|
||||
long randomBits = (long) id * 31L * 493286711L;
|
||||
randomBits = randomBits * randomBits * 4392167121L + randomBits * 98761L;
|
||||
float xNudge = (((float) (randomBits >> 16 & 7L) + 0.5F) / 8.0F - 0.5F) * 0.004F;
|
||||
float yNudge = (((float) (randomBits >> 20 & 7L) + 0.5F) / 8.0F - 0.5F) * 0.004F;
|
||||
float zNudge = (((float) (randomBits >> 24 & 7L) + 0.5F) / 8.0F - 0.5F) * 0.004F;
|
||||
return translate(xNudge, yNudge, zNudge);
|
||||
}
|
||||
|
||||
default TransformStack multiply(Vector3f axis, double angle) {
|
||||
if (angle == 0)
|
||||
return this;
|
||||
return multiply(axis.getDegreesQuaternion((float) angle));
|
||||
}
|
||||
}
|
136
src/main/java/com/jozufozu/flywheel/vanilla/ChestInstance.java
Normal file
136
src/main/java/com/jozufozu/flywheel/vanilla/ChestInstance.java
Normal file
|
@ -0,0 +1,136 @@
|
|||
package com.jozufozu.flywheel.vanilla;
|
||||
|
||||
import com.jozufozu.flywheel.backend.instancing.IDynamicInstance;
|
||||
import com.jozufozu.flywheel.backend.instancing.MaterialManager;
|
||||
import com.jozufozu.flywheel.backend.instancing.tile.TileEntityInstance;
|
||||
|
||||
import com.jozufozu.flywheel.backend.model.BufferedModel;
|
||||
import com.jozufozu.flywheel.core.Materials;
|
||||
import com.jozufozu.flywheel.core.materials.OrientedData;
|
||||
|
||||
import com.jozufozu.flywheel.core.model.ModelPart;
|
||||
import com.jozufozu.flywheel.util.AnimationTickHolder;
|
||||
|
||||
import it.unimi.dsi.fastutil.floats.Float2FloatFunction;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.ChestBlock;
|
||||
import net.minecraft.client.renderer.Atlases;
|
||||
import net.minecraft.client.renderer.model.RenderMaterial;
|
||||
import net.minecraft.state.properties.ChestType;
|
||||
import net.minecraft.tileentity.ChestTileEntity;
|
||||
import net.minecraft.tileentity.TileEntityMerger;
|
||||
import net.minecraft.util.math.vector.Quaternion;
|
||||
import net.minecraft.util.math.vector.Vector3f;
|
||||
|
||||
import java.util.Calendar;
|
||||
|
||||
public class ChestInstance extends TileEntityInstance<ChestTileEntity> implements IDynamicInstance {
|
||||
|
||||
private final OrientedData body;
|
||||
private final OrientedData lid;
|
||||
|
||||
private final Float2FloatFunction lidProgress;
|
||||
private final RenderMaterial renderMaterial;
|
||||
|
||||
public ChestInstance(MaterialManager<?> materialManager, ChestTileEntity tile) {
|
||||
super(materialManager, tile);
|
||||
|
||||
Block block = blockState.getBlock();
|
||||
|
||||
ChestType chestType = blockState.contains(ChestBlock.TYPE) ? blockState.get(ChestBlock.TYPE) : ChestType.SINGLE;
|
||||
renderMaterial = Atlases.getChestTexture(tile, chestType, isChristmas());
|
||||
|
||||
body = baseInstance()
|
||||
.setPosition(getInstancePosition());
|
||||
lid = lidInstance()
|
||||
.setPosition(getInstancePosition())
|
||||
.nudge(0, 9f/16f, 0);
|
||||
|
||||
if (block instanceof ChestBlock) {
|
||||
|
||||
ChestBlock chestBlock = (ChestBlock) block;
|
||||
|
||||
TileEntityMerger.ICallbackWrapper<? extends ChestTileEntity> wrapper = chestBlock.getBlockEntitySource(blockState, world, getWorldPosition(), true);
|
||||
|
||||
this.lidProgress = wrapper.apply(ChestBlock.getAnimationProgressRetriever(tile));
|
||||
|
||||
|
||||
} else {
|
||||
lidProgress = $ -> 0f;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beginFrame() {
|
||||
float progress = lidProgress.get(AnimationTickHolder.getPartialTicks());
|
||||
|
||||
progress = 1.0F - progress;
|
||||
progress = 1.0F - progress * progress * progress;
|
||||
|
||||
float angleX = -(progress * ((float) Math.PI / 2F));
|
||||
|
||||
Quaternion quaternion = new Quaternion(Vector3f.POSITIVE_X, angleX, false);
|
||||
|
||||
lid.setRotation(quaternion)
|
||||
.setPivot(0, 0, 1f / 16f);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateLight() {
|
||||
relight(getWorldPosition(), body, lid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
body.delete();
|
||||
lid.delete();
|
||||
}
|
||||
|
||||
private OrientedData baseInstance() {
|
||||
|
||||
return materialManager.getMaterial(Materials.ORIENTED, renderMaterial.getAtlasId())
|
||||
.get("base_" + renderMaterial.getTextureId(), this::getBaseModel)
|
||||
.createInstance();
|
||||
}
|
||||
|
||||
private OrientedData lidInstance() {
|
||||
|
||||
return materialManager.getMaterial(Materials.ORIENTED, renderMaterial.getAtlasId())
|
||||
.get("lid_" + renderMaterial.getTextureId(), this::getLidModel)
|
||||
.createInstance();
|
||||
}
|
||||
|
||||
private BufferedModel getBaseModel() {
|
||||
|
||||
return ModelPart.builder(64, 64)
|
||||
.sprite(renderMaterial.getSprite())
|
||||
.cuboid()
|
||||
.textureOffset(0, 19)
|
||||
.start(1, 0, 1)
|
||||
.end(15, 10, 15)
|
||||
.endCuboid()
|
||||
.build();
|
||||
}
|
||||
|
||||
private BufferedModel getLidModel() {
|
||||
|
||||
return ModelPart.builder(64, 64)
|
||||
.sprite(renderMaterial.getSprite())
|
||||
.cuboid()
|
||||
.textureOffset(0, 0)
|
||||
.start(1, 0, 1)
|
||||
.end(15, 5, 15)
|
||||
.endCuboid()
|
||||
.cuboid()
|
||||
.start(7, -2, 15)
|
||||
.size(2, 4, 1)
|
||||
.endCuboid()
|
||||
.build();
|
||||
}
|
||||
|
||||
public static boolean isChristmas() {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
return calendar.get(Calendar.MONTH) + 1 == 12 && calendar.get(Calendar.DATE) >= 24 && calendar.get(Calendar.DATE) <= 26;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package com.jozufozu.flywheel.vanilla;
|
||||
|
||||
import com.jozufozu.flywheel.backend.instancing.InstancedRenderRegistry;
|
||||
|
||||
import net.minecraft.tileentity.TileEntityType;
|
||||
|
||||
public class VanillaInstances {
|
||||
|
||||
public static void init() {
|
||||
InstancedRenderRegistry r = InstancedRenderRegistry.getInstance();
|
||||
|
||||
r.tile(TileEntityType.CHEST)
|
||||
.setSkipRender(true)
|
||||
.factory(ChestInstance::new)
|
||||
.build();
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue