mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-12-28 16:06:48 +01:00
Stacks of Cache
- Instancing support for bezier girders - Transformation matrices for bezier segments are only calculated once
This commit is contained in:
parent
051e7ffc1f
commit
26d6a7b3e4
5 changed files with 390 additions and 234 deletions
|
@ -3,7 +3,11 @@ package com.simibubi.create.content.logistics.trains;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.repack.joml.Math;
|
import com.jozufozu.flywheel.repack.joml.Math;
|
||||||
|
import com.jozufozu.flywheel.util.transform.MatrixTransformStack;
|
||||||
|
import com.mojang.math.Matrix4f;
|
||||||
|
import com.simibubi.create.content.logistics.trains.track.TrackRenderer;
|
||||||
import com.simibubi.create.foundation.utility.Couple;
|
import com.simibubi.create.foundation.utility.Couple;
|
||||||
|
import com.simibubi.create.foundation.utility.Iterate;
|
||||||
import com.simibubi.create.foundation.utility.VecHelper;
|
import com.simibubi.create.foundation.utility.VecHelper;
|
||||||
|
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
|
@ -14,6 +18,8 @@ import net.minecraft.nbt.Tag;
|
||||||
import net.minecraft.network.FriendlyByteBuf;
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
import net.minecraft.util.Mth;
|
import net.minecraft.util.Mth;
|
||||||
import net.minecraft.world.phys.Vec3;
|
import net.minecraft.world.phys.Vec3;
|
||||||
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
|
||||||
public class BezierConnection implements Iterable<BezierConnection.Segment> {
|
public class BezierConnection implements Iterable<BezierConnection.Segment> {
|
||||||
|
|
||||||
|
@ -264,17 +270,19 @@ public class BezierConnection implements Iterable<BezierConnection.Segment> {
|
||||||
public Iterator<Segment> iterator() {
|
public Iterator<Segment> iterator() {
|
||||||
resolve();
|
resolve();
|
||||||
var offset = Vec3.atLowerCornerOf(tePositions.getFirst())
|
var offset = Vec3.atLowerCornerOf(tePositions.getFirst())
|
||||||
.scale(-1)
|
.scale(-1)
|
||||||
.add(0, 3 / 16f, 0);
|
.add(0, 3 / 16f, 0);
|
||||||
return new Bezierator(this, offset);
|
return new Bezierator(this, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Segment {
|
public static class Segment {
|
||||||
|
|
||||||
public int index;
|
public int index;
|
||||||
public Vec3 position;
|
public Vec3 position;
|
||||||
public Vec3 derivative;
|
public Vec3 derivative;
|
||||||
public Vec3 faceNormal;
|
public Vec3 faceNormal;
|
||||||
public Vec3 normal;
|
public Vec3 normal;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class Bezierator implements Iterator<Segment> {
|
private static class Bezierator implements Iterator<Segment> {
|
||||||
|
@ -293,16 +301,16 @@ public class BezierConnection implements Iterable<BezierConnection.Segment> {
|
||||||
this.bc = bc;
|
this.bc = bc;
|
||||||
|
|
||||||
end1 = bc.starts.getFirst()
|
end1 = bc.starts.getFirst()
|
||||||
.add(offset);
|
.add(offset);
|
||||||
end2 = bc.starts.getSecond()
|
end2 = bc.starts.getSecond()
|
||||||
.add(offset);
|
.add(offset);
|
||||||
|
|
||||||
finish1 = bc.axes.getFirst()
|
finish1 = bc.axes.getFirst()
|
||||||
.scale(bc.handleLength)
|
.scale(bc.handleLength)
|
||||||
.add(end1);
|
.add(end1);
|
||||||
finish2 = bc.axes.getSecond()
|
finish2 = bc.axes.getSecond()
|
||||||
.scale(bc.handleLength)
|
.scale(bc.handleLength)
|
||||||
.add(end2);
|
.add(end2);
|
||||||
|
|
||||||
faceNormal1 = bc.normals.getFirst();
|
faceNormal1 = bc.normals.getFirst();
|
||||||
faceNormal2 = bc.normals.getSecond();
|
faceNormal2 = bc.normals.getSecond();
|
||||||
|
@ -321,12 +329,203 @@ public class BezierConnection implements Iterable<BezierConnection.Segment> {
|
||||||
float t = this.bc.getSegmentT(segment.index);
|
float t = this.bc.getSegmentT(segment.index);
|
||||||
segment.position = VecHelper.bezier(end1, end2, finish1, finish2, t);
|
segment.position = VecHelper.bezier(end1, end2, finish1, finish2, t);
|
||||||
segment.derivative = VecHelper.bezierDerivative(end1, end2, finish1, finish2, t)
|
segment.derivative = VecHelper.bezierDerivative(end1, end2, finish1, finish2, t)
|
||||||
.normalize();
|
.normalize();
|
||||||
segment.faceNormal = faceNormal1.equals(faceNormal2) ? faceNormal1 : VecHelper.slerp(t, faceNormal1, faceNormal2);
|
segment.faceNormal =
|
||||||
|
faceNormal1.equals(faceNormal2) ? faceNormal1 : VecHelper.slerp(t, faceNormal1, faceNormal2);
|
||||||
segment.normal = segment.faceNormal.cross(segment.derivative)
|
segment.normal = segment.faceNormal.cross(segment.derivative)
|
||||||
.normalize();
|
.normalize();
|
||||||
return segment;
|
return segment;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private SegmentAngles[] bakedSegments;
|
||||||
|
private GirderAngles[] bakedGirders;
|
||||||
|
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
public static class SegmentAngles {
|
||||||
|
|
||||||
|
public Matrix4f tieTransform;
|
||||||
|
public Couple<Matrix4f> railTransforms;
|
||||||
|
public BlockPos lightPosition;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
public static class GirderAngles {
|
||||||
|
|
||||||
|
public Couple<Matrix4f> beams;
|
||||||
|
public Couple<Couple<Matrix4f>> beamCaps;
|
||||||
|
public BlockPos lightPosition;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
public SegmentAngles[] getBakedSegments() {
|
||||||
|
if (bakedSegments != null)
|
||||||
|
return bakedSegments;
|
||||||
|
|
||||||
|
int segmentCount = getSegmentCount();
|
||||||
|
bakedSegments = new SegmentAngles[segmentCount + 1];
|
||||||
|
Couple<Vec3> previousOffsets = null;
|
||||||
|
|
||||||
|
for (BezierConnection.Segment segment : this) {
|
||||||
|
int i = segment.index;
|
||||||
|
boolean end = i == 0 || i == segmentCount;
|
||||||
|
|
||||||
|
SegmentAngles angles = bakedSegments[i] = new SegmentAngles();
|
||||||
|
Couple<Vec3> railOffsets = Couple.create(segment.position.add(segment.normal.scale(.965f)),
|
||||||
|
segment.position.subtract(segment.normal.scale(.965f)));
|
||||||
|
Vec3 railMiddle = railOffsets.getFirst()
|
||||||
|
.add(railOffsets.getSecond())
|
||||||
|
.scale(.5);
|
||||||
|
|
||||||
|
if (previousOffsets == null) {
|
||||||
|
previousOffsets = railOffsets;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tie
|
||||||
|
Vec3 prevMiddle = previousOffsets.getFirst()
|
||||||
|
.add(previousOffsets.getSecond())
|
||||||
|
.scale(.5);
|
||||||
|
Vec3 tieAngles = TrackRenderer.getModelAngles(segment.normal, railMiddle.subtract(prevMiddle));
|
||||||
|
angles.lightPosition = new BlockPos(railMiddle);
|
||||||
|
|
||||||
|
MatrixTransformStack mts = new MatrixTransformStack();
|
||||||
|
mts.translate(prevMiddle)
|
||||||
|
.rotateYRadians(tieAngles.y)
|
||||||
|
.rotateXRadians(tieAngles.x)
|
||||||
|
.rotateZRadians(tieAngles.z)
|
||||||
|
.translate(-1 / 2f, -2 / 16f - 1 / 256f, 0);
|
||||||
|
angles.tieTransform = mts.unwrap()
|
||||||
|
.last()
|
||||||
|
.pose();
|
||||||
|
angles.railTransforms = Couple.create(null, null);
|
||||||
|
|
||||||
|
// Rails
|
||||||
|
float scale = end ? 2.2f : 2.1f;
|
||||||
|
for (boolean first : Iterate.trueAndFalse) {
|
||||||
|
Vec3 railI = railOffsets.get(first);
|
||||||
|
Vec3 prevI = previousOffsets.get(first);
|
||||||
|
Vec3 diff = railI.subtract(prevI);
|
||||||
|
Vec3 anglesI = TrackRenderer.getModelAngles(segment.normal, diff);
|
||||||
|
|
||||||
|
mts = new MatrixTransformStack();
|
||||||
|
mts.translate(prevI)
|
||||||
|
.rotateYRadians(anglesI.y)
|
||||||
|
.rotateXRadians(anglesI.x)
|
||||||
|
.rotateZRadians(anglesI.z)
|
||||||
|
.translate(0, -2 / 16f + (i % 2 == 0 ? 1 : -1) / 2048f - 1 / 256f, -1 / 32f)
|
||||||
|
.scale(1, 1, (float) diff.length() * scale);
|
||||||
|
angles.railTransforms.set(first, mts.unwrap()
|
||||||
|
.last()
|
||||||
|
.pose());
|
||||||
|
}
|
||||||
|
|
||||||
|
previousOffsets = railOffsets;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bakedSegments;
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
public GirderAngles[] getBakedGirders() {
|
||||||
|
if (bakedGirders != null)
|
||||||
|
return bakedGirders;
|
||||||
|
|
||||||
|
int segmentCount = getSegmentCount();
|
||||||
|
bakedGirders = new GirderAngles[segmentCount + 1];
|
||||||
|
Couple<Couple<Vec3>> previousOffsets = null;
|
||||||
|
|
||||||
|
for (BezierConnection.Segment segment : this) {
|
||||||
|
int i = segment.index;
|
||||||
|
boolean end = i == 0 || i == segmentCount;
|
||||||
|
GirderAngles angles = bakedGirders[i] = new GirderAngles();
|
||||||
|
|
||||||
|
Vec3 leftGirder = segment.position.add(segment.normal.scale(.965f));
|
||||||
|
Vec3 rightGirder = segment.position.subtract(segment.normal.scale(.965f));
|
||||||
|
Vec3 upNormal = segment.derivative.normalize()
|
||||||
|
.cross(segment.normal);
|
||||||
|
Vec3 firstGirderOffset = upNormal.scale(-8 / 16f);
|
||||||
|
Vec3 secondGirderOffset = upNormal.scale(-10 / 16f);
|
||||||
|
Vec3 leftTop = segment.position.add(segment.normal.scale(1))
|
||||||
|
.add(firstGirderOffset);
|
||||||
|
Vec3 rightTop = segment.position.subtract(segment.normal.scale(1))
|
||||||
|
.add(firstGirderOffset);
|
||||||
|
Vec3 leftBottom = leftTop.add(secondGirderOffset);
|
||||||
|
Vec3 rightBottom = rightTop.add(secondGirderOffset);
|
||||||
|
|
||||||
|
angles.lightPosition = new BlockPos(leftGirder.add(rightGirder)
|
||||||
|
.scale(.5));
|
||||||
|
|
||||||
|
Couple<Couple<Vec3>> offsets =
|
||||||
|
Couple.create(Couple.create(leftTop, rightTop), Couple.create(leftBottom, rightBottom));
|
||||||
|
|
||||||
|
if (previousOffsets == null) {
|
||||||
|
previousOffsets = offsets;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
angles.beams = Couple.create(null, null);
|
||||||
|
angles.beamCaps = Couple.create(Couple.create(null, null), Couple.create(null, null));
|
||||||
|
float scale = end ? 2.3f : 2.2f;
|
||||||
|
|
||||||
|
for (boolean first : Iterate.trueAndFalse) {
|
||||||
|
|
||||||
|
// Middle
|
||||||
|
Vec3 currentBeam = offsets.getFirst()
|
||||||
|
.get(first)
|
||||||
|
.add(offsets.getSecond()
|
||||||
|
.get(first))
|
||||||
|
.scale(.5);
|
||||||
|
Vec3 previousBeam = previousOffsets.getFirst()
|
||||||
|
.get(first)
|
||||||
|
.add(previousOffsets.getSecond()
|
||||||
|
.get(first))
|
||||||
|
.scale(.5);
|
||||||
|
Vec3 beamDiff = currentBeam.subtract(previousBeam);
|
||||||
|
Vec3 beamAngles = TrackRenderer.getModelAngles(segment.normal, beamDiff);
|
||||||
|
|
||||||
|
MatrixTransformStack mts = new MatrixTransformStack();
|
||||||
|
mts.translate(previousBeam)
|
||||||
|
.rotateYRadians(beamAngles.y)
|
||||||
|
.rotateXRadians(beamAngles.x)
|
||||||
|
.rotateZRadians(beamAngles.z)
|
||||||
|
.translate(0, 2 / 16f + (segment.index % 2 == 0 ? 1 : -1) / 2048f - 1 / 1024f, -1 / 32f)
|
||||||
|
.scale(1, 1, (float) beamDiff.length() * scale);
|
||||||
|
angles.beams.set(first, mts.unwrap()
|
||||||
|
.last()
|
||||||
|
.pose());
|
||||||
|
|
||||||
|
// Caps
|
||||||
|
for (boolean top : Iterate.trueAndFalse) {
|
||||||
|
Vec3 current = offsets.get(top)
|
||||||
|
.get(first);
|
||||||
|
Vec3 previous = previousOffsets.get(top)
|
||||||
|
.get(first);
|
||||||
|
Vec3 diff = current.subtract(previous);
|
||||||
|
Vec3 capAngles = TrackRenderer.getModelAngles(segment.normal, diff);
|
||||||
|
|
||||||
|
mts = new MatrixTransformStack();
|
||||||
|
mts.translate(previous)
|
||||||
|
.rotateYRadians(capAngles.y)
|
||||||
|
.rotateXRadians(capAngles.x)
|
||||||
|
.rotateZRadians(capAngles.z)
|
||||||
|
.translate(0, 2 / 16f + (segment.index % 2 == 0 ? 1 : -1) / 2048f - 1 / 1024f, -1 / 32f)
|
||||||
|
.rotateZ(top ? 0 : 0)
|
||||||
|
.scale(1, 1, (float) diff.length() * scale);
|
||||||
|
angles.beamCaps.get(top)
|
||||||
|
.set(first, mts.unwrap()
|
||||||
|
.last()
|
||||||
|
.pose());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
previousOffsets = offsets;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return bakedGirders;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,15 +19,17 @@ import com.jozufozu.flywheel.util.transform.TransformStack;
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
import com.simibubi.create.AllBlockPartials;
|
import com.simibubi.create.AllBlockPartials;
|
||||||
import com.simibubi.create.content.logistics.trains.BezierConnection;
|
import com.simibubi.create.content.logistics.trains.BezierConnection;
|
||||||
|
import com.simibubi.create.content.logistics.trains.BezierConnection.GirderAngles;
|
||||||
|
import com.simibubi.create.content.logistics.trains.BezierConnection.SegmentAngles;
|
||||||
|
import com.simibubi.create.foundation.utility.Couple;
|
||||||
import com.simibubi.create.foundation.utility.Iterate;
|
import com.simibubi.create.foundation.utility.Iterate;
|
||||||
|
|
||||||
import net.minecraft.client.renderer.RenderType;
|
import net.minecraft.client.renderer.RenderType;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.world.phys.Vec3;
|
|
||||||
|
|
||||||
public class TrackInstance extends BlockEntityInstance<TrackTileEntity> {
|
public class TrackInstance extends BlockEntityInstance<TrackTileEntity> {
|
||||||
|
|
||||||
private List<BezierInstance> instances;
|
private List<BezierTrackInstance> instances;
|
||||||
|
|
||||||
public TrackInstance(MaterialManager materialManager, TrackTileEntity track) {
|
public TrackInstance(MaterialManager materialManager, TrackTileEntity track) {
|
||||||
super(materialManager, track);
|
super(materialManager, track);
|
||||||
|
@ -37,47 +39,52 @@ public class TrackInstance extends BlockEntityInstance<TrackTileEntity> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update() {
|
public void update() {
|
||||||
if (blockEntity.connections.stream().allMatch(Map::isEmpty)) {
|
if (blockEntity.connections.stream()
|
||||||
|
.allMatch(Map::isEmpty)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
instances = blockEntity.connections.stream()
|
instances = blockEntity.connections.stream()
|
||||||
.flatMap(FlwUtil::mapValues)
|
.flatMap(FlwUtil::mapValues)
|
||||||
.map(this::createInstance)
|
.map(this::createInstance)
|
||||||
.filter(Objects::nonNull)
|
.filter(Objects::nonNull)
|
||||||
.toList();
|
.toList();
|
||||||
LightUpdater.get(world).addListener(this);
|
LightUpdater.get(world)
|
||||||
|
.addListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ImmutableBox getVolume() {
|
public ImmutableBox getVolume() {
|
||||||
List<BlockPos> out = new ArrayList<>();
|
List<BlockPos> out = new ArrayList<>();
|
||||||
out.addAll(blockEntity.connections.getFirst()
|
out.addAll(blockEntity.connections.getFirst()
|
||||||
.keySet());
|
.keySet());
|
||||||
out.addAll(blockEntity.connections.getSecond()
|
out.addAll(blockEntity.connections.getSecond()
|
||||||
.keySet());
|
.keySet());
|
||||||
return GridAlignedBB.containingAll(out);
|
return GridAlignedBB.containingAll(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateLight() {
|
public void updateLight() {
|
||||||
if (instances == null) return;
|
if (instances == null)
|
||||||
instances.forEach(BezierInstance::updateLight);
|
return;
|
||||||
|
instances.forEach(BezierTrackInstance::updateLight);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private BezierInstance createInstance(BezierConnection bc) {
|
private BezierTrackInstance createInstance(BezierConnection bc) {
|
||||||
if (!bc.isPrimary()) return null;
|
if (!bc.isPrimary())
|
||||||
return new BezierInstance(bc);
|
return null;
|
||||||
|
return new BezierTrackInstance(bc);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void remove() {
|
public void remove() {
|
||||||
if (instances == null) return;
|
if (instances == null)
|
||||||
instances.forEach(BezierInstance::delete);
|
return;
|
||||||
|
instances.forEach(BezierTrackInstance::delete);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class BezierInstance {
|
private class BezierTrackInstance {
|
||||||
|
|
||||||
private final ModelData[] ties;
|
private final ModelData[] ties;
|
||||||
private final ModelData[] left;
|
private final ModelData[] left;
|
||||||
|
@ -86,17 +93,20 @@ public class TrackInstance extends BlockEntityInstance<TrackTileEntity> {
|
||||||
private final BlockPos[] leftLightPos;
|
private final BlockPos[] leftLightPos;
|
||||||
private final BlockPos[] rightLightPos;
|
private final BlockPos[] rightLightPos;
|
||||||
|
|
||||||
private BezierInstance(BezierConnection bc) {
|
private @Nullable GirderInstance girder;
|
||||||
|
|
||||||
|
private BezierTrackInstance(BezierConnection bc) {
|
||||||
BlockPos tePosition = bc.tePositions.getFirst();
|
BlockPos tePosition = bc.tePositions.getFirst();
|
||||||
|
girder = bc.hasGirder ? new GirderInstance(bc) : null;
|
||||||
|
|
||||||
PoseStack pose = new PoseStack();
|
PoseStack pose = new PoseStack();
|
||||||
TransformStack.cast(pose)
|
TransformStack.cast(pose)
|
||||||
.translate(getInstancePosition())
|
.translate(getInstancePosition())
|
||||||
.nudge((int) bc.tePositions.getFirst()
|
.nudge((int) bc.tePositions.getFirst()
|
||||||
.asLong());
|
.asLong());
|
||||||
|
|
||||||
var mat = materialManager.cutout(RenderType.cutoutMipped())
|
var mat = materialManager.cutout(RenderType.cutoutMipped())
|
||||||
.material(Materials.TRANSFORMED);
|
.material(Materials.TRANSFORMED);
|
||||||
|
|
||||||
int segCount = bc.getSegmentCount();
|
int segCount = bc.getSegmentCount();
|
||||||
ties = new ModelData[segCount];
|
ties = new ModelData[segCount];
|
||||||
|
@ -107,82 +117,120 @@ public class TrackInstance extends BlockEntityInstance<TrackTileEntity> {
|
||||||
rightLightPos = new BlockPos[segCount];
|
rightLightPos = new BlockPos[segCount];
|
||||||
|
|
||||||
mat.getModel(AllBlockPartials.TRACK_TIE)
|
mat.getModel(AllBlockPartials.TRACK_TIE)
|
||||||
.createInstances(ties);
|
.createInstances(ties);
|
||||||
mat.getModel(AllBlockPartials.TRACK_SEGMENT_LEFT)
|
mat.getModel(AllBlockPartials.TRACK_SEGMENT_LEFT)
|
||||||
.createInstances(left);
|
.createInstances(left);
|
||||||
mat.getModel(AllBlockPartials.TRACK_SEGMENT_RIGHT)
|
mat.getModel(AllBlockPartials.TRACK_SEGMENT_RIGHT)
|
||||||
.createInstances(right);
|
.createInstances(right);
|
||||||
|
|
||||||
Vec3 leftPrevious = null;
|
SegmentAngles[] segments = bc.getBakedSegments();
|
||||||
Vec3 rightPrevious = null;
|
for (int i = 1; i < segments.length; i++) {
|
||||||
|
SegmentAngles segment = segments[i];
|
||||||
|
var modelIndex = i - 1;
|
||||||
|
|
||||||
for (BezierConnection.Segment segment : bc) {
|
ties[modelIndex].setTransform(pose)
|
||||||
Vec3 left = segment.position.add(segment.normal.scale(.965f));
|
.mulPose(segment.tieTransform);
|
||||||
Vec3 right = segment.position.subtract(segment.normal.scale(.965f));
|
tiesLightPos[modelIndex] = segment.lightPosition.offset(tePosition);
|
||||||
|
|
||||||
if (leftPrevious != null) {
|
for (boolean first : Iterate.trueAndFalse) {
|
||||||
var modelIndex = segment.index - 1;
|
(first ? this.left : this.right)[modelIndex].setTransform(pose)
|
||||||
{
|
.mulPose(segment.railTransforms.get(first));
|
||||||
// Tie
|
(first ? leftLightPos : rightLightPos)[modelIndex] = segment.lightPosition.offset(tePosition);
|
||||||
Vec3 railMiddle = left.add(right)
|
|
||||||
.scale(.5);
|
|
||||||
Vec3 prevMiddle = leftPrevious.add(rightPrevious)
|
|
||||||
.scale(.5);
|
|
||||||
|
|
||||||
var tie = ties[modelIndex].setTransform(pose);
|
|
||||||
Vec3 diff = railMiddle.subtract(prevMiddle);
|
|
||||||
Vec3 angles = TrackRenderer.getModelAngles(segment.normal, diff);
|
|
||||||
|
|
||||||
tie.translate(prevMiddle)
|
|
||||||
.rotateYRadians(angles.y)
|
|
||||||
.rotateXRadians(angles.x)
|
|
||||||
.rotateZRadians(angles.z)
|
|
||||||
.translate(-1 / 2f, -2 / 16f - 1 / 256f, 0);
|
|
||||||
tiesLightPos[modelIndex] = new BlockPos(railMiddle).offset(tePosition);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rails
|
|
||||||
for (boolean first : Iterate.trueAndFalse) {
|
|
||||||
Vec3 railI = first ? left : right;
|
|
||||||
Vec3 prevI = first ? leftPrevious : rightPrevious;
|
|
||||||
|
|
||||||
var rail = (first ? this.left : this.right)[modelIndex].setTransform(pose);
|
|
||||||
Vec3 diff = railI.subtract(prevI);
|
|
||||||
Vec3 angles = TrackRenderer.getModelAngles(segment.normal, diff);
|
|
||||||
|
|
||||||
rail.translate(prevI)
|
|
||||||
.rotateYRadians(angles.y)
|
|
||||||
.rotateXRadians(angles.x)
|
|
||||||
.rotateZRadians(angles.z)
|
|
||||||
.translate(0, -2 / 16f + (segment.index % 2 == 0 ? 1 : -1) / 2048f - 1 / 256f, 0)
|
|
||||||
.scale(1, 1, (float) diff.length() * 2.1f);
|
|
||||||
(first ? leftLightPos : rightLightPos)[modelIndex] = new BlockPos(prevI).offset(tePosition);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
leftPrevious = left;
|
|
||||||
rightPrevious = right;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updateLight();
|
updateLight();
|
||||||
}
|
}
|
||||||
|
|
||||||
void delete() {
|
void delete() {
|
||||||
for (ModelData d : ties) d.delete();
|
for (ModelData d : ties)
|
||||||
for (ModelData d : left) d.delete();
|
d.delete();
|
||||||
for (ModelData d : right) d.delete();
|
for (ModelData d : left)
|
||||||
|
d.delete();
|
||||||
|
for (ModelData d : right)
|
||||||
|
d.delete();
|
||||||
|
if (girder != null)
|
||||||
|
girder.delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateLight() {
|
void updateLight() {
|
||||||
for (int i = 0; i < ties.length; i++) {
|
for (int i = 0; i < ties.length; i++)
|
||||||
ties[i].updateLight(world, tiesLightPos[i]);
|
ties[i].updateLight(world, tiesLightPos[i]);
|
||||||
}
|
for (int i = 0; i < left.length; i++)
|
||||||
for (int i = 0; i < left.length; i++) {
|
|
||||||
left[i].updateLight(world, leftLightPos[i]);
|
left[i].updateLight(world, leftLightPos[i]);
|
||||||
}
|
for (int i = 0; i < right.length; i++)
|
||||||
for (int i = 0; i < right.length; i++) {
|
|
||||||
right[i].updateLight(world, rightLightPos[i]);
|
right[i].updateLight(world, rightLightPos[i]);
|
||||||
}
|
if (girder != null)
|
||||||
|
girder.updateLight();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class GirderInstance {
|
||||||
|
|
||||||
|
private final Couple<ModelData[]> beams;
|
||||||
|
private final Couple<Couple<ModelData[]>> beamCaps;
|
||||||
|
private final BlockPos[] lightPos;
|
||||||
|
|
||||||
|
private GirderInstance(BezierConnection bc) {
|
||||||
|
BlockPos tePosition = bc.tePositions.getFirst();
|
||||||
|
PoseStack pose = new PoseStack();
|
||||||
|
TransformStack.cast(pose)
|
||||||
|
.translate(getInstancePosition())
|
||||||
|
.nudge((int) bc.tePositions.getFirst()
|
||||||
|
.asLong());
|
||||||
|
|
||||||
|
var mat = materialManager.cutout(RenderType.cutoutMipped())
|
||||||
|
.material(Materials.TRANSFORMED);
|
||||||
|
|
||||||
|
int segCount = bc.getSegmentCount();
|
||||||
|
beams = Couple.create(() -> new ModelData[segCount]);
|
||||||
|
beamCaps = Couple.create(() -> Couple.create(() -> new ModelData[segCount]));
|
||||||
|
lightPos = new BlockPos[segCount];
|
||||||
|
beams.forEach(mat.getModel(AllBlockPartials.GIRDER_SEGMENT_2)::createInstances);
|
||||||
|
beamCaps.forEach(c -> c.forEach(mat.getModel(AllBlockPartials.GIRDER_SEGMENT)::createInstances));
|
||||||
|
|
||||||
|
GirderAngles[] bakedGirders = bc.getBakedGirders();
|
||||||
|
for (int i = 1; i < bakedGirders.length; i++) {
|
||||||
|
GirderAngles segment = bakedGirders[i];
|
||||||
|
var modelIndex = i - 1;
|
||||||
|
lightPos[modelIndex] = segment.lightPosition.offset(tePosition);
|
||||||
|
|
||||||
|
for (boolean first : Iterate.trueAndFalse) {
|
||||||
|
beams.get(first)[modelIndex].setTransform(pose)
|
||||||
|
.mulPose(segment.beams.get(first));
|
||||||
|
for (boolean top : Iterate.trueAndFalse)
|
||||||
|
beamCaps.get(top)
|
||||||
|
.get(first)[modelIndex].setTransform(pose)
|
||||||
|
.mulPose(segment.beamCaps.get(top)
|
||||||
|
.get(first));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updateLight();
|
||||||
|
}
|
||||||
|
|
||||||
|
void delete() {
|
||||||
|
beams.forEach(arr -> {
|
||||||
|
for (ModelData d : arr)
|
||||||
|
d.delete();
|
||||||
|
});
|
||||||
|
beamCaps.forEach(c -> c.forEach(arr -> {
|
||||||
|
for (ModelData d : arr)
|
||||||
|
d.delete();
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateLight() {
|
||||||
|
beams.forEach(arr -> {
|
||||||
|
for (int i = 0; i < arr.length; i++)
|
||||||
|
arr[i].updateLight(world, lightPos[i]);
|
||||||
|
});
|
||||||
|
beamCaps.forEach(c -> c.forEach(arr -> {
|
||||||
|
for (int i = 0; i < arr.length; i++)
|
||||||
|
arr[i].updateLight(world, lightPos[i]);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,27 @@
|
||||||
package com.simibubi.create.content.logistics.trains.track;
|
package com.simibubi.create.content.logistics.trains.track;
|
||||||
|
|
||||||
|
import static com.simibubi.create.AllBlockPartials.GIRDER_SEGMENT;
|
||||||
|
import static com.simibubi.create.AllBlockPartials.GIRDER_SEGMENT_2;
|
||||||
|
import static com.simibubi.create.AllBlockPartials.TRACK_SEGMENT_LEFT;
|
||||||
|
import static com.simibubi.create.AllBlockPartials.TRACK_SEGMENT_RIGHT;
|
||||||
|
import static com.simibubi.create.AllBlockPartials.TRACK_TIE;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.Backend;
|
import com.jozufozu.flywheel.backend.Backend;
|
||||||
import com.jozufozu.flywheel.repack.joml.Math;
|
import com.jozufozu.flywheel.repack.joml.Math;
|
||||||
import com.jozufozu.flywheel.util.transform.TransformStack;
|
import com.jozufozu.flywheel.util.transform.TransformStack;
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||||
import com.simibubi.create.AllBlockPartials;
|
|
||||||
import com.simibubi.create.content.logistics.trains.BezierConnection;
|
import com.simibubi.create.content.logistics.trains.BezierConnection;
|
||||||
|
import com.simibubi.create.content.logistics.trains.BezierConnection.GirderAngles;
|
||||||
|
import com.simibubi.create.content.logistics.trains.BezierConnection.SegmentAngles;
|
||||||
import com.simibubi.create.foundation.render.CachedBufferer;
|
import com.simibubi.create.foundation.render.CachedBufferer;
|
||||||
import com.simibubi.create.foundation.render.SuperByteBuffer;
|
|
||||||
import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer;
|
import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer;
|
||||||
import com.simibubi.create.foundation.utility.AngleHelper;
|
import com.simibubi.create.foundation.utility.AngleHelper;
|
||||||
import com.simibubi.create.foundation.utility.Iterate;
|
import com.simibubi.create.foundation.utility.Iterate;
|
||||||
import com.simibubi.create.foundation.utility.VecHelper;
|
import com.simibubi.create.foundation.utility.VecHelper;
|
||||||
|
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.multiplayer.ClientLevel;
|
||||||
import net.minecraft.client.renderer.LevelRenderer;
|
import net.minecraft.client.renderer.LevelRenderer;
|
||||||
import net.minecraft.client.renderer.MultiBufferSource;
|
import net.minecraft.client.renderer.MultiBufferSource;
|
||||||
import net.minecraft.client.renderer.RenderType;
|
import net.minecraft.client.renderer.RenderType;
|
||||||
|
@ -23,6 +30,7 @@ import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Direction.Axis;
|
import net.minecraft.core.Direction.Axis;
|
||||||
import net.minecraft.util.Mth;
|
import net.minecraft.util.Mth;
|
||||||
import net.minecraft.world.level.block.Blocks;
|
import net.minecraft.world.level.block.Blocks;
|
||||||
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
import net.minecraft.world.phys.Vec3;
|
import net.minecraft.world.phys.Vec3;
|
||||||
|
|
||||||
public class TrackRenderer extends SafeTileEntityRenderer<TrackTileEntity> {
|
public class TrackRenderer extends SafeTileEntityRenderer<TrackTileEntity> {
|
||||||
|
@ -46,162 +54,63 @@ public class TrackRenderer extends SafeTileEntityRenderer<TrackTileEntity> {
|
||||||
|
|
||||||
ms.pushPose();
|
ms.pushPose();
|
||||||
BlockPos tePosition = bc.tePositions.getFirst();
|
BlockPos tePosition = bc.tePositions.getFirst();
|
||||||
|
BlockState air = Blocks.AIR.defaultBlockState();
|
||||||
|
ClientLevel level = Minecraft.getInstance().level;
|
||||||
|
SegmentAngles[] segments = bc.getBakedSegments();
|
||||||
|
|
||||||
TransformStack.cast(ms)
|
TransformStack.cast(ms)
|
||||||
.nudge((int) tePosition.asLong());
|
.nudge((int) tePosition.asLong());
|
||||||
|
|
||||||
if (bc.hasGirder)
|
renderGirder(bc, ms, vb, tePosition);
|
||||||
renderGirder(bc, ms, vb, tePosition);
|
|
||||||
|
|
||||||
Vec3 previous1 = null;
|
for (int i = 1; i < segments.length; i++) {
|
||||||
Vec3 previous2 = null;
|
SegmentAngles segment = segments[i];
|
||||||
|
int light = LevelRenderer.getLightColor(level, segment.lightPosition.offset(tePosition));
|
||||||
|
|
||||||
for (BezierConnection.Segment segment : bc) {
|
CachedBufferer.partial(TRACK_TIE, air)
|
||||||
Vec3 rail1 = segment.position.add(segment.normal.scale(.965f));
|
.mulPose(segment.tieTransform)
|
||||||
Vec3 rail2 = segment.position.subtract(segment.normal.scale(.965f));
|
.disableDiffuseMult()
|
||||||
|
.light(light)
|
||||||
|
.renderInto(ms, vb);
|
||||||
|
|
||||||
if (previous1 != null) {
|
for (boolean first : Iterate.trueAndFalse)
|
||||||
int centralLight = 0;
|
CachedBufferer.partial(first ? TRACK_SEGMENT_LEFT : TRACK_SEGMENT_RIGHT, air)
|
||||||
|
.mulPose(segment.railTransforms.get(first))
|
||||||
{
|
.disableDiffuseMult()
|
||||||
// Tie
|
.light(light)
|
||||||
Vec3 railMiddle = rail1.add(rail2)
|
.renderInto(ms, vb);
|
||||||
.scale(.5);
|
|
||||||
Vec3 prevMiddle = previous1.add(previous2)
|
|
||||||
.scale(.5);
|
|
||||||
Vec3 diff = railMiddle.subtract(prevMiddle);
|
|
||||||
Vec3 angles = getModelAngles(segment.normal, diff);
|
|
||||||
|
|
||||||
centralLight = LevelRenderer.getLightColor(Minecraft.getInstance().level,
|
|
||||||
new BlockPos(railMiddle).offset(tePosition));
|
|
||||||
|
|
||||||
SuperByteBuffer sbb =
|
|
||||||
CachedBufferer.partial(AllBlockPartials.TRACK_TIE, Blocks.AIR.defaultBlockState());
|
|
||||||
|
|
||||||
sbb.translate(prevMiddle)
|
|
||||||
.rotateYRadians(angles.y)
|
|
||||||
.rotateXRadians(angles.x)
|
|
||||||
.rotateZRadians(angles.z)
|
|
||||||
.translate(-1 / 2f, -2 / 16f - 1 / 256f, 0);
|
|
||||||
|
|
||||||
sbb.disableDiffuseMult()
|
|
||||||
.light(centralLight);
|
|
||||||
sbb.renderInto(ms, vb);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rails
|
|
||||||
for (boolean first : Iterate.trueAndFalse) {
|
|
||||||
Vec3 railI = first ? rail1 : rail2;
|
|
||||||
Vec3 prevI = first ? previous1 : previous2;
|
|
||||||
Vec3 diff = railI.subtract(prevI);
|
|
||||||
Vec3 angles = getModelAngles(segment.normal, diff);
|
|
||||||
|
|
||||||
SuperByteBuffer sbb = CachedBufferer.partial(
|
|
||||||
first ? AllBlockPartials.TRACK_SEGMENT_LEFT : AllBlockPartials.TRACK_SEGMENT_RIGHT,
|
|
||||||
Blocks.AIR.defaultBlockState());
|
|
||||||
|
|
||||||
sbb.translate(prevI)
|
|
||||||
.rotateYRadians(angles.y)
|
|
||||||
.rotateXRadians(angles.x)
|
|
||||||
.rotateZRadians(angles.z)
|
|
||||||
.translate(0, -2 / 16f + (segment.index % 2 == 0 ? 1 : -1) / 2048f - 1 / 256f, 0)
|
|
||||||
.scale(1, 1, (float) diff.length() * 2.1f);
|
|
||||||
|
|
||||||
sbb.disableDiffuseMult()
|
|
||||||
.light(LevelRenderer.getLightColor(Minecraft.getInstance().level,
|
|
||||||
new BlockPos(prevI).offset(tePosition)));
|
|
||||||
sbb.renderInto(ms, vb);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
previous1 = rail1;
|
|
||||||
previous2 = rail2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ms.popPose();
|
ms.popPose();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void renderGirder(BezierConnection bc, PoseStack ms, VertexConsumer vb, BlockPos tePosition) {
|
private static void renderGirder(BezierConnection bc, PoseStack ms, VertexConsumer vb, BlockPos tePosition) {
|
||||||
Vec3 previousG11 = null;
|
if (!bc.hasGirder)
|
||||||
Vec3 previousG21 = null;
|
return;
|
||||||
Vec3 previousG12 = null;
|
|
||||||
Vec3 previousG22 = null;
|
|
||||||
|
|
||||||
for (BezierConnection.Segment segment : bc) {
|
BlockState air = Blocks.AIR.defaultBlockState();
|
||||||
Vec3 rail1 = segment.position.add(segment.normal.scale(.965f));
|
ClientLevel level = Minecraft.getInstance().level;
|
||||||
Vec3 rail2 = segment.position.subtract(segment.normal.scale(.965f));
|
GirderAngles[] girders = bc.getBakedGirders();
|
||||||
|
|
||||||
Vec3 upNormal = segment.derivative.normalize()
|
for (int i = 1; i < girders.length; i++) {
|
||||||
.cross(segment.normal);
|
GirderAngles segment = girders[i];
|
||||||
Vec3 firstGirderOffset = upNormal.scale(-8 / 16f);
|
int light = LevelRenderer.getLightColor(level, segment.lightPosition.offset(tePosition));
|
||||||
Vec3 secondGirderOffset = upNormal.scale(-10 / 16f);
|
|
||||||
Vec3 g11 = segment.position.add(segment.normal.scale(1))
|
|
||||||
.add(firstGirderOffset);
|
|
||||||
Vec3 g12 = segment.position.subtract(segment.normal.scale(1))
|
|
||||||
.add(firstGirderOffset);
|
|
||||||
Vec3 g21 = g11.add(secondGirderOffset);
|
|
||||||
Vec3 g22 = g12.add(secondGirderOffset);
|
|
||||||
|
|
||||||
if (previousG11 != null) {
|
for (boolean first : Iterate.trueAndFalse) {
|
||||||
Vec3 railMiddle = rail1.add(rail2)
|
CachedBufferer.partial(GIRDER_SEGMENT_2, air)
|
||||||
.scale(.5);
|
.mulPose(segment.beams.get(first))
|
||||||
int centralLight = LevelRenderer.getLightColor(Minecraft.getInstance().level,
|
.disableDiffuseMult()
|
||||||
new BlockPos(railMiddle).offset(tePosition));
|
.light(light)
|
||||||
Vec3 normal = segment.normal;
|
.renderInto(ms, vb);
|
||||||
float l = 2.2f;
|
|
||||||
|
|
||||||
for (boolean first : Iterate.trueAndFalse) {
|
for (boolean top : Iterate.trueAndFalse)
|
||||||
for (boolean top : Iterate.trueAndFalse) {
|
CachedBufferer.partial(GIRDER_SEGMENT, air)
|
||||||
Vec3 railI = top ? first ? g11 : g12 : first ? g21 : g22;
|
.mulPose(segment.beamCaps.get(top)
|
||||||
Vec3 prevI = top ? first ? previousG11 : previousG12 : first ? previousG21 : previousG22;
|
.get(first))
|
||||||
Vec3 diff = railI.subtract(prevI);
|
.disableDiffuseMult()
|
||||||
Vec3 angles = getModelAngles(normal, diff);
|
.light(light)
|
||||||
|
.renderInto(ms, vb);
|
||||||
SuperByteBuffer sbb2 =
|
|
||||||
CachedBufferer.partial(AllBlockPartials.GIRDER_SEGMENT, Blocks.AIR.defaultBlockState());
|
|
||||||
|
|
||||||
sbb2.translate(prevI)
|
|
||||||
.rotateYRadians(angles.y)
|
|
||||||
.rotateXRadians(angles.x)
|
|
||||||
.rotateZRadians(angles.z)
|
|
||||||
.translate(0, 2 / 16f + (segment.index % 2 == 0 ? 1 : -1) / 2048f - 1 / 1024f, 0)
|
|
||||||
.rotateZ(top ? 0 : 0)
|
|
||||||
.scale(1, 1, (float) diff.length() * l);
|
|
||||||
|
|
||||||
sbb2.disableDiffuseMult()
|
|
||||||
.light(centralLight);
|
|
||||||
sbb2.renderInto(ms, vb);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
Vec3 railI = (first ? g11 : g12).add(first ? g21 : g22)
|
|
||||||
.scale(.5);
|
|
||||||
Vec3 prevI = (first ? previousG11 : previousG12).add(first ? previousG21 : previousG22)
|
|
||||||
.scale(.5);
|
|
||||||
Vec3 diff = railI.subtract(prevI);
|
|
||||||
Vec3 angles = getModelAngles(normal, diff);
|
|
||||||
|
|
||||||
SuperByteBuffer sbb2 =
|
|
||||||
CachedBufferer.partial(AllBlockPartials.GIRDER_SEGMENT_2, Blocks.AIR.defaultBlockState());
|
|
||||||
|
|
||||||
sbb2.translate(prevI)
|
|
||||||
.rotateYRadians(angles.y)
|
|
||||||
.rotateXRadians(angles.x)
|
|
||||||
.rotateZRadians(angles.z)
|
|
||||||
.translate(0, 2 / 16f + (segment.index % 2 == 0 ? 1 : -1) / 2048f - 1 / 1024f, 0)
|
|
||||||
.scale(1, 1, (float) diff.length() * l);
|
|
||||||
|
|
||||||
sbb2.disableDiffuseMult()
|
|
||||||
.light(centralLight);
|
|
||||||
sbb2.renderInto(ms, vb);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
previousG11 = g11;
|
|
||||||
previousG12 = g12;
|
|
||||||
previousG21 = g21;
|
|
||||||
previousG22 = g22;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,9 +10,9 @@
|
||||||
"to": [2, 4, 8],
|
"to": [2, 4, 8],
|
||||||
"rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]},
|
"rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]},
|
||||||
"faces": {
|
"faces": {
|
||||||
"north": {"uv": [8, 1, 12, 3], "rotation": 270, "texture": "#0"},
|
"north": {"uv": [2, 5, 4, 9], "texture": "#0"},
|
||||||
"east": {"uv": [0, 5, 4, 9], "texture": "#0"},
|
"east": {"uv": [0, 5, 4, 9], "texture": "#0"},
|
||||||
"south": {"uv": [8, 1, 12, 3], "rotation": 270, "texture": "#0"},
|
"south": {"uv": [2, 5, 4, 9], "texture": "#0"},
|
||||||
"west": {"uv": [0, 5, 4, 9], "texture": "#0"}
|
"west": {"uv": [0, 5, 4, 9], "texture": "#0"}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 297 B After Width: | Height: | Size: 404 B |
Loading…
Reference in a new issue