Buffing the Buffers

- Refactored the smart bytebuffers to use one centralized system.
- Unified caches to a single instance
- SuperByteBuffers collect transformations in a matrix rather than performing individual vertex manipulations in subclasses
This commit is contained in:
simibubi 2019-11-23 22:17:37 +01:00
parent e537474c8b
commit 786789c312
40 changed files with 737 additions and 810 deletions

View file

@ -47,7 +47,7 @@ public class ClientEvents {
if (!KineticDebugger.isActive() && KineticTileEntityRenderer.rainbowMode) { if (!KineticDebugger.isActive() && KineticTileEntityRenderer.rainbowMode) {
KineticTileEntityRenderer.rainbowMode = false; KineticTileEntityRenderer.rainbowMode = false;
KineticTileEntityRenderer.invalidateCache(); CreateClient.bufferCache.invalidate();
} }
ScreenOpener.tick(); ScreenOpener.tick();

View file

@ -6,9 +6,11 @@ import java.util.function.Function;
import com.simibubi.create.foundation.block.CTModel; import com.simibubi.create.foundation.block.CTModel;
import com.simibubi.create.foundation.block.IHaveConnectedTextures; import com.simibubi.create.foundation.block.IHaveConnectedTextures;
import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.modules.contraptions.CachedBufferReloader; import com.simibubi.create.foundation.utility.SuperByteBufferCache;
import com.simibubi.create.modules.contraptions.WrenchModel; import com.simibubi.create.modules.contraptions.WrenchModel;
import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer;
import com.simibubi.create.modules.contraptions.receivers.EncasedFanParticleHandler; import com.simibubi.create.modules.contraptions.receivers.EncasedFanParticleHandler;
import com.simibubi.create.modules.contraptions.receivers.constructs.ContraptionRenderer;
import com.simibubi.create.modules.curiosities.deforester.DeforesterModel; import com.simibubi.create.modules.curiosities.deforester.DeforesterModel;
import com.simibubi.create.modules.curiosities.partialWindows.WindowInABlockModel; import com.simibubi.create.modules.curiosities.partialWindows.WindowInABlockModel;
import com.simibubi.create.modules.curiosities.placementHandgun.BuilderGunModel; import com.simibubi.create.modules.curiosities.placementHandgun.BuilderGunModel;
@ -44,6 +46,7 @@ public class CreateClient {
public static SchematicHologram schematicHologram; public static SchematicHologram schematicHologram;
public static SchematicAndQuillHandler schematicAndQuillHandler; public static SchematicAndQuillHandler schematicAndQuillHandler;
public static EncasedFanParticleHandler fanParticles; public static EncasedFanParticleHandler fanParticles;
public static SuperByteBufferCache bufferCache;
public static int renderTicks; public static int renderTicks;
public static ModConfig config; public static ModConfig config;
@ -65,6 +68,10 @@ public class CreateClient {
schematicAndQuillHandler = new SchematicAndQuillHandler(); schematicAndQuillHandler = new SchematicAndQuillHandler();
fanParticles = new EncasedFanParticleHandler(); fanParticles = new EncasedFanParticleHandler();
bufferCache = new SuperByteBufferCache();
bufferCache.registerCompartment(KineticTileEntityRenderer.KINETIC_TILE);
bufferCache.registerCompartment(ContraptionRenderer.CONTRAPTION, 20);
AllKeys.register(); AllKeys.register();
AllContainers.registerScreenFactories(); AllContainers.registerScreenFactories();
AllTileEntities.registerRenderers(); AllTileEntities.registerRenderers();
@ -74,7 +81,7 @@ public class CreateClient {
IResourceManager resourceManager = Minecraft.getInstance().getResourceManager(); IResourceManager resourceManager = Minecraft.getInstance().getResourceManager();
if (resourceManager instanceof IReloadableResourceManager) if (resourceManager instanceof IReloadableResourceManager)
((IReloadableResourceManager) resourceManager).addReloadListener(new CachedBufferReloader()); ((IReloadableResourceManager) resourceManager).addReloadListener(new ResourceReloadHandler());
} }
public static void createConfigs(ModConfig.ModConfigEvent event) { public static void createConfigs(ModConfig.ModConfigEvent event) {

View file

@ -0,0 +1,24 @@
package com.simibubi.create;
import com.simibubi.create.foundation.block.SpriteShifter;
import com.simibubi.create.modules.contraptions.receivers.constructs.MechanicalBearingTileEntityRenderer;
import net.minecraft.client.resources.ReloadListener;
import net.minecraft.profiler.IProfiler;
import net.minecraft.resources.IResourceManager;
public class ResourceReloadHandler extends ReloadListener<String> {
@Override
protected String prepare(IResourceManager resourceManagerIn, IProfiler profilerIn) {
return "";
}
@Override
protected void apply(String splashList, IResourceManager resourceManagerIn, IProfiler profilerIn) {
MechanicalBearingTileEntityRenderer.invalidateCache();
SpriteShifter.reloadUVs();
CreateClient.bufferCache.invalidate();
}
}

View file

@ -5,7 +5,7 @@ import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.Random;
import com.simibubi.create.foundation.block.CTModelTextureHandler.TextureEntry; import com.simibubi.create.foundation.block.SpriteShifter.SpriteShiftEntry;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
@ -24,7 +24,7 @@ import net.minecraftforge.client.model.data.ModelProperty;
public class CTModel extends BakedModelWrapper<IBakedModel> { public class CTModel extends BakedModelWrapper<IBakedModel> {
private static ModelProperty<CTData> CT_PROPERTY = new ModelProperty<>(); private static ModelProperty<CTData> CT_PROPERTY = new ModelProperty<>();
private TextureEntry texture; private SpriteShiftEntry texture;
private class CTData { private class CTData {
int[] textures; int[] textures;
@ -45,7 +45,7 @@ public class CTModel extends BakedModelWrapper<IBakedModel> {
public CTModel(IBakedModel originalModel, String blockId) { public CTModel(IBakedModel originalModel, String blockId) {
super(originalModel); super(originalModel);
texture = CTModelTextureHandler.get(blockId); texture = SpriteShifter.getCT(blockId);
} }
@Override @Override
@ -82,8 +82,8 @@ public class CTModel extends BakedModelWrapper<IBakedModel> {
float uShift = (index % 8) * textureSize; float uShift = (index % 8) * textureSize;
float vShift = (index / 8) * textureSize * 2; float vShift = (index / 8) * textureSize * 2;
uShift = texture.connectedTextures.getInterpolatedU((index % 8) * 2) - texture.originalTexture.getMinU(); uShift = texture.target.getInterpolatedU((index % 8) * 2) - texture.original.getMinU();
vShift = texture.connectedTextures.getInterpolatedV((index / 8) * 2) - texture.originalTexture.getMinV(); vShift = texture.target.getInterpolatedV((index / 8) * 2) - texture.original.getMinV();
BakedQuad newQuad = new BakedQuad(Arrays.copyOf(quad.getVertexData(), quad.getVertexData().length), BakedQuad newQuad = new BakedQuad(Arrays.copyOf(quad.getVertexData(), quad.getVertexData().length),
quad.getTintIndex(), quad.getFace(), quad.getSprite(), quad.shouldApplyDiffuseLighting(), quad.getTintIndex(), quad.getFace(), quad.getSprite(), quad.shouldApplyDiffuseLighting(),

View file

@ -1,46 +0,0 @@
package com.simibubi.create.foundation.block;
import java.util.HashMap;
import java.util.Map;
import com.simibubi.create.Create;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.texture.AtlasTexture;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.util.ResourceLocation;
public class CTModelTextureHandler {
static class TextureEntry {
ResourceLocation originalTextureLocation;
ResourceLocation connectedTextureLocation;
TextureAtlasSprite originalTexture;
TextureAtlasSprite connectedTextures;
void loadTextures() {
AtlasTexture textureMap = Minecraft.getInstance().getTextureMap();
originalTexture = textureMap.getSprite(originalTextureLocation);
connectedTextures = textureMap.getSprite(connectedTextureLocation);
}
}
static Map<String, TextureEntry> textures = new HashMap<>();
public static TextureEntry get(String blockId) {
if (textures.containsKey(blockId))
return textures.get(blockId);
TextureEntry entry = new TextureEntry();
entry.originalTextureLocation = new ResourceLocation(Create.ID, "block/" + blockId);
entry.connectedTextureLocation = new ResourceLocation(Create.ID, "block/connected/" + blockId);
entry.loadTextures();
textures.put(blockId, entry);
return entry;
}
public static void reloadUVs() {
textures.values().forEach(TextureEntry::loadTextures);
}
}

View file

@ -0,0 +1,32 @@
package com.simibubi.create.foundation.block;
import com.simibubi.create.CreateClient;
import com.simibubi.create.foundation.utility.SuperByteBuffer;
import net.minecraft.block.BlockState;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.client.model.animation.TileEntityRendererFast;
public abstract class ColoredOverlayTileEntityRenderer<T extends TileEntity> extends TileEntityRendererFast<T> {
@Override
public void renderTileEntityFast(T te, double x, double y, double z, float partialTicks, int destroyStage,
BufferBuilder buffer) {
SuperByteBuffer render = render(getWorld(), te.getPos(), getOverlayState(te), getColor(te, partialTicks));
buffer.putBulkData(render.translate(x, y, z).build());
}
protected abstract int getColor(T te, float partialTicks);
protected abstract BlockState getOverlayState(T te);
public static SuperByteBuffer render(World world, BlockPos pos, BlockState state, int color) {
int packedLightmapCoords = state.getPackedLightmapCoords(world, pos);
SuperByteBuffer buffer = CreateClient.bufferCache.renderGenericBlockModel(state);
return buffer.color(color).light(packedLightmapCoords);
}
}

View file

@ -0,0 +1,59 @@
package com.simibubi.create.foundation.block;
import java.util.HashMap;
import java.util.Map;
import com.simibubi.create.Create;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.texture.AtlasTexture;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.util.ResourceLocation;
public class SpriteShifter {
public static class SpriteShiftEntry {
ResourceLocation originalTextureLocation;
ResourceLocation targetTextureLocation;
TextureAtlasSprite original;
TextureAtlasSprite target;
void loadTextures() {
AtlasTexture textureMap = Minecraft.getInstance().getTextureMap();
original = textureMap.getSprite(originalTextureLocation);
target = textureMap.getSprite(targetTextureLocation);
}
public TextureAtlasSprite getTarget() {
return target;
}
public TextureAtlasSprite getOriginal() {
return original;
}
}
static Map<String, SpriteShiftEntry> textures = new HashMap<>();
public static SpriteShiftEntry getCT(String blockId) {
return get("block/" + blockId, "block/connected/" + blockId);
}
public static SpriteShiftEntry get(String originalLocation, String targetLocation) {
String key = originalLocation + "->" + targetLocation;
if (textures.containsKey(key))
return textures.get(key);
SpriteShiftEntry entry = new SpriteShiftEntry();
entry.originalTextureLocation = new ResourceLocation(Create.ID, originalLocation);
entry.targetTextureLocation = new ResourceLocation(Create.ID, targetLocation);
entry.loadTextures();
textures.put(key, entry);
return entry;
}
public static void reloadUVs() {
textures.values().forEach(SpriteShiftEntry::loadTextures);
}
}

View file

@ -7,6 +7,7 @@ import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.util.Direction.Axis; import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.MathHelper;
@Deprecated
public abstract class BufferManipulator { public abstract class BufferManipulator {
public static final int FORMAT_LENGTH = DefaultVertexFormats.BLOCK.getSize(); public static final int FORMAT_LENGTH = DefaultVertexFormats.BLOCK.getSize();

View file

@ -1,77 +0,0 @@
package com.simibubi.create.foundation.utility;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.function.Function;
import org.lwjgl.opengl.GL11;
import net.minecraft.block.BlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BlockModelRenderer;
import net.minecraft.client.renderer.BlockRendererDispatcher;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.model.IBakedModel;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.util.math.BlockPos;
import net.minecraftforge.client.model.data.EmptyModelData;
public class ColoredIndicatorRenderer extends BufferManipulator {
protected static Map<BlockState, ColoredIndicatorRenderer> cachedBuffers = new HashMap<>();
public ColoredIndicatorRenderer(ByteBuffer original) {
super(original);
}
public ByteBuffer getTransformed(float xIn, float yIn, float zIn, int color, int packedLightCoords) {
original.rewind();
mutable.rewind();
byte r = (byte) (color >> 16);
byte g = (byte) ((color >> 8) & 0xFF);
byte b = (byte) (color & 0xFF);
byte a = (byte) 255;
for (int vertex = 0; vertex < vertexCount(original); vertex++) {
putColor(mutable, vertex, r, g, b, a);
putPos(mutable, vertex, getX(original, vertex) + xIn, getY(original, vertex) + yIn,
getZ(original, vertex) + zIn);
putLight(mutable, vertex, packedLightCoords);
}
return mutable;
}
public static <R extends ColoredIndicatorRenderer> void cacheIfMissing(BlockState renderedState,
Function<ByteBuffer, R> factory) {
if (!cachedBuffers.containsKey(renderedState)) {
BlockRendererDispatcher dispatcher = Minecraft.getInstance().getBlockRendererDispatcher();
BlockModelRenderer blockRenderer = dispatcher.getBlockModelRenderer();
IBakedModel originalModel = dispatcher.getModelForState(renderedState);
BufferBuilder builder = new BufferBuilder(0);
Random random = new Random();
builder.setTranslation(0, 1, 0);
builder.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK);
blockRenderer.renderModelFlat(Minecraft.getInstance().world, originalModel, renderedState,
BlockPos.ZERO.down(), builder, true, random, 42, EmptyModelData.INSTANCE);
builder.finishDrawing();
cachedBuffers.put(renderedState, factory.apply(builder.getByteBuffer()));
}
}
public static ColoredIndicatorRenderer get(BlockState state) {
cacheIfMissing(state, ColoredIndicatorRenderer::new);
return cachedBuffers.get(state);
}
public static void invalidateCache() {
cachedBuffers.clear();
}
}

View file

@ -0,0 +1,234 @@
package com.simibubi.create.foundation.utility;
import java.nio.ByteBuffer;
import javax.vecmath.Matrix4f;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.GLAllocation;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.util.Direction.Axis;
public class SuperByteBuffer {
public interface IVertexLighter {
public int getPackedLight(float x, float y, float z);
}
public static final int FORMAT_LENGTH = DefaultVertexFormats.BLOCK.getSize();
protected ByteBuffer original;
protected ByteBuffer mutable;
// Vertex Position
private Matrix4f transforms;
private Matrix4f t;
// Vertex Texture Coords
private boolean shouldShiftUV;
private float uShift, vShift;
// Vertex Lighting
private boolean shouldLight;
private IVertexLighter vertexLighter;
private int packedLightCoords;
// Vertex Coloring
private boolean shouldColor;
private int r, g, b, a;
public SuperByteBuffer(ByteBuffer original) {
original.rewind();
this.original = original;
this.mutable = GLAllocation.createDirectByteBuffer(original.capacity());
this.mutable.order(original.order());
this.mutable.limit(original.limit());
mutable.put(this.original);
mutable.rewind();
t = new Matrix4f();
transforms = new Matrix4f();
transforms.setIdentity();
}
public ByteBuffer build() {
original.rewind();
mutable.rewind();
float x, y, z = 0;
float x2, y2, z2 = 0;
Matrix4f t = transforms;
for (int vertex = 0; vertex < vertexCount(original); vertex++) {
x = getX(original, vertex);
y = getY(original, vertex);
z = getZ(original, vertex);
x2 = t.m00 * x + t.m01 * y + t.m02 * z + t.m03;
y2 = t.m10 * x + t.m11 * y + t.m12 * z + t.m13;
z2 = t.m20 * x + t.m21 * y + t.m22 * z + t.m23;
putPos(mutable, vertex, x2, y2, z2);
if (shouldColor) {
byte lumByte = getR(original, vertex);
float lum = (lumByte < 0 ? 255 + lumByte : lumByte) / 256f;
int r2 = (int) (r * lum);
int g2 = (int) (g * lum);
int b2 = (int) (b * lum);
putColor(mutable, vertex, (byte) r2, (byte) g2, (byte) b2, (byte) a);
}
if (shouldShiftUV)
putUV(mutable, vertex, getU(original, vertex) + uShift, getV(original, vertex) + vShift);
if (shouldLight) {
if (vertexLighter != null)
putLight(mutable, vertex, vertexLighter.getPackedLight(x2, y2, z2));
else
putLight(mutable, vertex, packedLightCoords);
}
}
t.setIdentity();
return mutable;
}
public void renderInto(BufferBuilder buffer) {
buffer.putBulkData(build());
}
public SuperByteBuffer translate(double x, double y, double z) {
return translate((float) x, (float) y, (float) z);
}
public SuperByteBuffer translate(float x, float y, float z) {
transforms.m03 += x;
transforms.m13 += y;
transforms.m23 += z;
return this;
}
public SuperByteBuffer rotate(Axis axis, float angle) {
if (angle == 0)
return this;
t.setIdentity();
if (axis == Axis.X)
t.rotX(angle);
else if (axis == Axis.Y)
t.rotY(angle);
else
t.rotZ(angle);
transforms.mul(t, transforms);
return this;
}
public SuperByteBuffer rotateCentered(Axis axis, float angle) {
return translate(-.5f, -.5f, -.5f).rotate(axis, angle).translate(.5f, .5f, .5f);
}
public SuperByteBuffer shiftUV(TextureAtlasSprite from, TextureAtlasSprite to) {
shouldShiftUV = true;
uShift = to.getMinU() - from.getMinU();
vShift = to.getMinV() - from.getMinV();
return this;
}
public SuperByteBuffer shiftUVtoSheet(TextureAtlasSprite from, TextureAtlasSprite to, int sheetX, int sheetY) {
shouldShiftUV = true;
uShift = to.getInterpolatedU(sheetX * 16f / to.getWidth()) - from.getMinU();
vShift = to.getInterpolatedV(sheetY * 16f / to.getHeight()) - from.getMinV();
return this;
}
public SuperByteBuffer light(int packedLightCoords) {
shouldLight = true;
this.packedLightCoords = packedLightCoords;
return this;
}
public SuperByteBuffer light(IVertexLighter lighter) {
shouldLight = true;
vertexLighter = lighter;
return this;
}
public SuperByteBuffer color(int color) {
shouldColor = true;
r = ((color >> 16) & 0xFF);
g = ((color >> 8) & 0xFF);
b = (color & 0xFF);
a = 255;
return this;
}
protected int vertexCount(ByteBuffer buffer) {
return buffer.limit() / FORMAT_LENGTH;
}
protected int getBufferPosition(int vertexIndex) {
return vertexIndex * FORMAT_LENGTH;
}
protected float getX(ByteBuffer buffer, int index) {
return buffer.getFloat(getBufferPosition(index));
}
protected float getY(ByteBuffer buffer, int index) {
return buffer.getFloat(getBufferPosition(index) + 4);
}
protected float getZ(ByteBuffer buffer, int index) {
return buffer.getFloat(getBufferPosition(index) + 8);
}
protected byte getR(ByteBuffer buffer, int index) {
return buffer.get(getBufferPosition(index) + 12);
}
protected byte getG(ByteBuffer buffer, int index) {
return buffer.get(getBufferPosition(index) + 13);
}
protected byte getB(ByteBuffer buffer, int index) {
return buffer.get(getBufferPosition(index) + 14);
}
protected byte getA(ByteBuffer buffer, int index) {
return buffer.get(getBufferPosition(index) + 15);
}
protected float getU(ByteBuffer buffer, int index) {
return buffer.getFloat(getBufferPosition(index) + 16);
}
protected float getV(ByteBuffer buffer, int index) {
return buffer.getFloat(getBufferPosition(index) + 20);
}
protected void putPos(ByteBuffer buffer, int index, float x, float y, float z) {
int pos = getBufferPosition(index);
buffer.putFloat(pos, x);
buffer.putFloat(pos + 4, y);
buffer.putFloat(pos + 8, z);
}
protected void putUV(ByteBuffer buffer, int index, float u, float v) {
int pos = getBufferPosition(index);
buffer.putFloat(pos + 16, u);
buffer.putFloat(pos + 20, v);
}
protected void putLight(ByteBuffer buffer, int index, int packedLight) {
buffer.putInt(getBufferPosition(index) + 24, packedLight);
}
protected void putColor(ByteBuffer buffer, int index, byte r, byte g, byte b, byte a) {
int bufferPosition = getBufferPosition(index);
buffer.put(bufferPosition + 12, r);
buffer.put(bufferPosition + 13, g);
buffer.put(bufferPosition + 14, b);
buffer.put(bufferPosition + 15, a);
}
}

View file

@ -0,0 +1,91 @@
package com.simibubi.create.foundation.utility;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
import org.lwjgl.opengl.GL11;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import net.minecraft.block.BlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BlockModelRenderer;
import net.minecraft.client.renderer.BlockRendererDispatcher;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.model.IBakedModel;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.util.math.BlockPos;
import net.minecraftforge.client.model.data.EmptyModelData;
public class SuperByteBufferCache {
public static class Compartment<T> {
}
public static final Compartment<BlockState> GENERIC_TILE = new Compartment<>();
Map<Compartment<?>, Cache<Object, SuperByteBuffer>> cache;
public SuperByteBufferCache() {
cache = new HashMap<>();
registerCompartment(GENERIC_TILE);
}
public SuperByteBuffer renderGenericBlockModel(BlockState toRender) {
return getGeneric(toRender, () -> standardBlockRender(toRender));
}
public SuperByteBuffer renderBlockState(Compartment<BlockState> compartment, BlockState toRender) {
return get(compartment, toRender, () -> standardBlockRender(toRender));
}
public SuperByteBuffer getGeneric(BlockState key, Supplier<SuperByteBuffer> supplier) {
return get(GENERIC_TILE, key, supplier);
}
public <T> SuperByteBuffer get(Compartment<T> compartment, T key, Supplier<SuperByteBuffer> supplier) {
Cache<Object, SuperByteBuffer> compartmentCache = this.cache.get(compartment);
try {
return compartmentCache.get(key, supplier::get);
} catch (ExecutionException e) {
e.printStackTrace();
return null;
}
}
public void registerCompartment(Compartment<?> instance) {
cache.put(instance, CacheBuilder.newBuilder().build());
}
public void registerCompartment(Compartment<?> instance, long ticksTillExpired) {
cache.put(instance,
CacheBuilder.newBuilder().expireAfterAccess(ticksTillExpired * 50, TimeUnit.MILLISECONDS).build());
}
private SuperByteBuffer standardBlockRender(BlockState renderedState) {
BlockRendererDispatcher dispatcher = Minecraft.getInstance().getBlockRendererDispatcher();
BlockModelRenderer blockRenderer = dispatcher.getBlockModelRenderer();
IBakedModel originalModel = dispatcher.getModelForState(renderedState);
BufferBuilder builder = new BufferBuilder(0);
Random random = new Random();
builder.setTranslation(0, 1, 0);
builder.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK);
blockRenderer.renderModelFlat(Minecraft.getInstance().world, originalModel, renderedState, BlockPos.ZERO.down(),
builder, true, random, 42, EmptyModelData.INSTANCE);
builder.finishDrawing();
return new SuperByteBuffer(builder.getByteBuffer());
}
public void invalidate() {
cache.forEach((comp, cache) -> {
cache.invalidateAll();
});
}
}

View file

@ -1,32 +0,0 @@
package com.simibubi.create.modules.contraptions;
import com.simibubi.create.foundation.block.CTModelTextureHandler;
import com.simibubi.create.foundation.utility.ColoredIndicatorRenderer;
import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer;
import com.simibubi.create.modules.contraptions.receivers.constructs.ContraptionRenderer;
import com.simibubi.create.modules.contraptions.receivers.constructs.MechanicalBearingTileEntityRenderer;
import com.simibubi.create.modules.contraptions.relays.belt.BeltModelAnimator;
import net.minecraft.client.resources.ReloadListener;
import net.minecraft.profiler.IProfiler;
import net.minecraft.resources.IResourceManager;
public class CachedBufferReloader extends ReloadListener<String> {
@Override
protected String prepare(IResourceManager resourceManagerIn, IProfiler profilerIn) {
return "";
}
@Override
protected void apply(String splashList, IResourceManager resourceManagerIn, IProfiler profilerIn) {
KineticTileEntityRenderer.invalidateCache();
ContraptionRenderer.invalidateCache();
MechanicalBearingTileEntityRenderer.invalidateCache();
ColoredIndicatorRenderer.invalidateCache();
CTModelTextureHandler.reloadUVs();
BeltModelAnimator.invalidateCache();
}
}

View file

@ -1,86 +1,38 @@
package com.simibubi.create.modules.contraptions.base; package com.simibubi.create.modules.contraptions.base;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.function.Function;
import org.lwjgl.opengl.GL11;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.CreateClient;
import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.AnimationTickHolder;
import com.simibubi.create.foundation.utility.BufferManipulator; import com.simibubi.create.foundation.utility.SuperByteBuffer;
import com.simibubi.create.foundation.utility.SuperByteBufferCache.Compartment;
import com.simibubi.create.modules.contraptions.KineticDebugger; import com.simibubi.create.modules.contraptions.KineticDebugger;
import com.simibubi.create.modules.logistics.management.base.LogisticalActorTileEntity; import com.simibubi.create.modules.logistics.management.base.LogisticalActorTileEntity;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BlockModelRenderer;
import net.minecraft.client.renderer.BlockRendererDispatcher;
import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.model.IBakedModel;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction.Axis; import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.model.animation.TileEntityRendererFast; import net.minecraftforge.client.model.animation.TileEntityRendererFast;
import net.minecraftforge.client.model.data.EmptyModelData;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber; import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
@EventBusSubscriber(value = Dist.CLIENT) @EventBusSubscriber(value = Dist.CLIENT)
public class KineticTileEntityRenderer extends TileEntityRendererFast<KineticTileEntity> { public class KineticTileEntityRenderer extends TileEntityRendererFast<KineticTileEntity> {
public static Map<BlockState, BufferManipulator> cachedBuffers; public static final Compartment<BlockState> KINETIC_TILE = new Compartment<>();
public static boolean rainbowMode = false; public static boolean rainbowMode = false;
public static class BlockModelSpinner extends BufferManipulator {
public BlockModelSpinner(ByteBuffer original) {
super(original);
}
public ByteBuffer getTransformed(float xIn, float yIn, float zIn, float angle, Axis axis,
int packedLightCoords) {
original.rewind();
mutable.rewind();
float cos = MathHelper.cos(angle);
float sin = MathHelper.sin(angle);
float x, y, z = 0;
for (int vertex = 0; vertex < vertexCount(original); vertex++) {
x = getX(original, vertex) - .5f;
y = getY(original, vertex) - .5f;
z = getZ(original, vertex) - .5f;
putPos(mutable, vertex, rotateX(x, y, z, sin, cos, axis) + .5f + xIn,
rotateY(x, y, z, sin, cos, axis) + .5f + yIn, rotateZ(x, y, z, sin, cos, axis) + .5f + zIn);
putLight(mutable, vertex, packedLightCoords);
}
return mutable;
}
}
public KineticTileEntityRenderer() {
cachedBuffers = new HashMap<>();
}
@Override @Override
public void renderTileEntityFast(KineticTileEntity te, double x, double y, double z, float partialTicks, public void renderTileEntityFast(KineticTileEntity te, double x, double y, double z, float partialTicks,
int destroyStage, BufferBuilder buffer) { int destroyStage, BufferBuilder buffer) {
renderRotatingKineticBlock(te, getWorld(), getRenderedBlockState(te), x, y, z, buffer);
}
final BlockState state = getRenderedBlockState(te); public static void renderRotatingKineticBlock(KineticTileEntity te, World world, BlockState renderedState, double x,
cacheIfMissing(state, getWorld(), BlockModelSpinner::new); double y, double z, BufferBuilder buffer) {
SuperByteBuffer superByteBuffer = CreateClient.bufferCache.renderBlockState(KINETIC_TILE, renderedState);
final BlockPos pos = te.getPos(); buffer.putBulkData(standardKineticRotationTransform(superByteBuffer, te, world).translate(x, y, z).build());
Axis axis = ((IRotate) te.getBlockState().getBlock()).getRotationAxis(te.getBlockState());
float angle = getAngleForTe(te, pos, axis);
renderFromCache(buffer, state, getWorld(), (float) x, (float) y, (float) z, pos, axis, angle);
} }
public static float getAngleForTe(KineticTileEntity te, final BlockPos pos, Axis axis) { public static float getAngleForTe(KineticTileEntity te, final BlockPos pos, Axis axis) {
@ -90,45 +42,26 @@ public class KineticTileEntityRenderer extends TileEntityRendererFast<KineticTil
return angle; return angle;
} }
public static void renderFromCache(BufferBuilder buffer, BlockState state, World world, float x, float y, public static SuperByteBuffer standardKineticRotationTransform(SuperByteBuffer buffer, KineticTileEntity te,
float z, BlockPos pos, Axis axis, float angle) { World world) {
int packedLightmapCoords = state.getPackedLightmapCoords(world, pos); final BlockPos pos = te.getPos();
ByteBuffer transformed = ((BlockModelSpinner) getBuffer(state)).getTransformed(x, y, z, angle, axis, Axis axis = ((IRotate) te.getBlockState().getBlock()).getRotationAxis(te.getBlockState());
packedLightmapCoords); return kineticRotationTransform(buffer, te, axis, getAngleForTe(te, pos, axis), world);
}
public static SuperByteBuffer kineticRotationTransform(SuperByteBuffer buffer, KineticTileEntity te, Axis axis,
float angle, World world) {
int packedLightmapCoords = te.getBlockState().getPackedLightmapCoords(world, te.getPos());
buffer.light(packedLightmapCoords);
buffer.rotateCentered(axis, angle);
if (KineticDebugger.isActive()) { if (KineticDebugger.isActive()) {
rainbowMode = true; rainbowMode = true;
TileEntity tileEntity = world.getTileEntity(pos); if (te.hasNetwork())
if (tileEntity instanceof KineticTileEntity && ((KineticTileEntity) tileEntity).hasNetwork()) { buffer.color(LogisticalActorTileEntity.colorFromUUID(te.getNetworkID()));
int color = LogisticalActorTileEntity.colorFromUUID(((KineticTileEntity) tileEntity).getNetworkID());
BufferManipulator.recolorBuffer(transformed, color);
}
} }
buffer.putBulkData(transformed); return buffer;
}
public static BufferManipulator getBuffer(BlockState state) {
return cachedBuffers.get(state);
}
public static void cacheIfMissing(final BlockState state, World world,
Function<ByteBuffer, BufferManipulator> factory) {
if (!cachedBuffers.containsKey(state)) {
BlockRendererDispatcher dispatcher = Minecraft.getInstance().getBlockRendererDispatcher();
BlockModelRenderer blockRenderer = dispatcher.getBlockModelRenderer();
IBakedModel originalModel = dispatcher.getModelForState(state);
BufferBuilder builder = new BufferBuilder(0);
Random random = new Random();
builder.setTranslation(0, 1, 0);
builder.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK);
blockRenderer.renderModelFlat(world, originalModel, state, BlockPos.ZERO.down(), builder, true, random, 42,
EmptyModelData.INSTANCE);
builder.finishDrawing();
cachedBuffers.put(state, factory.apply(builder.getByteBuffer()));
}
} }
protected static float getRotationOffsetForPosition(KineticTileEntity te, final BlockPos pos, final Axis axis) { protected static float getRotationOffsetForPosition(KineticTileEntity te, final BlockPos pos, final Axis axis) {
@ -145,9 +78,4 @@ public class KineticTileEntityRenderer extends TileEntityRendererFast<KineticTil
return te.getBlockState(); return te.getBlockState();
} }
public static void invalidateCache() {
if (cachedBuffers != null)
cachedBuffers.clear();
}
} }

View file

@ -1,10 +1,10 @@
package com.simibubi.create.modules.contraptions.receivers; package com.simibubi.create.modules.contraptions.receivers;
import java.nio.ByteBuffer;
import java.util.List; import java.util.List;
import com.simibubi.create.foundation.block.IRenderUtilityBlock; import com.simibubi.create.foundation.block.IRenderUtilityBlock;
import com.simibubi.create.foundation.block.IWithTileEntity; import com.simibubi.create.foundation.block.IWithTileEntity;
import com.simibubi.create.foundation.utility.SuperByteBuffer;
import com.simibubi.create.foundation.utility.VoxelShapers; import com.simibubi.create.foundation.utility.VoxelShapers;
import com.simibubi.create.modules.contraptions.base.DirectionalKineticBlock; import com.simibubi.create.modules.contraptions.base.DirectionalKineticBlock;
import com.simibubi.create.modules.contraptions.receivers.constructs.IHaveMovementBehavior; import com.simibubi.create.modules.contraptions.receivers.constructs.IHaveMovementBehavior;
@ -80,8 +80,8 @@ public class DrillBlock extends DirectionalKineticBlock
@Override @Override
@OnlyIn(value = Dist.CLIENT) @OnlyIn(value = Dist.CLIENT)
public ByteBuffer renderInConstruct(MovementContext context) { public SuperByteBuffer renderInContraption(MovementContext context) {
return DrillTileEntityRenderer.renderInConstruct(context); return DrillTileEntityRenderer.renderInContraption(context);
} }
@Override @Override

View file

@ -2,20 +2,17 @@ package com.simibubi.create.modules.contraptions.receivers;
import static net.minecraft.state.properties.BlockStateProperties.FACING; import static net.minecraft.state.properties.BlockStateProperties.FACING;
import java.nio.ByteBuffer;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.CreateClient;
import com.simibubi.create.foundation.utility.AnimationTickHolder;
import com.simibubi.create.foundation.utility.SuperByteBuffer;
import com.simibubi.create.modules.contraptions.base.IRotate; import com.simibubi.create.modules.contraptions.base.IRotate;
import com.simibubi.create.modules.contraptions.base.KineticTileEntity; import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer;
import com.simibubi.create.modules.contraptions.receivers.constructs.IHaveMovementBehavior.MovementContext; import com.simibubi.create.modules.contraptions.receivers.constructs.IHaveMovementBehavior.MovementContext;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.util.Direction.Axis; import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.client.model.animation.Animation;
public class DrillTileEntityRenderer extends KineticTileEntityRenderer { public class DrillTileEntityRenderer extends KineticTileEntityRenderer {
@ -28,21 +25,16 @@ public class DrillTileEntityRenderer extends KineticTileEntityRenderer {
return AllBlocks.DRILL_HEAD.get().getDefaultState().with(FACING, state.get(FACING)); return AllBlocks.DRILL_HEAD.get().getDefaultState().with(FACING, state.get(FACING));
} }
public static ByteBuffer renderInConstruct(MovementContext context) { public static SuperByteBuffer renderInContraption(MovementContext context) {
World world = context.world;
BlockState state = context.state; BlockState state = context.state;
BlockPos pos = context.currentGridPos; SuperByteBuffer buffer = CreateClient.bufferCache.renderBlockState(KINETIC_TILE, getRenderedBlockState(state));
final BlockState renderedState = getRenderedBlockState(state);
cacheIfMissing(renderedState, world, BlockModelSpinner::new);
float speed = (float) (context.getMovementDirection() == state.get(FACING) ? context.getAnimationSpeed() : 0); float speed = (float) (context.getMovementDirection() == state.get(FACING) ? context.getAnimationSpeed() : 0);
Axis axis = ((IRotate) state.getBlock()).getRotationAxis(state); Axis axis = ((IRotate) state.getBlock()).getRotationAxis(state);
float time = Animation.getWorldTime(Minecraft.getInstance().world, float time = AnimationTickHolder.getRenderTick();
Minecraft.getInstance().getRenderPartialTicks());
float angle = (float) (((time * speed) % 360) / 180 * (float) Math.PI); float angle = (float) (((time * speed) % 360) / 180 * (float) Math.PI);
return ((BlockModelSpinner) getBuffer(renderedState)).getTransformed(0, 0, 0, angle, axis,
world.getCombinedLight(pos, 0)); return buffer.rotateCentered(axis, angle);
} }
} }

View file

@ -1,10 +1,10 @@
package com.simibubi.create.modules.contraptions.receivers; package com.simibubi.create.modules.contraptions.receivers;
import java.nio.ByteBuffer;
import java.util.List; import java.util.List;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.block.IRenderUtilityBlock; import com.simibubi.create.foundation.block.IRenderUtilityBlock;
import com.simibubi.create.foundation.utility.SuperByteBuffer;
import com.simibubi.create.foundation.utility.VoxelShaper; import com.simibubi.create.foundation.utility.VoxelShaper;
import com.simibubi.create.modules.contraptions.receivers.constructs.IHaveMovementBehavior; import com.simibubi.create.modules.contraptions.receivers.constructs.IHaveMovementBehavior;
@ -74,8 +74,8 @@ public class HarvesterBlock extends HorizontalBlock implements IHaveMovementBeha
@Override @Override
@OnlyIn(value = Dist.CLIENT) @OnlyIn(value = Dist.CLIENT)
public ByteBuffer renderInConstruct(MovementContext context) { public SuperByteBuffer renderInContraption(MovementContext context) {
return HarvesterTileEntityRenderer.renderInConstruct(context); return HarvesterTileEntityRenderer.renderInContraption(context);
} }
@Override @Override

View file

@ -1,99 +1,64 @@
package com.simibubi.create.modules.contraptions.receivers; package com.simibubi.create.modules.contraptions.receivers;
import static com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer.KINETIC_TILE;
import static net.minecraft.state.properties.BlockStateProperties.HORIZONTAL_FACING; import static net.minecraft.state.properties.BlockStateProperties.HORIZONTAL_FACING;
import java.nio.ByteBuffer;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.utility.BufferManipulator; import com.simibubi.create.CreateClient;
import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.foundation.utility.AnimationTickHolder;
import com.simibubi.create.foundation.utility.SuperByteBuffer;
import com.simibubi.create.modules.contraptions.receivers.constructs.IHaveMovementBehavior.MovementContext; import com.simibubi.create.modules.contraptions.receivers.constructs.IHaveMovementBehavior.MovementContext;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.tileentity.TileEntityRenderer; import net.minecraft.client.renderer.tileentity.TileEntityRenderer;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis; import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.client.model.animation.Animation;
public class HarvesterTileEntityRenderer extends TileEntityRenderer<HarvesterTileEntity> { public class HarvesterTileEntityRenderer extends TileEntityRenderer<HarvesterTileEntity> {
protected static class HarvesterRenderer extends BufferManipulator { @Override
public void renderTileEntityFast(HarvesterTileEntity te, double x, double y, double z, float partialTicks,
public HarvesterRenderer(ByteBuffer original) { int destroyStage, BufferBuilder buffer) {
super(original); SuperByteBuffer superBuffer = renderHead(getWorld(), te.getPos(), te.getBlockState(), 0);
} superBuffer.translate(x, y, z).renderInto(buffer);
public ByteBuffer getTransformed(float xIn, float yIn, float zIn, float angle, Direction facing,
int packedLightCoords) {
original.rewind();
mutable.rewind();
float cos = MathHelper.cos(angle);
float sin = MathHelper.sin(angle);
float x, y, z = 0;
Axis axis = facing.rotateYCCW().getAxis();
int axisDirection = -facing.getAxisDirection().getOffset();
float originOffset = 1 / 16f;
float xOffset = axis == Axis.X ? 0 : originOffset * axisDirection;
float zOffset = axis == Axis.Z ? 0 : originOffset * axisDirection;
for (int vertex = 0; vertex < vertexCount(original); vertex++) {
x = getX(original, vertex) - .5f + xOffset;
y = getY(original, vertex) - .5f + 2 * originOffset;
z = getZ(original, vertex) - .5f + zOffset;
putPos(mutable, vertex, rotateX(x, y, z, sin, cos, axis) + .5f - xOffset + xIn,
rotateY(x, y, z, sin, cos, axis) + .5f - 2 * originOffset + yIn,
rotateZ(x, y, z, sin, cos, axis) + .5f - zOffset + zIn);
putLight(mutable, vertex, packedLightCoords);
}
return mutable;
}
} }
public static ByteBuffer renderInConstruct(MovementContext context) { public static SuperByteBuffer renderInContraption(MovementContext context) {
World world = context.world;
BlockState state = context.state; BlockState state = context.state;
BlockPos pos = context.currentGridPos;
Direction facing = context.getMovementDirection(); Direction facing = context.getMovementDirection();
float speed = (float) (facing == state.get(HORIZONTAL_FACING) float speed = (float) (facing == state.get(HORIZONTAL_FACING)
? context.getAnimationSpeed() * facing.getAxisDirection().getOffset() ? context.getAnimationSpeed() * facing.getAxisDirection().getOffset()
: 0); : 0);
if (facing.getAxis() == Axis.X) if (facing.getAxis() == Axis.X)
speed = -speed; speed = -speed;
float time = AnimationTickHolder.getRenderTick();
float time = Animation.getWorldTime(Minecraft.getInstance().world,
Minecraft.getInstance().getRenderPartialTicks());
float angle = (float) (((time * speed) % 360) / 180 * (float) Math.PI); float angle = (float) (((time * speed) % 360) / 180 * (float) Math.PI);
return getVertexData(world, state, pos, 0, 0, 0, angle);
return renderHead(context.world, BlockPos.ZERO, state, angle);
} }
@Override public static SuperByteBuffer renderHead(World world, BlockPos pos, BlockState state, float angle) {
public void renderTileEntityFast(HarvesterTileEntity te, double x, double y, double z, float partialTicks,
int destroyStage, BufferBuilder buffer) {
buffer.putBulkData(getVertexData(te.getWorld(), te.getBlockState(), te.getPos(), x, y, z, 0));
}
public static ByteBuffer getVertexData(World world, BlockState state, BlockPos pos, double x, double y, double z,
float angle) {
if (!AllBlocks.HARVESTER.typeOf(state))
return ByteBuffer.wrap(new byte[] {});
BlockState renderedState = AllBlocks.HARVESTER_BLADE.get().getDefaultState().with(HORIZONTAL_FACING, BlockState renderedState = AllBlocks.HARVESTER_BLADE.get().getDefaultState().with(HORIZONTAL_FACING,
state.get(HORIZONTAL_FACING)); state.get(HORIZONTAL_FACING));
SuperByteBuffer buffer = CreateClient.bufferCache.renderBlockState(KINETIC_TILE, renderedState);
KineticTileEntityRenderer.cacheIfMissing(renderedState, world, HarvesterRenderer::new); int lightMapCoords = state.getPackedLightmapCoords(world, pos);
HarvesterRenderer renderer = (HarvesterRenderer) KineticTileEntityRenderer.getBuffer(renderedState); Direction facing = state.get(HORIZONTAL_FACING);
ByteBuffer byteBuffer = renderer.getTransformed((float) x, (float) y, (float) z, angle, Axis axis = facing.rotateYCCW().getAxis();
state.get(HORIZONTAL_FACING), state.getPackedLightmapCoords(world, pos)); int axisDirection = -facing.getAxisDirection().getOffset();
return byteBuffer; float originOffset = 1 / 16f;
float xOffset = axis == Axis.X ? 0 : originOffset * axisDirection;
float zOffset = axis == Axis.Z ? 0 : originOffset * axisDirection;
buffer.translate(xOffset, 2 * originOffset, zOffset);
buffer.rotateCentered(axis, angle);
buffer.translate(-xOffset, -2 * originOffset, -zOffset);
buffer.light(lightMapCoords);
return buffer;
} }
} }

View file

@ -66,24 +66,23 @@ public class MechanicalMixerTileEntity extends KineticTileEntity {
public float getRenderedHeadOffset(float partialTicks) { public float getRenderedHeadOffset(float partialTicks) {
int localTick = 0; int localTick = 0;
float offset = 0;
if (running) { if (running) {
if (runningTicks < 20) { if (runningTicks < 20) {
localTick = runningTicks; localTick = runningTicks;
float num = (localTick + partialTicks) / 20f; float num = (localTick + partialTicks) / 20f;
num = ((2 - MathHelper.cos((float) (num * Math.PI))) / 2); num = ((2 - MathHelper.cos((float) (num * Math.PI))) / 2);
return num - .5f; offset = num - .5f;
} } else if (runningTicks <= 20) {
if (runningTicks <= 20) { offset = 1;
return 1; } else if (runningTicks > 20) {
}
if (runningTicks > 20) {
localTick = 40 - runningTicks; localTick = 40 - runningTicks;
float num = (localTick - partialTicks) / 20f; float num = (localTick - partialTicks) / 20f;
num = ((2 - MathHelper.cos((float) (num * Math.PI))) / 2); num = ((2 - MathHelper.cos((float) (num * Math.PI))) / 2);
return num - .5f; offset = num - .5f;
} }
} }
return 0; return offset + 7 / 16f;
} }
public float getRenderedHeadRotationSpeed(float partialTicks) { public float getRenderedHeadRotationSpeed(float partialTicks) {

View file

@ -1,10 +1,11 @@
package com.simibubi.create.modules.contraptions.receivers; package com.simibubi.create.modules.contraptions.receivers;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.CreateClient;
import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.AnimationTickHolder;
import com.simibubi.create.foundation.utility.SuperByteBuffer;
import com.simibubi.create.modules.contraptions.base.KineticTileEntity; import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer;
import com.simibubi.create.modules.contraptions.receivers.MechanicalPressTileEntityRenderer.HeadTranslator;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.BufferBuilder;
@ -19,22 +20,23 @@ public class MechanicalMixerTileEntityRenderer extends KineticTileEntityRenderer
int destroyStage, BufferBuilder buffer) { int destroyStage, BufferBuilder buffer) {
super.renderTileEntityFast(te, x, y, z, partialTicks, destroyStage, buffer); super.renderTileEntityFast(te, x, y, z, partialTicks, destroyStage, buffer);
final BlockState poleState = AllBlocks.MECHANICAL_MIXER_POLE.get().getDefaultState(); MechanicalMixerTileEntity mixer = (MechanicalMixerTileEntity) te;
final BlockState headState = AllBlocks.MECHANICAL_MIXER_HEAD.get().getDefaultState(); BlockState poleState = AllBlocks.MECHANICAL_MIXER_POLE.get().getDefaultState();
cacheIfMissing(poleState, getWorld(), HeadTranslator::new); BlockState headState = AllBlocks.MECHANICAL_MIXER_HEAD.get().getDefaultState();
cacheIfMissing(headState, getWorld(), HeadTranslator::new); BlockPos pos = te.getPos();
final BlockPos pos = te.getPos();
int packedLightmapCoords = poleState.getPackedLightmapCoords(getWorld(), pos); int packedLightmapCoords = poleState.getPackedLightmapCoords(getWorld(), pos);
float speed = ((MechanicalMixerTileEntity) te).getRenderedHeadRotationSpeed(partialTicks); float renderedHeadOffset = mixer.getRenderedHeadOffset(partialTicks);
float renderedHeadOffset = ((MechanicalMixerTileEntity) te).getRenderedHeadOffset(partialTicks) + 7 / 16f; float speed = mixer.getRenderedHeadRotationSpeed(partialTicks);
float time = AnimationTickHolder.getRenderTick(); float time = AnimationTickHolder.getRenderTick();
float angle = (float) (((time * speed * 2) % 360) / 180 * (float) Math.PI); float angle = (float) (((time * speed * 2) % 360) / 180 * (float) Math.PI);
buffer.putBulkData(((HeadTranslator) cachedBuffers.get(poleState)).getTransformed((float) x, (float) y, SuperByteBuffer poleRender = CreateClient.bufferCache.renderGenericBlockModel(poleState);
(float) z, renderedHeadOffset, packedLightmapCoords)); poleRender.translate(x, y - renderedHeadOffset, z).light(packedLightmapCoords).renderInto(buffer);
buffer.putBulkData(((HeadTranslator) cachedBuffers.get(headState)).getTransformedRotated((float) x, (float) y,
(float) z, renderedHeadOffset, angle, packedLightmapCoords)); SuperByteBuffer headRender = CreateClient.bufferCache.renderGenericBlockModel(headState);
headRender.rotateCentered(Axis.Y, angle).translate(x, y - renderedHeadOffset, z).light(packedLightmapCoords)
.renderInto(buffer);
} }
@Override @Override

View file

@ -1,89 +1,43 @@
package com.simibubi.create.modules.contraptions.receivers; package com.simibubi.create.modules.contraptions.receivers;
import java.nio.ByteBuffer; import static net.minecraft.state.properties.BlockStateProperties.HORIZONTAL_FACING;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.utility.BufferManipulator; import com.simibubi.create.CreateClient;
import com.simibubi.create.foundation.utility.SuperByteBuffer;
import com.simibubi.create.modules.contraptions.base.KineticTileEntity; import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
public class MechanicalPressTileEntityRenderer extends KineticTileEntityRenderer { public class MechanicalPressTileEntityRenderer extends KineticTileEntityRenderer {
public static class HeadTranslator extends BufferManipulator {
public HeadTranslator(ByteBuffer original) {
super(original);
}
public ByteBuffer getTransformed(float xIn, float yIn, float zIn, float pushDistance, int packedLightCoords) {
original.rewind();
mutable.rewind();
for (int vertex = 0; vertex < vertexCount(original); vertex++) {
putPos(mutable, vertex, getX(original, vertex) + xIn, getY(original, vertex) + yIn - pushDistance,
getZ(original, vertex) + zIn);
putLight(mutable, vertex, packedLightCoords);
}
return mutable;
}
public ByteBuffer getTransformedRotated(float xIn, float yIn, float zIn, float pushDistance, float angle,
int packedLightCoords) {
original.rewind();
mutable.rewind();
float cos = MathHelper.cos(angle);
float sin = MathHelper.sin(angle);
for (int vertex = 0; vertex < vertexCount(original); vertex++) {
float x = getX(original, vertex) - .5f;
float y = getY(original, vertex) + yIn - pushDistance;
float z = getZ(original, vertex) - .5f;
float x2 = x;
x = rotateX(x, y, z, sin, cos, Axis.Y) + .5f + xIn;
z = rotateZ(x2, y, z, sin, cos, Axis.Y) + .5f + zIn;
putPos(mutable, vertex, x, y, z);
putLight(mutable, vertex, packedLightCoords);
}
return mutable;
}
}
@Override @Override
public void renderTileEntityFast(KineticTileEntity te, double x, double y, double z, float partialTicks, public void renderTileEntityFast(KineticTileEntity te, double x, double y, double z, float partialTicks,
int destroyStage, BufferBuilder buffer) { int destroyStage, BufferBuilder buffer) {
super.renderTileEntityFast(te, x, y, z, partialTicks, destroyStage, buffer); super.renderTileEntityFast(te, x, y, z, partialTicks, destroyStage, buffer);
final BlockState state = getRenderedHeadBlockState(te); BlockState state = getRenderedHeadBlockState(te);
cacheIfMissing(state, getWorld(), HeadTranslator::new); BlockPos pos = te.getPos();
final BlockPos pos = te.getPos();
int packedLightmapCoords = state.getPackedLightmapCoords(getWorld(), pos); int packedLightmapCoords = state.getPackedLightmapCoords(getWorld(), pos);
buffer.putBulkData(((HeadTranslator) cachedBuffers.get(state)).getTransformed((float) x, (float) y, (float) z, float renderedHeadOffset = ((MechanicalPressTileEntity) te).getRenderedHeadOffset(partialTicks);
((MechanicalPressTileEntity) te).getRenderedHeadOffset(partialTicks), packedLightmapCoords));
SuperByteBuffer headRender = CreateClient.bufferCache.renderGenericBlockModel(state);
headRender.translate(x, y - renderedHeadOffset, z).light(packedLightmapCoords).renderInto(buffer);
} }
@Override @Override
protected BlockState getRenderedBlockState(KineticTileEntity te) { protected BlockState getRenderedBlockState(KineticTileEntity te) {
return AllBlocks.SHAFT.get().getDefaultState().with(BlockStateProperties.AXIS, return AllBlocks.SHAFT.get().getDefaultState().with(BlockStateProperties.AXIS,
te.getBlockState().get(BlockStateProperties.HORIZONTAL_FACING).getAxis()); te.getBlockState().get(HORIZONTAL_FACING).getAxis());
} }
protected BlockState getRenderedHeadBlockState(KineticTileEntity te) { protected BlockState getRenderedHeadBlockState(KineticTileEntity te) {
return AllBlocks.MECHANICAL_PRESS_HEAD.get().getDefaultState().with(BlockStateProperties.HORIZONTAL_FACING, return AllBlocks.MECHANICAL_PRESS_HEAD.get().getDefaultState().with(HORIZONTAL_FACING,
te.getBlockState().get(BlockStateProperties.HORIZONTAL_FACING)); te.getBlockState().get(HORIZONTAL_FACING));
} }
} }

View file

@ -9,7 +9,6 @@ import com.simibubi.create.foundation.utility.TessellatorHelper;
import com.simibubi.create.modules.contraptions.base.IRotate; import com.simibubi.create.modules.contraptions.base.IRotate;
import com.simibubi.create.modules.contraptions.base.KineticTileEntity; import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer;
import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer.BlockModelSpinner;
import com.simibubi.create.modules.logistics.block.FilteredTileEntityRenderer; import com.simibubi.create.modules.logistics.block.FilteredTileEntityRenderer;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
@ -22,23 +21,27 @@ import net.minecraft.client.renderer.tileentity.TileEntityRenderer;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.MathHelper;
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
public class SawTileEntityRenderer extends TileEntityRenderer<SawTileEntity> { public class SawTileEntityRenderer extends TileEntityRenderer<SawTileEntity> {
FilteredTileEntityRenderer filterRenderer;
public SawTileEntityRenderer() {
filterRenderer = new FilteredTileEntityRenderer();
}
@Override @Override
public void render(SawTileEntity te, double x, double y, double z, float partialTicks, int destroyStage) { public void render(SawTileEntity te, double x, double y, double z, float partialTicks, int destroyStage) {
super.render(te, x, y, z, partialTicks, destroyStage); renderItems(te, x, y, z, partialTicks);
FilteredTileEntityRenderer.render(te, x, y, z, partialTicks, destroyStage);
renderShaft(te, x, y, z);
}
protected void renderShaft(SawTileEntity te, double x, double y, double z) {
TessellatorHelper.prepareFastRender();
TessellatorHelper.begin(DefaultVertexFormats.BLOCK);
KineticTileEntityRenderer.renderRotatingKineticBlock(te, getWorld(), getRenderedBlockState(te), x, y, z,
Tessellator.getInstance().getBuffer());
TessellatorHelper.draw();
}
protected void renderItems(SawTileEntity te, double x, double y, double z, float partialTicks) {
boolean processingMode = te.getBlockState().get(SawBlock.FACING) == Direction.UP; boolean processingMode = te.getBlockState().get(SawBlock.FACING) == Direction.UP;
if (processingMode && !te.inventory.isEmpty()) { if (processingMode && !te.inventory.isEmpty()) {
boolean alongZ = !te.getBlockState().get(SawBlock.AXIS_ALONG_FIRST_COORDINATE); boolean alongZ = !te.getBlockState().get(SawBlock.AXIS_ALONG_FIRST_COORDINATE);
@ -69,22 +72,6 @@ public class SawTileEntityRenderer extends TileEntityRenderer<SawTileEntity> {
itemRenderer.renderItem(stack, ItemCameraTransforms.TransformType.FIXED); itemRenderer.renderItem(stack, ItemCameraTransforms.TransformType.FIXED);
GlStateManager.popMatrix(); GlStateManager.popMatrix();
} }
// Filter
filterRenderer.render(te, x, y, z, partialTicks, destroyStage);
// Kinetic renders
final BlockState state = getRenderedBlockState(te);
KineticTileEntityRenderer.cacheIfMissing(state, getWorld(), BlockModelSpinner::new);
final BlockPos pos = te.getPos();
Axis axis = ((IRotate) te.getBlockState().getBlock()).getRotationAxis(te.getBlockState());
float angle = KineticTileEntityRenderer.getAngleForTe(te, pos, axis);
TessellatorHelper.prepareFastRender();
TessellatorHelper.begin(DefaultVertexFormats.BLOCK);
KineticTileEntityRenderer.renderFromCache(Tessellator.getInstance().getBuffer(), state, getWorld(), (float) x,
(float) y, (float) z, pos, axis, angle);
TessellatorHelper.draw();
} }
protected BlockState getRenderedBlockState(KineticTileEntity te) { protected BlockState getRenderedBlockState(KineticTileEntity te) {

View file

@ -1,16 +1,15 @@
package com.simibubi.create.modules.contraptions.receivers.constructs; package com.simibubi.create.modules.contraptions.receivers.constructs;
import java.nio.ByteBuffer;
import java.util.Random; import java.util.Random;
import java.util.concurrent.TimeUnit; import java.util.function.Consumer;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL11;
import com.google.common.cache.Cache; import com.simibubi.create.CreateClient;
import com.google.common.cache.CacheBuilder;
import com.simibubi.create.foundation.utility.BufferManipulator;
import com.simibubi.create.foundation.utility.PlacementSimulationWorld; import com.simibubi.create.foundation.utility.PlacementSimulationWorld;
import com.simibubi.create.foundation.utility.SuperByteBuffer;
import com.simibubi.create.foundation.utility.SuperByteBufferCache.Compartment;
import com.simibubi.create.modules.contraptions.receivers.constructs.IHaveMovementBehavior.MovementContext; import com.simibubi.create.modules.contraptions.receivers.constructs.IHaveMovementBehavior.MovementContext;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
@ -19,20 +18,24 @@ import net.minecraft.client.renderer.BlockRendererDispatcher;
import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.model.IBakedModel; import net.minecraft.client.renderer.model.IBakedModel;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraft.world.gen.feature.template.Template.BlockInfo; import net.minecraft.world.gen.feature.template.Template.BlockInfo;
import net.minecraftforge.client.model.data.EmptyModelData; import net.minecraftforge.client.model.data.EmptyModelData;
public class ContraptionRenderer { public class ContraptionRenderer {
protected static Cache<Contraption, ContraptionVertexBuffer> cachedConstructs; public static final Compartment<Contraption> CONTRAPTION = new Compartment<>();
protected static PlacementSimulationWorld renderWorld; protected static PlacementSimulationWorld renderWorld;
public static <T extends BufferManipulator> void cacheContraptionIfMissing(Contraption c) { public static void render(World world, Contraption c, Consumer<SuperByteBuffer> transform, BufferBuilder buffer) {
if (cachedConstructs == null) SuperByteBuffer contraptionBuffer = CreateClient.bufferCache.get(CONTRAPTION, c, () -> renderContraption(c));
cachedConstructs = CacheBuilder.newBuilder().expireAfterAccess(1, TimeUnit.SECONDS).build(); transform.accept(contraptionBuffer);
if (cachedConstructs.getIfPresent(c) != null) buffer.putBulkData(contraptionBuffer.build());
return; renderActors(world, c, transform, buffer);
}
private static SuperByteBuffer renderContraption(Contraption c) {
if (renderWorld == null || renderWorld.getWorld() != Minecraft.getInstance().world) if (renderWorld == null || renderWorld.getWorld() != Minecraft.getInstance().world)
renderWorld = new PlacementSimulationWorld(Minecraft.getInstance().world); renderWorld = new PlacementSimulationWorld(Minecraft.getInstance().world);
@ -43,10 +46,8 @@ public class ContraptionRenderer {
builder.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK); builder.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK);
builder.setTranslation(0, 0, 0); builder.setTranslation(0, 0, 0);
for (BlockInfo info : c.blocks.values()) { for (BlockInfo info : c.blocks.values())
renderWorld.setBlockState(info.pos, info.state); renderWorld.setBlockState(info.pos, info.state);
}
for (BlockInfo info : c.blocks.values()) { for (BlockInfo info : c.blocks.values()) {
IBakedModel originalModel = dispatcher.getModelForState(info.state); IBakedModel originalModel = dispatcher.getModelForState(info.state);
blockRenderer.renderModel(renderWorld, originalModel, info.state, info.pos, builder, true, random, 42, blockRenderer.renderModel(renderWorld, originalModel, info.state, info.pos, builder, true, random, 42,
@ -55,14 +56,10 @@ public class ContraptionRenderer {
builder.finishDrawing(); builder.finishDrawing();
renderWorld.clear(); renderWorld.clear();
cachedConstructs.put(c, new ContraptionVertexBuffer(builder.getByteBuffer())); return new SuperByteBuffer(builder.getByteBuffer());
} }
public static ContraptionVertexBuffer get(Contraption c) { private static void renderActors(World world, Contraption c, Consumer<SuperByteBuffer> transform,
return cachedConstructs.getIfPresent(c);
}
public static void renderActors(World world, Contraption c, float xIn, float yIn, float zIn, float yaw, float pitch,
BufferBuilder buffer) { BufferBuilder buffer) {
for (Pair<BlockInfo, MovementContext> actor : c.getActors()) { for (Pair<BlockInfo, MovementContext> actor : c.getActors()) {
MovementContext context = actor.getRight(); MovementContext context = actor.getRight();
@ -73,30 +70,18 @@ public class ContraptionRenderer {
BlockInfo blockInfo = actor.getLeft(); BlockInfo blockInfo = actor.getLeft();
IHaveMovementBehavior block = (IHaveMovementBehavior) blockInfo.state.getBlock(); IHaveMovementBehavior block = (IHaveMovementBehavior) blockInfo.state.getBlock();
ByteBuffer renderInConstruct = block.renderInConstruct(context); SuperByteBuffer render = block.renderInContraption(context);
if (renderInConstruct == null) if (render == null)
continue; continue;
int posX = blockInfo.pos.getX(); int posX = blockInfo.pos.getX();
int posY = blockInfo.pos.getY(); int posY = blockInfo.pos.getY();
int posZ = blockInfo.pos.getZ(); int posZ = blockInfo.pos.getZ();
float x = xIn + posX; render.translate(posX, posY, posZ);
float y = yIn + posY; transform.accept(render);
float z = zIn + posZ; render.light((lx, ly, lz) -> world.getCombinedLight(new BlockPos(lx, ly, lz), 0)).renderInto(buffer);
float xOrigin = -posX + c.anchor.getX() + .5f;
float yOrigin = -posY + c.anchor.getY() + .5f;
float zOrigin = -posZ + c.anchor.getZ() + .5f;
buffer.putBulkData(BufferManipulator.remanipulateBuffer(renderInConstruct, x, y, z, xOrigin, yOrigin,
zOrigin, yaw, pitch));
} }
} }
public static void invalidateCache() {
if (cachedConstructs != null)
cachedConstructs.invalidateAll();
}
} }

View file

@ -1,70 +0,0 @@
package com.simibubi.create.modules.contraptions.receivers.constructs;
import java.nio.ByteBuffer;
import com.simibubi.create.foundation.utility.BufferManipulator;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
public class ContraptionVertexBuffer extends BufferManipulator {
public ContraptionVertexBuffer(ByteBuffer original) {
super(original);
}
public ByteBuffer getTranslated(World world, float x, float y, float z, Vec3d offset) {
original.rewind();
mutable.rewind();
for (int vertex = 0; vertex < vertexCount(original); vertex++) {
float xL = getX(original, vertex);
float yL = getY(original, vertex);
float zL = getZ(original, vertex);
putPos(mutable, vertex, xL + x + (float) offset.x, yL + y + (float) offset.y, zL + z + (float) offset.z);
BlockPos pos = new BlockPos(offset.x + xL, offset.y + yL, offset.z + zL);
putLight(mutable, vertex, world.getCombinedLight(pos, 0));
}
return mutable;
}
public ByteBuffer getTranslatedAndRotated(World world, float x, float y, float z, float yaw, float pitch,
Vec3d offset, Vec3d rotationOffset) {
original.rewind();
mutable.rewind();
float cosYaw = MathHelper.cos(yaw);
float sinYaw = MathHelper.sin(yaw);
float cosPitch = MathHelper.cos(pitch);
float sinPitch = MathHelper.sin(pitch);
for (int vertex = 0; vertex < vertexCount(original); vertex++) {
float xL = getX(original, vertex) - (float) rotationOffset.x;
float yL = getY(original, vertex) - (float) rotationOffset.y;
float zL = getZ(original, vertex) - (float) rotationOffset.z;
float xL2 = rotateX(xL, yL, zL, sinPitch, cosPitch, Axis.X);
float yL2 = rotateY(xL, yL, zL, sinPitch, cosPitch, Axis.X);
float zL2 = rotateZ(xL, yL, zL, sinPitch, cosPitch, Axis.X);
//
xL = rotateX(xL2, yL2, zL2, sinYaw, cosYaw, Axis.Y);
yL = rotateY(xL2, yL2, zL2, sinYaw, cosYaw, Axis.Y);
zL = rotateZ(xL2, yL2, zL2, sinYaw, cosYaw, Axis.Y);
float xPos = xL + x + (float) (offset.x + rotationOffset.x);
float yPos = yL + y + (float) (offset.y + rotationOffset.y);
float zPos = zL + z + (float) (offset.z + rotationOffset.z);
putPos(mutable, vertex, xPos, yPos, zPos);
BlockPos pos = new BlockPos(xL + rotationOffset.x - .5f, yL + rotationOffset.y - .5f,
zL + rotationOffset.z - .5f);
putLight(mutable, vertex, world.getCombinedLight(pos, 15));
}
return mutable;
}
}

View file

@ -1,7 +1,6 @@
package com.simibubi.create.modules.contraptions.receivers.constructs; package com.simibubi.create.modules.contraptions.receivers.constructs;
import java.nio.ByteBuffer; import com.simibubi.create.foundation.utility.SuperByteBuffer;
import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
@ -76,7 +75,7 @@ public interface IHaveMovementBehavior {
} }
@OnlyIn(value = Dist.CLIENT) @OnlyIn(value = Dist.CLIENT)
default ByteBuffer renderInConstruct(MovementContext context) { default SuperByteBuffer renderInContraption(MovementContext context) {
return null; return null;
} }

View file

@ -8,6 +8,7 @@ import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockReader; import net.minecraft.world.IBlockReader;
import net.minecraft.world.World; import net.minecraft.world.World;
@ -43,4 +44,9 @@ public class MechanicalBearingBlock extends DirectionalKineticBlock
return true; return true;
} }
@Override
public Axis getRotationAxis(BlockState state) {
return state.get(FACING).getAxis();
}
} }

View file

@ -8,9 +8,9 @@ import org.lwjgl.opengl.GL11;
import com.google.common.cache.Cache; import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheBuilder;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.CreateClient;
import com.simibubi.create.foundation.utility.PlacementSimulationWorld; import com.simibubi.create.foundation.utility.PlacementSimulationWorld;
import com.simibubi.create.modules.contraptions.base.IRotate; import com.simibubi.create.foundation.utility.SuperByteBuffer;
import com.simibubi.create.modules.contraptions.base.KineticTileEntity; import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer;
@ -23,7 +23,6 @@ import net.minecraft.client.renderer.model.IBakedModel;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3i; import net.minecraft.util.math.Vec3i;
import net.minecraft.world.gen.feature.template.Template.BlockInfo; import net.minecraft.world.gen.feature.template.Template.BlockInfo;
import net.minecraftforge.client.model.data.EmptyModelData; import net.minecraftforge.client.model.data.EmptyModelData;
@ -36,28 +35,17 @@ public class MechanicalBearingTileEntityRenderer extends KineticTileEntityRender
@Override @Override
public void renderTileEntityFast(KineticTileEntity te, double x, double y, double z, float partialTicks, public void renderTileEntityFast(KineticTileEntity te, double x, double y, double z, float partialTicks,
int destroyStage, BufferBuilder buffer) { int destroyStage, BufferBuilder buffer) {
super.renderTileEntityFast(te, x, y, z, partialTicks, destroyStage, buffer);
MechanicalBearingTileEntity bearingTe = (MechanicalBearingTileEntity) te; MechanicalBearingTileEntity bearingTe = (MechanicalBearingTileEntity) te;
final Direction facing = te.getBlockState().get(BlockStateProperties.FACING); final Direction facing = te.getBlockState().get(BlockStateProperties.FACING);
final BlockPos pos = te.getPos();
float time = AnimationTickHolder.getRenderTick();
BlockState shaftState = AllBlocks.SHAFT_HALF.get().getDefaultState().with(BlockStateProperties.FACING,
facing.getOpposite());
BlockState capState = AllBlocks.MECHANICAL_BEARING_TOP.get().getDefaultState().with(BlockStateProperties.FACING, BlockState capState = AllBlocks.MECHANICAL_BEARING_TOP.get().getDefaultState().with(BlockStateProperties.FACING,
facing); facing);
cacheIfMissing(shaftState, getWorld(), BlockModelSpinner::new); SuperByteBuffer superBuffer = CreateClient.bufferCache.renderBlockState(KINETIC_TILE, capState);
cacheIfMissing(capState, getWorld(), BlockModelSpinner::new);
float offset = getRotationOffsetForPosition(te, pos, facing.getAxis());
float angle = (time * te.getSpeed()) % 360;
angle += offset;
angle = angle / 180f * (float) Math.PI;
float interpolatedAngle = bearingTe.getInterpolatedAngle(partialTicks); float interpolatedAngle = bearingTe.getInterpolatedAngle(partialTicks);
kineticRotationTransform(superBuffer, bearingTe, facing.getAxis(), interpolatedAngle, getWorld());
renderFromCache(buffer, shaftState, getWorld(), (float) x, (float) y, (float) z, pos, facing.getAxis(), angle); superBuffer.translate(x, y, z).renderInto(buffer);
renderFromCache(buffer, capState, getWorld(), (float) x, (float) y, (float) z, pos, facing.getAxis(),
interpolatedAngle);
if (!bearingTe.running) if (!bearingTe.running)
return; return;
@ -108,8 +96,8 @@ public class MechanicalBearingTileEntityRenderer extends KineticTileEntityRender
@Override @Override
protected BlockState getRenderedBlockState(KineticTileEntity te) { protected BlockState getRenderedBlockState(KineticTileEntity te) {
return AllBlocks.SHAFT.block.getDefaultState().with(BlockStateProperties.AXIS, return AllBlocks.SHAFT_HALF.get().getDefaultState().with(BlockStateProperties.FACING,
((IRotate) te.getBlockState().getBlock()).getRotationAxis(te.getBlockState())); te.getBlockState().get(BlockStateProperties.FACING).getOpposite());
} }
public static void invalidateCache() { public static void invalidateCache() {

View file

@ -17,27 +17,13 @@ public class MechanicalPistonTileEntityRenderer extends KineticTileEntityRendere
int destroyStage, BufferBuilder buffer) { int destroyStage, BufferBuilder buffer) {
super.renderTileEntityFast(te, x, y, z, partialTicks, destroyStage, buffer); super.renderTileEntityFast(te, x, y, z, partialTicks, destroyStage, buffer);
// SPECIAL RENDER
MechanicalPistonTileEntity pistonTe = (MechanicalPistonTileEntity) te; MechanicalPistonTileEntity pistonTe = (MechanicalPistonTileEntity) te;
if (!pistonTe.running) if (!pistonTe.running)
return; return;
ContraptionRenderer.cacheContraptionIfMissing(pistonTe.movedContraption);
renderConstructFromCache(pistonTe.movedContraption, pistonTe, x, y, z, partialTicks, buffer);
Vec3d offset = pistonTe.getConstructOffset(partialTicks).subtract(new Vec3d(pistonTe.getPos())); Vec3d offset = pistonTe.getConstructOffset(partialTicks).subtract(new Vec3d(pistonTe.getPos()));
ContraptionRenderer.renderActors(pistonTe.getWorld(), pistonTe.movedContraption, (float) (x + offset.x), ContraptionRenderer.render(getWorld(), pistonTe.movedContraption, (superBuffer) -> {
(float) (y + offset.y), (float) (z + offset.z), 0, 0, buffer); superBuffer.translate(x + offset.x, y + offset.y, z + offset.z);
} }, buffer);
protected void renderConstructFromCache(Contraption c, MechanicalPistonTileEntity te, double x, double y, double z,
float partialTicks, BufferBuilder buffer) {
final Vec3d offset = te.getConstructOffset(partialTicks);
float xPos = (float) (x - te.getPos().getX());
float yPos = (float) (y - te.getPos().getY());
float zPos = (float) (z - te.getPos().getZ());
buffer.putBulkData(ContraptionRenderer.get(c).getTranslated(te.getWorld(), xPos, yPos, zPos, offset));
} }
@Override @Override

View file

@ -4,7 +4,6 @@ import com.mojang.blaze3d.platform.GlStateManager;
import com.simibubi.create.foundation.utility.TessellatorHelper; import com.simibubi.create.foundation.utility.TessellatorHelper;
import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.receivers.constructs.ContraptionRenderer; import com.simibubi.create.modules.contraptions.receivers.constructs.ContraptionRenderer;
import com.simibubi.create.modules.contraptions.receivers.constructs.ContraptionVertexBuffer;
import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.entity.EntityRenderer; import net.minecraft.client.renderer.entity.EntityRenderer;
@ -12,6 +11,7 @@ import net.minecraft.client.renderer.entity.EntityRendererManager;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.item.minecart.AbstractMinecartEntity; import net.minecraft.entity.item.minecart.AbstractMinecartEntity;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.MathHelper;
@ -74,20 +74,19 @@ public class ContraptionEntityRenderer extends EntityRenderer<ContraptionEntity>
} }
} }
ContraptionRenderer.cacheContraptionIfMissing(entity.contraption); BlockPos anchor = entity.contraption.getAnchor();
Vec3d rotationOffset = VecHelper.getCenterOf(anchor);
// Vec3d offset = VecHelper.getCenterOf(anchor).scale(-1);
TessellatorHelper.prepareFastRender(); TessellatorHelper.prepareFastRender();
TessellatorHelper.begin(DefaultVertexFormats.BLOCK); TessellatorHelper.begin(DefaultVertexFormats.BLOCK);
ContraptionVertexBuffer buffer = ContraptionRenderer.get(entity.contraption); ContraptionRenderer.render(entity.world, entity.contraption, superByteBuffer -> {
if (buffer != null) { superByteBuffer.translate(-rotationOffset.x, -rotationOffset.y, -rotationOffset.z);
BlockPos anchor = entity.contraption.getAnchor(); superByteBuffer.rotate(Axis.Y, angleYaw);
Vec3d rotationOffset = VecHelper.getCenterOf(anchor); superByteBuffer.rotate(Axis.Z, anglePitch);
Vec3d offset = VecHelper.getCenterOf(anchor).scale(-1); superByteBuffer.translate(x, y, z);
Tessellator.getInstance().getBuffer().putBulkData(buffer.getTranslatedAndRotated(entity.world, (float) x,
(float) y, (float) z, angleYaw, -anglePitch, offset, rotationOffset)); }, Tessellator.getInstance().getBuffer());
ContraptionRenderer.renderActors(entity.world, entity.contraption, (float) (x + offset.x),
(float) (y + offset.y), (float) (z + offset.z), angleYaw, -anglePitch,
Tessellator.getInstance().getBuffer());
}
TessellatorHelper.draw(); TessellatorHelper.draw();
GlStateManager.popMatrix(); GlStateManager.popMatrix();

View file

@ -1,7 +1,9 @@
package com.simibubi.create.modules.contraptions.relays; package com.simibubi.create.modules.contraptions.relays;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.CreateClient;
import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.AnimationTickHolder;
import com.simibubi.create.foundation.utility.SuperByteBuffer;
import com.simibubi.create.modules.contraptions.base.KineticTileEntity; import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer;
@ -28,8 +30,6 @@ public class GearboxTileEntityRenderer extends KineticTileEntityRenderer {
continue; continue;
BlockState state = defaultState.with(BlockStateProperties.FACING, direction); BlockState state = defaultState.with(BlockStateProperties.FACING, direction);
cacheIfMissing(state, getWorld(), BlockModelSpinner::new);
float offset = getRotationOffsetForPosition(te, pos, axis); float offset = getRotationOffsetForPosition(te, pos, axis);
float angle = (time * te.getSpeed()) % 360; float angle = (time * te.getSpeed()) % 360;
@ -45,7 +45,9 @@ public class GearboxTileEntityRenderer extends KineticTileEntityRenderer {
angle += offset; angle += offset;
angle = angle / 180f * (float) Math.PI; angle = angle / 180f * (float) Math.PI;
renderFromCache(buffer, state, getWorld(), (float) x, (float) y, (float) z, pos, axis, angle); SuperByteBuffer superByteBuffer = CreateClient.bufferCache.renderBlockState(KINETIC_TILE, state);
kineticRotationTransform(superByteBuffer, te, axis, angle, getWorld());
superByteBuffer.translate(x, y, z).renderInto(buffer);
} }
} }

View file

@ -1,7 +1,9 @@
package com.simibubi.create.modules.contraptions.relays; package com.simibubi.create.modules.contraptions.relays;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.CreateClient;
import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.AnimationTickHolder;
import com.simibubi.create.foundation.utility.SuperByteBuffer;
import com.simibubi.create.modules.contraptions.base.KineticTileEntity; import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer;
@ -18,18 +20,15 @@ public class SplitShaftTileEntityRenderer extends KineticTileEntityRenderer {
public void renderTileEntityFast(KineticTileEntity te, double x, double y, double z, float partialTicks, public void renderTileEntityFast(KineticTileEntity te, double x, double y, double z, float partialTicks,
int destroyStage, BufferBuilder buffer) { int destroyStage, BufferBuilder buffer) {
final Axis boxAxis = te.getBlockState().get(BlockStateProperties.AXIS); final Axis boxAxis = te.getBlockState().get(BlockStateProperties.AXIS);
final BlockState defaultState = AllBlocks.SHAFT_HALF.get().getDefaultState();
final BlockPos pos = te.getPos(); final BlockPos pos = te.getPos();
float time = AnimationTickHolder.getRenderTick(); float time = AnimationTickHolder.getRenderTick();
final BlockState defaultState = AllBlocks.SHAFT_HALF.get().getDefaultState();
for (Direction direction : Direction.values()) { for (Direction direction : Direction.values()) {
final Axis axis = direction.getAxis(); Axis axis = direction.getAxis();
if (boxAxis != axis) if (boxAxis != axis)
continue; continue;
BlockState state = defaultState.with(BlockStateProperties.FACING, direction);
cacheIfMissing(state, getWorld(), BlockModelSpinner::new);
float offset = getRotationOffsetForPosition(te, pos, axis); float offset = getRotationOffsetForPosition(te, pos, axis);
float angle = (time * te.getSpeed()) % 360; float angle = (time * te.getSpeed()) % 360;
float modifier = 1; float modifier = 1;
@ -41,7 +40,11 @@ public class SplitShaftTileEntityRenderer extends KineticTileEntityRenderer {
angle += offset; angle += offset;
angle = angle / 180f * (float) Math.PI; angle = angle / 180f * (float) Math.PI;
renderFromCache(buffer, state, getWorld(), (float) x, (float) y, (float) z, pos, axis, angle); BlockState state = defaultState.with(BlockStateProperties.FACING, direction);
SuperByteBuffer superByteBuffer = CreateClient.bufferCache.renderBlockState(KINETIC_TILE, state);
kineticRotationTransform(superByteBuffer, te, axis, angle, getWorld());
superByteBuffer.translate(x, y, z).renderInto(buffer);
} }
} }

View file

@ -1,86 +0,0 @@
package com.simibubi.create.modules.contraptions.relays.belt;
import java.nio.ByteBuffer;
import com.simibubi.create.Create;
import com.simibubi.create.foundation.utility.AnimationTickHolder;
import com.simibubi.create.foundation.utility.BufferManipulator;
import net.minecraft.block.BlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.texture.AtlasTexture;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.util.Direction;
import net.minecraft.util.ResourceLocation;
public class BeltModelAnimator extends BufferManipulator {
protected static TextureAtlasSprite beltTextures;
protected static TextureAtlasSprite originalTexture;
public BeltModelAnimator(ByteBuffer template) {
super(template);
}
private void initSprites() {
AtlasTexture textureMap = Minecraft.getInstance().getTextureMap();
originalTexture = textureMap.getSprite(new ResourceLocation(Create.ID, "block/belt"));
beltTextures = textureMap.getSprite(new ResourceLocation(Create.ID, "block/belt_animated"));
}
public ByteBuffer getTransformed(BeltTileEntity te, float x, float y, float z, int color) {
original.rewind();
mutable.rewind();
float textureOffsetX = 0;
float textureOffsetY = 0;
if (te.getSpeed() != 0) {
float time = AnimationTickHolder.getRenderTick();
Direction direction = te.getBlockState().get(BlockStateProperties.HORIZONTAL_FACING);
if (direction == Direction.EAST || direction == Direction.NORTH)
time = -time;
int textureIndex = (int) ((te.getSpeed() * time / 8) % 16);
if (textureIndex < 0)
textureIndex += 16;
if (beltTextures == null)
initSprites();
textureOffsetX = beltTextures.getInterpolatedU((textureIndex % 4) * 4) - originalTexture.getMinU();
textureOffsetY = beltTextures.getInterpolatedV((textureIndex / 4) * 4) - originalTexture.getMinV();
}
final BlockState blockState = te.getBlockState();
int packedLightCoords = blockState.getPackedLightmapCoords(te.getWorld(), te.getPos());
float texOffX = textureOffsetX;
float texOffY = textureOffsetY;
boolean defaultColor = color == -1;
int b = defaultColor ? 128 : color & 0xFF;
int g = defaultColor ? 128 : (color >> 8) & 0xFF;
int r = defaultColor ? 128 : (color >> 16) & 0xFF;
for (int vertex = 0; vertex < vertexCount(original); vertex++) {
putPos(mutable, vertex, getX(original, vertex) + x, getY(original, vertex) + y, getZ(original, vertex) + z);
putLight(mutable, vertex, packedLightCoords);
int bufferPosition = getBufferPosition(vertex);
mutable.putFloat(bufferPosition + 16, original.getFloat(bufferPosition + 16) + texOffX);
mutable.putFloat(bufferPosition + 20, original.getFloat(bufferPosition + 20) + texOffY);
byte lumByte = getR(original, vertex);
float lum = (lumByte < 0 ? 255 + lumByte : lumByte) / 256f;
int r2 = (int) (r * lum);
int g2 = (int) (g * lum);
int b2 = (int) (b * lum);
putColor(mutable, vertex, (byte) r2, (byte) g2, (byte) b2, (byte) 255);
}
return mutable;
}
public static void invalidateCache() {
beltTextures = null;
}
}

View file

@ -1,15 +1,21 @@
package com.simibubi.create.modules.contraptions.relays.belt; package com.simibubi.create.modules.contraptions.relays.belt;
import static net.minecraft.state.properties.BlockStateProperties.HORIZONTAL_FACING;
import java.util.Random; import java.util.Random;
import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.platform.GlStateManager;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.CreateClient;
import com.simibubi.create.foundation.block.SpriteShifter;
import com.simibubi.create.foundation.block.SpriteShifter.SpriteShiftEntry;
import com.simibubi.create.foundation.utility.AnimationTickHolder;
import com.simibubi.create.foundation.utility.IndependentShadowRenderer; import com.simibubi.create.foundation.utility.IndependentShadowRenderer;
import com.simibubi.create.foundation.utility.SuperByteBuffer;
import com.simibubi.create.foundation.utility.TessellatorHelper; import com.simibubi.create.foundation.utility.TessellatorHelper;
import com.simibubi.create.modules.contraptions.base.IRotate; import com.simibubi.create.modules.contraptions.base.IRotate;
import com.simibubi.create.modules.contraptions.base.KineticTileEntity; import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer;
import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer.BlockModelSpinner;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope; import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
@ -23,7 +29,6 @@ import net.minecraft.client.renderer.tileentity.TileEntityRenderer;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.util.Direction.Axis; import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.Vec3i; import net.minecraft.util.math.Vec3i;
@ -31,6 +36,8 @@ import net.minecraft.util.math.Vec3i;
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
public class BeltTileEntityRenderer extends TileEntityRenderer<BeltTileEntity> { public class BeltTileEntityRenderer extends TileEntityRenderer<BeltTileEntity> {
private static SpriteShiftEntry animatedTexture;
@Override @Override
public void render(BeltTileEntity te, double x, double y, double z, float partialTicks, int destroyStage) { public void render(BeltTileEntity te, double x, double y, double z, float partialTicks, int destroyStage) {
super.render(te, x, y, z, partialTicks, destroyStage); super.render(te, x, y, z, partialTicks, destroyStage);
@ -40,6 +47,41 @@ public class BeltTileEntityRenderer extends TileEntityRenderer<BeltTileEntity> {
renderTileEntityFast(te, x, y, z, partialTicks, destroyStage, Tessellator.getInstance().getBuffer()); renderTileEntityFast(te, x, y, z, partialTicks, destroyStage, Tessellator.getInstance().getBuffer());
TessellatorHelper.draw(); TessellatorHelper.draw();
renderItems(te, x, y, z, partialTicks);
}
@Override
public void renderTileEntityFast(BeltTileEntity te, double x, double y, double z, float partialTicks,
int destroyStage, BufferBuilder buffer) {
if (te.hasPulley())
KineticTileEntityRenderer.renderRotatingKineticBlock(te, getWorld(), getPulleyState(te), x, y, z, buffer);
BlockState renderedState = getBeltState(te);
SuperByteBuffer beltBuffer = CreateClient.bufferCache.renderBlockState(KineticTileEntityRenderer.KINETIC_TILE,
renderedState);
beltBuffer.color(te.color == -1 ? 0x808080 : te.color);
// UV shift
if (te.getSpeed() != 0) {
if (animatedTexture == null)
animatedTexture = SpriteShifter.get("block/belt", "block/belt_animated");
float time = AnimationTickHolder.getRenderTick()
* te.getBlockState().get(HORIZONTAL_FACING).getAxisDirection().getOffset();
int textureIndex = (int) ((te.getSpeed() * time / 8) % 16);
if (textureIndex < 0)
textureIndex += 16;
beltBuffer.shiftUVtoSheet(animatedTexture.getOriginal(), animatedTexture.getTarget(),
(textureIndex % 4) * 16, (textureIndex / 4) * 16);
}
int packedLightmapCoords = te.getBlockState().getPackedLightmapCoords(getWorld(), te.getPos());
beltBuffer.light(packedLightmapCoords).translate(x, y, z).renderInto(buffer);
}
protected void renderItems(BeltTileEntity te, double x, double y, double z, float partialTicks) {
if (te.isController()) { if (te.isController()) {
GlStateManager.pushMatrix(); GlStateManager.pushMatrix();
@ -127,33 +169,13 @@ public class BeltTileEntityRenderer extends TileEntityRenderer<BeltTileEntity> {
} }
} }
@Override protected BlockState getPulleyState(KineticTileEntity te) {
public void renderTileEntityFast(BeltTileEntity te, double x, double y, double z, float partialTicks,
int destroyStage, BufferBuilder buffer) {
if (te.hasPulley()) {
final BlockState state = getRenderedBlockState(te);
KineticTileEntityRenderer.cacheIfMissing(state, getWorld(), BlockModelSpinner::new);
final BlockPos pos = te.getPos();
Axis axis = ((IRotate) te.getBlockState().getBlock()).getRotationAxis(te.getBlockState());
float angle = KineticTileEntityRenderer.getAngleForTe(te, pos, axis);
KineticTileEntityRenderer.renderFromCache(buffer, state, getWorld(), (float) x, (float) y, (float) z, pos,
axis, angle);
}
KineticTileEntityRenderer.cacheIfMissing(te.getBlockState().with(BeltBlock.CASING, false), getWorld(),
BeltModelAnimator::new);
renderBeltFromCache(te, (float) x, (float) y, (float) z, buffer);
}
protected BlockState getRenderedBlockState(KineticTileEntity te) {
return AllBlocks.BELT_PULLEY.get().getDefaultState().with(BlockStateProperties.AXIS, return AllBlocks.BELT_PULLEY.get().getDefaultState().with(BlockStateProperties.AXIS,
((IRotate) AllBlocks.BELT.get()).getRotationAxis(te.getBlockState())); ((IRotate) AllBlocks.BELT.get()).getRotationAxis(te.getBlockState()));
} }
public void renderBeltFromCache(BeltTileEntity te, float x, float y, float z, BufferBuilder buffer) { protected BlockState getBeltState(KineticTileEntity te) {
buffer.putBulkData(((BeltModelAnimator) KineticTileEntityRenderer.cachedBuffers return te.getBlockState().with(BeltBlock.CASING, false);
.get(te.getBlockState().with(BeltBlock.CASING, false))).getTransformed(te, x, y, z, te.color));
} }
} }

View file

@ -18,7 +18,7 @@ import net.minecraft.util.math.Vec3d;
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
public class FilteredTileEntityRenderer { public class FilteredTileEntityRenderer {
public <T extends TileEntity & IHaveFilter> void render(T tileEntityIn, double x, double y, double z, public static <T extends TileEntity & IHaveFilter> void render(T tileEntityIn, double x, double y, double z,
float partialTicks, int destroyStage) { float partialTicks, int destroyStage) {
BlockState state = tileEntityIn.getBlockState(); BlockState state = tileEntityIn.getBlockState();
IBlockWithFilter block = (IBlockWithFilter) state.getBlock(); IBlockWithFilter block = (IBlockWithFilter) state.getBlock();
@ -41,7 +41,8 @@ public class FilteredTileEntityRenderer {
} }
private void renderFilterItem(ItemStack stack, Vec3d position, Direction facing, float scaleDiff, float angle) { private static void renderFilterItem(ItemStack stack, Vec3d position, Direction facing, float scaleDiff,
float angle) {
ItemRenderer itemRenderer = Minecraft.getInstance().getItemRenderer(); ItemRenderer itemRenderer = Minecraft.getInstance().getItemRenderer();
boolean vertical = facing.getAxis().isVertical(); boolean vertical = facing.getAxis().isVertical();

View file

@ -6,17 +6,11 @@ import net.minecraft.client.renderer.tileentity.TileEntityRenderer;
public class BeltFunnelTileEntityRenderer extends TileEntityRenderer<BeltFunnelTileEntity> { public class BeltFunnelTileEntityRenderer extends TileEntityRenderer<BeltFunnelTileEntity> {
FilteredTileEntityRenderer filterRenderer;
public BeltFunnelTileEntityRenderer() {
filterRenderer = new FilteredTileEntityRenderer();
}
@Override @Override
public void render(BeltFunnelTileEntity tileEntityIn, double x, double y, double z, float partialTicks, public void render(BeltFunnelTileEntity tileEntityIn, double x, double y, double z, float partialTicks,
int destroyStage) { int destroyStage) {
super.render(tileEntityIn, x, y, z, partialTicks, destroyStage); super.render(tileEntityIn, x, y, z, partialTicks, destroyStage);
filterRenderer.render(tileEntityIn, x, y, z, partialTicks, destroyStage); FilteredTileEntityRenderer.render(tileEntityIn, x, y, z, partialTicks, destroyStage);
} }
} }

View file

@ -8,12 +8,6 @@ import net.minecraft.state.properties.BlockStateProperties;
public class EntityDetectorTileEntityRenderer extends TileEntityRenderer<EntityDetectorTileEntity> { public class EntityDetectorTileEntityRenderer extends TileEntityRenderer<EntityDetectorTileEntity> {
private FilteredTileEntityRenderer filterRenderer;
public EntityDetectorTileEntityRenderer() {
filterRenderer = new FilteredTileEntityRenderer();
}
@Override @Override
public void render(EntityDetectorTileEntity tileEntityIn, double x, double y, double z, float partialTicks, public void render(EntityDetectorTileEntity tileEntityIn, double x, double y, double z, float partialTicks,
int destroyStage) { int destroyStage) {
@ -25,7 +19,7 @@ public class EntityDetectorTileEntityRenderer extends TileEntityRenderer<EntityD
int k = i / 65536; int k = i / 65536;
GLX.glMultiTexCoord2f(GLX.GL_TEXTURE1, (float) j, (float) k); GLX.glMultiTexCoord2f(GLX.GL_TEXTURE1, (float) j, (float) k);
filterRenderer.render(tileEntityIn, x, y, z, partialTicks, destroyStage); FilteredTileEntityRenderer.render(tileEntityIn, x, y, z, partialTicks, destroyStage);
} }
} }

View file

@ -6,17 +6,11 @@ import net.minecraft.client.renderer.tileentity.TileEntityRenderer;
public class ExtractorTileEntityRenderer extends TileEntityRenderer<ExtractorTileEntity> { public class ExtractorTileEntityRenderer extends TileEntityRenderer<ExtractorTileEntity> {
FilteredTileEntityRenderer filterRenderer;
public ExtractorTileEntityRenderer() {
filterRenderer = new FilteredTileEntityRenderer();
}
@Override @Override
public void render(ExtractorTileEntity tileEntityIn, double x, double y, double z, float partialTicks, public void render(ExtractorTileEntity tileEntityIn, double x, double y, double z, float partialTicks,
int destroyStage) { int destroyStage) {
super.render(tileEntityIn, x, y, z, partialTicks, destroyStage); super.render(tileEntityIn, x, y, z, partialTicks, destroyStage);
filterRenderer.render(tileEntityIn, x, y, z, partialTicks, destroyStage); FilteredTileEntityRenderer.render(tileEntityIn, x, y, z, partialTicks, destroyStage);
} }
} }

View file

@ -8,11 +8,9 @@ import net.minecraft.client.renderer.tileentity.TileEntityRenderer;
public class LinkedExtractorTileEntityRenderer extends TileEntityRenderer<LinkedExtractorTileEntity> { public class LinkedExtractorTileEntityRenderer extends TileEntityRenderer<LinkedExtractorTileEntity> {
LinkedTileEntityRenderer linkRenderer; LinkedTileEntityRenderer linkRenderer;
FilteredTileEntityRenderer filterRenderer;
public LinkedExtractorTileEntityRenderer() { public LinkedExtractorTileEntityRenderer() {
linkRenderer = new LinkedTileEntityRenderer(); linkRenderer = new LinkedTileEntityRenderer();
filterRenderer = new FilteredTileEntityRenderer();
} }
@Override @Override
@ -20,7 +18,7 @@ public class LinkedExtractorTileEntityRenderer extends TileEntityRenderer<Linked
int destroyStage) { int destroyStage) {
super.render(tileEntityIn, x, y, z, partialTicks, destroyStage); super.render(tileEntityIn, x, y, z, partialTicks, destroyStage);
linkRenderer.render(tileEntityIn, x, y, z, partialTicks, destroyStage); linkRenderer.render(tileEntityIn, x, y, z, partialTicks, destroyStage);
filterRenderer.render(tileEntityIn, x, y, z, partialTicks, destroyStage); FilteredTileEntityRenderer.render(tileEntityIn, x, y, z, partialTicks, destroyStage);
} }
} }

View file

@ -1,28 +1,21 @@
package com.simibubi.create.modules.logistics.block.diodes; package com.simibubi.create.modules.logistics.block.diodes;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.block.ColoredOverlayTileEntityRenderer;
import com.simibubi.create.foundation.utility.ColorHelper; import com.simibubi.create.foundation.utility.ColorHelper;
import com.simibubi.create.foundation.utility.ColoredIndicatorRenderer;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.util.math.BlockPos;
import net.minecraftforge.client.model.animation.TileEntityRendererFast;
public class FlexpeaterTileEntityRenderer extends TileEntityRendererFast<FlexpeaterTileEntity> { public class FlexpeaterTileEntityRenderer extends ColoredOverlayTileEntityRenderer<FlexpeaterTileEntity> {
@Override @Override
public void renderTileEntityFast(FlexpeaterTileEntity te, double x, double y, double z, float partialTicks, protected int getColor(FlexpeaterTileEntity te, float partialTicks) {
int destroyStage, BufferBuilder buffer) { return ColorHelper.mixColors(0x2C0300, 0xCD0000, te.state / (float) te.maxState);
BlockPos pos = te.getPos(); }
BlockState renderedState = AllBlocks.FLEXPEATER_INDICATOR.get().getDefaultState(); @Override
BlockState blockState = te.getBlockState(); protected BlockState getOverlayState(FlexpeaterTileEntity te) {
int color = ColorHelper.mixColors(0x2C0300, 0xCD0000, te.state / (float) te.maxState); return AllBlocks.FLEXPEATER_INDICATOR.get().getDefaultState();
int packedLightmapCoords = blockState.getPackedLightmapCoords(getWorld(), pos);
buffer.putBulkData(ColoredIndicatorRenderer.get(renderedState).getTransformed((float) x, (float) y, (float) z,
color, packedLightmapCoords));
} }
} }

View file

@ -4,25 +4,23 @@ import static com.simibubi.create.modules.logistics.management.base.LogisticalCo
import static net.minecraft.state.properties.BlockStateProperties.FACING; import static net.minecraft.state.properties.BlockStateProperties.FACING;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.utility.ColoredIndicatorRenderer; import com.simibubi.create.foundation.block.ColoredOverlayTileEntityRenderer;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.util.math.BlockPos;
import net.minecraftforge.client.model.animation.TileEntityRendererFast;
public class LogisticalControllerTileEntityRenderer extends TileEntityRendererFast<LogisticalActorTileEntity> { public class LogisticalControllerTileEntityRenderer
extends ColoredOverlayTileEntityRenderer<LogisticalActorTileEntity> {
@Override @Override
public void renderTileEntityFast(LogisticalActorTileEntity te, double x, double y, double z, protected int getColor(LogisticalActorTileEntity te, float partialTicks) {
float partialTicks, int destroyStage, BufferBuilder buffer) { return te.getColor();
BlockPos pos = te.getPos(); }
BlockState blockState = te.getBlockState();
BlockState renderedState = AllBlocks.LOGISTICAL_CONTROLLER_INDICATOR.get().getDefaultState() @Override
.with(FACING, blockState.get(FACING)).with(TYPE, blockState.get(TYPE)); protected BlockState getOverlayState(LogisticalActorTileEntity te) {
int packedLightmapCoords = blockState.getPackedLightmapCoords(getWorld(), pos); BlockState state = te.getBlockState();
buffer.putBulkData(ColoredIndicatorRenderer.get(renderedState).getTransformed((float) x, (float) y, (float) z, return AllBlocks.LOGISTICAL_CONTROLLER_INDICATOR.get().getDefaultState().with(FACING, state.get(FACING))
te.getColor(), packedLightmapCoords)); .with(TYPE, state.get(TYPE));
} }
} }

View file

@ -1,10 +1,9 @@
package com.simibubi.create.modules.logistics.transport.villager; package com.simibubi.create.modules.logistics.transport.villager;
import org.lwjgl.opengl.GL11;
import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.platform.GlStateManager;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.utility.ColoredIndicatorRenderer; import com.simibubi.create.foundation.block.ColoredOverlayTileEntityRenderer;
import com.simibubi.create.foundation.utility.SuperByteBuffer;
import com.simibubi.create.foundation.utility.TessellatorHelper; import com.simibubi.create.foundation.utility.TessellatorHelper;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
@ -15,29 +14,32 @@ import net.minecraft.client.renderer.tileentity.TileEntityRenderer;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos;
public class LogisticiansTableTileEntityRenderer extends TileEntityRenderer<LogisticiansTableTileEntity> { public class LogisticiansTableTileEntityRenderer extends TileEntityRenderer<LogisticiansTableTileEntity> {
public void render(LogisticiansTableTileEntity te, double x, double y, double z, float partialTicks,
int destroyStage) {
renderColoredIndicator(te, x, y, z);
renderBook(te, x, y, z);
}
protected void renderColoredIndicator(LogisticiansTableTileEntity te, double x, double y, double z) {
TessellatorHelper.prepareFastRender();
BlockState renderedState = AllBlocks.LOGISTICIANS_TABLE_INDICATOR.get().getDefaultState();
TessellatorHelper.begin(DefaultVertexFormats.BLOCK);
SuperByteBuffer render = ColoredOverlayTileEntityRenderer.render(getWorld(), te.getPos(), renderedState,
te.getColor());
Tessellator.getInstance().getBuffer().putBulkData(render.translate(x, y, z).build());
TessellatorHelper.draw();
}
private static final ResourceLocation bookLocation = new ResourceLocation( private static final ResourceLocation bookLocation = new ResourceLocation(
"textures/entity/enchanting_table_book.png"); "textures/entity/enchanting_table_book.png");
private final BookModel bookModel = new BookModel(); private final BookModel bookModel = new BookModel();
public void render(LogisticiansTableTileEntity tileEntityIn, double x, double y, double z, float partialTicks, protected void renderBook(LogisticiansTableTileEntity te, double x, double y, double z) {
int destroyStage) {
TessellatorHelper.prepareFastRender();
BlockPos pos = tileEntityIn.getPos();
BlockState blockState = tileEntityIn.getBlockState();
BlockState renderedState = AllBlocks.LOGISTICIANS_TABLE_INDICATOR.get().getDefaultState();
int packedLightmapCoords = blockState.getPackedLightmapCoords(getWorld(), pos);
Tessellator.getInstance().getBuffer().begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK);
int color = tileEntityIn.getColor();
Tessellator.getInstance().getBuffer().putBulkData(ColoredIndicatorRenderer.get(renderedState)
.getTransformed((float) x, (float) y, (float) z, color, packedLightmapCoords));
Tessellator.getInstance().draw();
RenderHelper.enableStandardItemLighting(); RenderHelper.enableStandardItemLighting();
BlockState blockstate = te.getBlockState();
BlockState blockstate = tileEntityIn.getBlockState();
GlStateManager.pushMatrix(); GlStateManager.pushMatrix();
GlStateManager.translatef((float) x + 0.5F, (float) y + 1.0F + 0.0625F, (float) z + 0.5F); GlStateManager.translatef((float) x + 0.5F, (float) y + 1.0F + 0.0625F, (float) z + 0.5F);
float f = blockstate.get(BlockStateProperties.HORIZONTAL_FACING).rotateY().getHorizontalAngle(); float f = blockstate.get(BlockStateProperties.HORIZONTAL_FACING).rotateY().getHorizontalAngle();
@ -49,6 +51,5 @@ public class LogisticiansTableTileEntityRenderer extends TileEntityRenderer<Logi
this.bookModel.render(0.0F, 0.1F, 0.9F, 1.2F, 0.0F, 0.0625F); this.bookModel.render(0.0F, 0.1F, 0.9F, 1.2F, 0.0F, 0.0625F);
GlStateManager.disableCull(); GlStateManager.disableCull();
GlStateManager.popMatrix(); GlStateManager.popMatrix();
} }
} }