Towards better normals.

- Easier SuperByteBuffer transform settings.
 - Some cleanup here and there.
This commit is contained in:
JozsefA 2021-03-06 21:46:17 -08:00
parent e930e62436
commit bb3fed2a3b
15 changed files with 182 additions and 141 deletions

View file

@ -15,7 +15,7 @@ public class BackHalfShaftInstance extends HalfShaftInstance {
InstancedTileRenderRegistry.instance.register(type, BackHalfShaftInstance::new));
}
public BackHalfShaftInstance(InstancedTileRenderer modelManager, KineticTileEntity tile) {
public BackHalfShaftInstance(InstancedTileRenderer<?> modelManager, KineticTileEntity tile) {
super(modelManager, tile);
}

View file

@ -58,6 +58,13 @@ public class KineticData<D extends KineticData<D>> extends InstanceData {
return (D) this;
}
public D nudge(float x, float y, float z) {
this.x += x;
this.y += y;
this.z += z;
return (D) this;
}
public D setBlockLight(int blockLight) {
this.blockLight = (byte) ((blockLight & 0xF) << 4);
return (D) this;

View file

@ -21,7 +21,7 @@ public class SingleRotatingInstance extends KineticTileInstance<KineticTileEntit
protected InstanceKey<RotatingData> rotatingModelKey;
public SingleRotatingInstance(InstancedTileRenderer modelManager, KineticTileEntity tile) {
public SingleRotatingInstance(InstancedTileRenderer<?> modelManager, KineticTileEntity tile) {
super(modelManager, tile);
}

View file

@ -24,7 +24,7 @@ public class DrillInstance extends SingleRotatingInstance {
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () ->
InstancedTileRenderRegistry.instance.register(type, DrillInstance::new)); }
public DrillInstance(InstancedTileRenderer modelManager, KineticTileEntity tile) {
public DrillInstance(InstancedTileRenderer<?> modelManager, KineticTileEntity tile) {
super(modelManager, tile);
}

View file

@ -32,17 +32,16 @@ public class StickerRenderer extends SafeTileEntityRenderer<StickerTileEntity> {
offset = state.get(StickerBlock.EXTENDED) ? 1 : 0;
Direction facing = state.get(StickerBlock.FACING);
ms.push();
MatrixStacker.of(ms)
head.matrixStacker()
.nudge(te.hashCode())
.centre()
.rotateY(AngleHelper.horizontalAngle(facing))
.rotateX(AngleHelper.verticalAngle(facing) + 90)
.unCentre();
ms.translate(0, (offset * offset) * 4 / 16f, 0);
.unCentre()
.translate(0, (offset * offset) * 4 / 16f, 0);
head.light(light)
.renderInto(ms, buffer.getBuffer(RenderType.getSolid()));
ms.pop();
}
}

View file

@ -4,6 +4,7 @@ import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.AllBlockPartials;
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer;
import com.simibubi.create.foundation.render.SuperByteBuffer;
import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.foundation.utility.AnimationTickHolder;
import com.simibubi.create.foundation.utility.Iterate;
@ -50,25 +51,20 @@ public class GantryPinionRenderer extends KineticTileEntityRenderer {
if (facing == Direction.NORTH || facing == Direction.EAST)
angleForTe *= -1;
ms.push();
MatrixStacker msr = MatrixStacker.of(ms);
msr.centre()
SuperByteBuffer cogs = AllBlockPartials.GANTRY_COGS.renderOn(state);
cogs.matrixStacker()
.centre()
.rotateY(AngleHelper.horizontalAngle(facing))
.rotateX(facing == Direction.UP ? 0 : facing == Direction.DOWN ? 180 : 90)
.rotateY(alongFirst ^ facing.getAxis() == Axis.Z ? 90 : 0);
.rotateY(alongFirst ^ facing.getAxis() == Axis.Z ? 90 : 0)
.translate(0, -9 / 16f, 0)
.multiply(Vector3f.POSITIVE_X.getRadialQuaternion(-angleForTe))
.translate(0, 9 / 16f, 0)
.unCentre();
ms.translate(0, -9 / 16f, 0);
ms.multiply(Vector3f.POSITIVE_X.getRadialQuaternion(-angleForTe));
ms.translate(0, 9 / 16f, 0);
msr.unCentre();
AllBlockPartials.GANTRY_COGS.renderOn(state)
.light(light)
cogs.light(light)
.renderInto(ms, buffer.getBuffer(RenderType.getSolid()));
ms.pop();
}
public static float getAngleForTe(KineticTileEntity te, final BlockPos pos, Axis axis) {

View file

@ -1,7 +0,0 @@
package com.simibubi.create.content.contraptions.components.structureMovement.render;
public class ContraptionRenderer {
}

View file

@ -71,11 +71,11 @@ public class BeltRenderer extends SafeTileEntityRenderer<BeltTileEntity> {
boolean sideways = beltSlope == BeltSlope.SIDEWAYS;
boolean alongX = facing.getAxis() == Axis.X;
MatrixStacker msr = MatrixStacker.of(ms);
MatrixStack localTransforms = new MatrixStack();
MatrixStacker msr = MatrixStacker.of(localTransforms);
IVertexBuilder vb = buffer.getBuffer(RenderType.getSolid());
float renderTick = AnimationTickHolder.getRenderTime();
ms.push();
msr.centre();
msr.rotateY(AngleHelper.horizontalAngle(facing) + (upward ? 180 : 0) + (sideways ? 270 : 0));
msr.rotateZ(sideways ? 90 : 0);
@ -117,12 +117,13 @@ public class BeltRenderer extends SafeTileEntityRenderer<BeltTileEntity> {
beltBuffer.shiftUVScrolling(spriteShift, (float) scroll);
}
beltBuffer.renderInto(ms, vb);
beltBuffer
.transform(localTransforms)
.renderInto(ms, vb);
// Diagonal belt do not have a separate bottom model
if (diagonal) break;
}
ms.pop();
if (te.hasPulley()) {
// TODO 1.15 find a way to cache this model matrix computation

View file

@ -17,7 +17,7 @@ public class ShaftInstance extends SingleRotatingInstance {
InstancedTileRenderRegistry.instance.register(type, ShaftInstance::new));
}
public ShaftInstance(InstancedTileRenderer dispatcher, KineticTileEntity tile) {
public ShaftInstance(InstancedTileRenderer<?> dispatcher, KineticTileEntity tile) {
super(dispatcher, tile);
}

View file

@ -41,7 +41,9 @@ public class ArmRenderer extends KineticTileEntityRenderer {
ArmTileEntity arm = (ArmTileEntity) te;
IVertexBuilder builder = buffer.getBuffer(RenderType.getSolid());
BlockState blockState = te.getBlockState();
MatrixStacker msr = MatrixStacker.of(ms);
MatrixStack msLocal = new MatrixStack();
MatrixStacker msr = MatrixStacker.of(msLocal);
int color = 0xFFFFFF;
float baseAngle = arm.baseAngle.get(pt);
@ -58,8 +60,6 @@ public class ArmRenderer extends KineticTileEntityRenderer {
headAngle = -lowerArmAngle;
color = ColorHelper.rainbowColor(AnimationTickHolder.getTicks() * 100);
}
ms.push();
SuperByteBuffer base = AllBlockPartials.ARM_BASE.renderOn(blockState).light(light);
SuperByteBuffer lowerBody = AllBlockPartials.ARM_LOWER_BODY.renderOn(blockState).light(light);
@ -73,27 +73,32 @@ public class ArmRenderer extends KineticTileEntityRenderer {
if (blockState.get(ArmBlock.CEILING))
msr.rotateX(180);
ms.translate(0, 4 / 16d, 0);
msLocal.translate(0, 4 / 16d, 0);
msr.rotateY(baseAngle);
base.renderInto(ms, builder);
ms.translate(0, 1 / 16d, -2 / 16d);
msr.rotateX(lowerArmAngle);
ms.translate(0, -1 / 16d, 0);
lowerBody.color(color)
base.transform(msLocal)
.renderInto(ms, builder);
ms.translate(0, 12 / 16d, 12 / 16d);
msLocal.translate(0, 1 / 16d, -2 / 16d);
msr.rotateX(lowerArmAngle);
msLocal.translate(0, -1 / 16d, 0);
lowerBody.color(color)
.transform(msLocal)
.renderInto(ms, builder);
msLocal.translate(0, 12 / 16d, 12 / 16d);
msr.rotateX(upperArmAngle);
upperBody.color(color)
.transform(msLocal)
.renderInto(ms, builder);
msLocal.translate(0, 11 / 16d, -11 / 16d);
msr.rotateX(headAngle);
head.transform(msLocal)
.renderInto(ms, builder);
ms.translate(0, 11 / 16d, -11 / 16d);
msr.rotateX(headAngle);
head.renderInto(ms, builder);
ms.translate(0, 0, -4 / 16d);
claw.renderInto(ms, builder);
msLocal.translate(0, 0, -4 / 16d);
claw.transform(msLocal)
.renderInto(ms, builder);
ItemStack item = arm.heldItem;
ItemRenderer itemRenderer = Minecraft.getInstance()
.getItemRenderer();
@ -103,23 +108,27 @@ public class ArmRenderer extends KineticTileEntityRenderer {
.isGui3d();
for (int flip : Iterate.positiveAndNegative) {
ms.push();
ms.translate(0, flip * 3 / 16d, -1 / 16d);
msLocal.push();
msLocal.translate(0, flip * 3 / 16d, -1 / 16d);
msr.rotateX(flip * (hasItem ? isBlockItem ? 0 : -35 : 0));
clawGrip.light(light).renderInto(ms, builder);
ms.pop();
clawGrip.light(light).transform(msLocal).renderInto(ms, builder);
msLocal.pop();
}
if (hasItem) {
ms.push();
float itemScale = isBlockItem ? .5f : .625f;
msr.rotateX(90);
ms.translate(0, -4 / 16f, 0);
ms.scale(itemScale, itemScale, itemScale);
msLocal.translate(0, -4 / 16f, 0);
msLocal.scale(itemScale, itemScale, itemScale);
ms.peek().getModel().multiply(msLocal.peek().getModel());
itemRenderer
.renderItem(item, TransformType.FIXED, light, overlay, ms, buffer);
ms.pop();
}
ms.pop();
}
@Override

View file

@ -42,7 +42,6 @@ public class SchematicannonRenderer extends SafeTileEntityRenderer<Schematicanno
double yaw = 0;
double pitch = 40;
double recoil = 0;
BlockPos pos = tileEntityIn.getPos();
if (tileEntityIn.target != null) {
@ -67,78 +66,7 @@ public class SchematicannonRenderer extends SafeTileEntityRenderer<Schematicanno
}
if (!tileEntityIn.flyingBlocks.isEmpty()) {
for (LaunchedItem launched : tileEntityIn.flyingBlocks) {
if (launched.ticksRemaining == 0)
continue;
// Calculate position of flying block
Vec3d start = new Vec3d(tileEntityIn.getPos().add(.5f, 1, .5f));
Vec3d target = new Vec3d(launched.target).add(-.5, 0, 1);
Vec3d distance = target.subtract(start);
double targetY = target.y - start.y;
double throwHeight = Math.sqrt(distance.lengthSquared()) * .6f + targetY;
Vec3d cannonOffset = distance.add(0, throwHeight, 0).normalize().scale(2);
start = start.add(cannonOffset);
float progress =
((float) launched.totalTicks - (launched.ticksRemaining + 1 - partialTicks)) / launched.totalTicks;
Vec3d blockLocationXZ = new Vec3d(.5, .5, .5).add(target.subtract(start).scale(progress).mul(1, 0, 1));
// Height is determined through a bezier curve
float t = progress;
double yOffset = 2 * (1 - t) * t * throwHeight + t * t * targetY;
Vec3d blockLocation = blockLocationXZ.add(0, yOffset + 1, 0).add(cannonOffset);
// Offset to position
ms.push();
ms.translate(blockLocation.x, blockLocation.y, blockLocation.z);
ms.multiply(new Vector3f(0, 1, 0).getDegreesQuaternion(360 * t * 2));
ms.multiply(new Vector3f(1, 0, 0).getDegreesQuaternion(360 * t * 2));
// Render the Block
if (launched instanceof ForBlockState) {
float scale = .3f;
ms.scale(scale, scale, scale);
Minecraft.getInstance().getBlockRendererDispatcher().renderBlock(((ForBlockState) launched).state,
ms, buffer, light, overlay, EmptyModelData.INSTANCE);
}
// Render the item
if (launched instanceof ForEntity) {
float scale = 1.2f;
ms.scale(scale, scale, scale);
Minecraft.getInstance().getItemRenderer().renderItem(launched.stack, TransformType.GROUND, light,
overlay, ms, buffer);
}
ms.pop();
// Apply Recoil if block was just launched
if ((launched.ticksRemaining + 1 - partialTicks) > launched.totalTicks - 10)
recoil = Math.max(recoil, (launched.ticksRemaining + 1 - partialTicks) - launched.totalTicks + 10);
// Render particles for launch
if (launched.ticksRemaining == launched.totalTicks && tileEntityIn.firstRenderTick) {
tileEntityIn.firstRenderTick = false;
for (int i = 0; i < 10; i++) {
Random r = tileEntityIn.getWorld().getRandom();
double sX = cannonOffset.x * .01f;
double sY = (cannonOffset.y + 1) * .01f;
double sZ = cannonOffset.z * .01f;
double rX = r.nextFloat() - sX * 40;
double rY = r.nextFloat() - sY * 40;
double rZ = r.nextFloat() - sZ * 40;
tileEntityIn.getWorld().addParticle(ParticleTypes.CLOUD, start.x + rX, start.y + rY,
start.z + rZ, sX, sY, sZ);
}
}
}
}
double recoil = !tileEntityIn.flyingBlocks.isEmpty() ? getRecoil(tileEntityIn, partialTicks, ms, buffer, light, overlay) : 0;
ms.push();
BlockState state = tileEntityIn.getBlockState();
@ -163,4 +91,79 @@ public class SchematicannonRenderer extends SafeTileEntityRenderer<Schematicanno
ms.pop();
}
private double getRecoil(SchematicannonTileEntity tileEntityIn, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay) {
double recoil = 0;
for (LaunchedItem launched : tileEntityIn.flyingBlocks) {
if (launched.ticksRemaining == 0)
continue;
// Calculate position of flying block
Vec3d start = new Vec3d(tileEntityIn.getPos().add(.5f, 1, .5f));
Vec3d target = new Vec3d(launched.target).add(-.5, 0, 1);
Vec3d distance = target.subtract(start);
double targetY = target.y - start.y;
double throwHeight = Math.sqrt(distance.lengthSquared()) * .6f + targetY;
Vec3d cannonOffset = distance.add(0, throwHeight, 0).normalize().scale(2);
start = start.add(cannonOffset);
float progress =
((float) launched.totalTicks - (launched.ticksRemaining + 1 - partialTicks)) / launched.totalTicks;
Vec3d blockLocationXZ = new Vec3d(.5, .5, .5).add(target.subtract(start).scale(progress).mul(1, 0, 1));
// Height is determined through a bezier curve
float t = progress;
double yOffset = 2 * (1 - t) * t * throwHeight + t * t * targetY;
Vec3d blockLocation = blockLocationXZ.add(0, yOffset + 1, 0).add(cannonOffset);
// Offset to position
ms.push();
ms.translate(blockLocation.x, blockLocation.y, blockLocation.z);
ms.multiply(new Vector3f(0, 1, 0).getDegreesQuaternion(360 * t * 2));
ms.multiply(new Vector3f(1, 0, 0).getDegreesQuaternion(360 * t * 2));
// Render the Block
if (launched instanceof ForBlockState) {
float scale = .3f;
ms.scale(scale, scale, scale);
Minecraft.getInstance().getBlockRendererDispatcher().renderBlock(((ForBlockState) launched).state, ms, buffer, light, overlay, EmptyModelData.INSTANCE);
}
// Render the item
if (launched instanceof ForEntity) {
float scale = 1.2f;
ms.scale(scale, scale, scale);
Minecraft.getInstance().getItemRenderer().renderItem(launched.stack, TransformType.GROUND, light, overlay, ms, buffer);
}
ms.pop();
// Apply Recoil if block was just launched
if ((launched.ticksRemaining + 1 - partialTicks) > launched.totalTicks - 10)
recoil = Math.max(recoil, (launched.ticksRemaining + 1 - partialTicks) - launched.totalTicks + 10);
// Render particles for launch
if (launched.ticksRemaining == launched.totalTicks && tileEntityIn.firstRenderTick) {
tileEntityIn.firstRenderTick = false;
for (int i = 0; i < 10; i++) {
Random r = tileEntityIn.getWorld().getRandom();
double sX = cannonOffset.x * .01f;
double sY = (cannonOffset.y + 1) * .01f;
double sZ = cannonOffset.z * .01f;
double rX = r.nextFloat() - sX * 40;
double rY = r.nextFloat() - sY * 40;
double rZ = r.nextFloat() - sZ * 40;
tileEntityIn.getWorld().addParticle(ParticleTypes.CLOUD, start.x + rX, start.y + rY,
start.z + rZ, sX, sY, sZ);
}
}
}
return recoil;
}
}

View file

@ -201,7 +201,6 @@ public class ClientEvents {
if (!isGameActive())
return;
TurntableHandler.gameRenderTick();
ContraptionRenderDispatcher.renderTick();
}
protected static boolean isGameActive() {

View file

@ -8,17 +8,15 @@ import com.mojang.blaze3d.vertex.IVertexBuilder;
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher;
import com.simibubi.create.foundation.block.render.SpriteShiftEntry;
import com.simibubi.create.foundation.utility.MatrixStacker;
import it.unimi.dsi.fastutil.longs.Long2DoubleMap;
import it.unimi.dsi.fastutil.longs.Long2DoubleOpenHashMap;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.Matrix3f;
import net.minecraft.client.renderer.Matrix4f;
import net.minecraft.client.renderer.Vector3f;
import net.minecraft.client.renderer.Vector4f;
import net.minecraft.client.renderer.*;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.LightType;
import net.minecraft.world.World;
import net.minecraftforge.client.model.pipeline.LightUtil;
@ -107,13 +105,16 @@ public class SuperByteBuffer extends TemplateBuffer {
float staticDiffuse = LightUtil.diffuseLight(normalX, normalY, normalZ);
normal.set(normalX, normalY, normalZ);
normal.transform(normalMat);
float instanceDiffuse = LightUtil.diffuseLight(normal.getX(), normal.getY(), normal.getZ());
float nx = normal.getX();
float ny = normal.getY();
float nz = normal.getZ();
float instanceDiffuse = LightUtil.diffuseLight(nx, ny, nz);
pos.set(x, y, z, 1F);
pos.transform(modelMat);
builder.vertex(pos.getX(), pos.getY(), pos.getZ());
//builder.color((byte) Math.max(0, normal.getX() * 255), (byte) Math.max(0, normal.getY() * 255), (byte) Math.max(0, normal.getZ() * 255), a);
//builder.color((byte) Math.max(0, nx * 255), (byte) Math.max(0, ny * 255), (byte) Math.max(0, nz * 255), a);
if (shouldColor) {
//float lum = (r < 0 ? 255 + r : r) / 256f;
int colorR = Math.min(255, (int) (((float) this.r) * instanceDiffuse));
@ -152,7 +153,7 @@ public class SuperByteBuffer extends TemplateBuffer {
} else
builder.light(getLight(buffer, i));
builder.normal(normal.getX(), normal.getY(), normal.getZ())
builder.normal(nx, ny, nz)
.endVertex();
}
@ -164,6 +165,14 @@ public class SuperByteBuffer extends TemplateBuffer {
otherBlockLight = -1;
}
public MatrixStacker matrixStacker() {
return MatrixStacker.of(transforms);
}
public SuperByteBuffer translate(Vec3d vec) {
return translate(vec.x, vec.y, vec.z);
}
public SuperByteBuffer translate(double x, double y, double z) {
return translate((float) x, (float) y, (float) z);
}
@ -173,6 +182,12 @@ public class SuperByteBuffer extends TemplateBuffer {
return this;
}
public SuperByteBuffer transform(MatrixStack stack) {
transforms.peek().getModel().multiply(stack.peek().getModel());
transforms.peek().getNormal().multiply(stack.peek().getNormal());
return this;
}
public SuperByteBuffer rotate(Direction axis, float radians) {
if (radians == 0)
return this;

View file

@ -77,6 +77,14 @@ public abstract class InstancedModel<D extends InstanceData> extends BufferedMod
key.invalidate();
}
public D getInstance(InstanceKey<D> key) {
verifyKey(key);
markIndexChanged(key.index);
return this.data.get(key.index);
}
public synchronized void modifyInstance(InstanceKey<D> key, Consumer<D> edit) {
verifyKey(key);

View file

@ -2,6 +2,7 @@ package com.simibubi.create.foundation.utility;
import com.mojang.blaze3d.matrix.MatrixStack;
import net.minecraft.client.renderer.Quaternion;
import net.minecraft.client.renderer.Vector3f;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.BlockPos;
@ -10,7 +11,7 @@ import net.minecraft.util.math.Vec3i;
public class MatrixStacker {
static Vec3d center = VecHelper.getCenterOf(BlockPos.ZERO);
public static final Vec3d center = VecHelper.getCenterOf(BlockPos.ZERO);
static MatrixStacker instance;
MatrixStack ms;
@ -63,6 +64,16 @@ public class MatrixStacker {
return this;
}
public MatrixStacker translate(double x, double y, double z) {
ms.translate(x, y, z);
return this;
}
public MatrixStacker multiply(Quaternion quaternion) {
ms.multiply(quaternion);
return this;
}
public MatrixStacker nudge(int id) {
long randomBits = (long) id * 493286711L;
randomBits = randomBits * randomBits * 4392167121L + randomBits * 98761L;