mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-12-27 23:47:38 +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 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.Iterate;
|
||||
import com.simibubi.create.foundation.utility.VecHelper;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
|
@ -14,6 +18,8 @@ import net.minecraft.nbt.Tag;
|
|||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.util.Mth;
|
||||
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> {
|
||||
|
||||
|
@ -264,17 +270,19 @@ public class BezierConnection implements Iterable<BezierConnection.Segment> {
|
|||
public Iterator<Segment> iterator() {
|
||||
resolve();
|
||||
var offset = Vec3.atLowerCornerOf(tePositions.getFirst())
|
||||
.scale(-1)
|
||||
.add(0, 3 / 16f, 0);
|
||||
.scale(-1)
|
||||
.add(0, 3 / 16f, 0);
|
||||
return new Bezierator(this, offset);
|
||||
}
|
||||
|
||||
public static class Segment {
|
||||
|
||||
public int index;
|
||||
public Vec3 position;
|
||||
public Vec3 derivative;
|
||||
public Vec3 faceNormal;
|
||||
public Vec3 normal;
|
||||
|
||||
}
|
||||
|
||||
private static class Bezierator implements Iterator<Segment> {
|
||||
|
@ -293,16 +301,16 @@ public class BezierConnection implements Iterable<BezierConnection.Segment> {
|
|||
this.bc = bc;
|
||||
|
||||
end1 = bc.starts.getFirst()
|
||||
.add(offset);
|
||||
.add(offset);
|
||||
end2 = bc.starts.getSecond()
|
||||
.add(offset);
|
||||
.add(offset);
|
||||
|
||||
finish1 = bc.axes.getFirst()
|
||||
.scale(bc.handleLength)
|
||||
.add(end1);
|
||||
.scale(bc.handleLength)
|
||||
.add(end1);
|
||||
finish2 = bc.axes.getSecond()
|
||||
.scale(bc.handleLength)
|
||||
.add(end2);
|
||||
.scale(bc.handleLength)
|
||||
.add(end2);
|
||||
|
||||
faceNormal1 = bc.normals.getFirst();
|
||||
faceNormal2 = bc.normals.getSecond();
|
||||
|
@ -321,12 +329,203 @@ public class BezierConnection implements Iterable<BezierConnection.Segment> {
|
|||
float t = this.bc.getSegmentT(segment.index);
|
||||
segment.position = VecHelper.bezier(end1, end2, finish1, finish2, t);
|
||||
segment.derivative = VecHelper.bezierDerivative(end1, end2, finish1, finish2, t)
|
||||
.normalize();
|
||||
segment.faceNormal = faceNormal1.equals(faceNormal2) ? faceNormal1 : VecHelper.slerp(t, faceNormal1, faceNormal2);
|
||||
.normalize();
|
||||
segment.faceNormal =
|
||||
faceNormal1.equals(faceNormal2) ? faceNormal1 : VecHelper.slerp(t, faceNormal1, faceNormal2);
|
||||
segment.normal = segment.faceNormal.cross(segment.derivative)
|
||||
.normalize();
|
||||
.normalize();
|
||||
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.simibubi.create.AllBlockPartials;
|
||||
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 net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public class TrackInstance extends BlockEntityInstance<TrackTileEntity> {
|
||||
|
||||
private List<BezierInstance> instances;
|
||||
private List<BezierTrackInstance> instances;
|
||||
|
||||
public TrackInstance(MaterialManager materialManager, TrackTileEntity track) {
|
||||
super(materialManager, track);
|
||||
|
@ -37,47 +39,52 @@ public class TrackInstance extends BlockEntityInstance<TrackTileEntity> {
|
|||
|
||||
@Override
|
||||
public void update() {
|
||||
if (blockEntity.connections.stream().allMatch(Map::isEmpty)) {
|
||||
if (blockEntity.connections.stream()
|
||||
.allMatch(Map::isEmpty)) {
|
||||
return;
|
||||
}
|
||||
|
||||
instances = blockEntity.connections.stream()
|
||||
.flatMap(FlwUtil::mapValues)
|
||||
.map(this::createInstance)
|
||||
.filter(Objects::nonNull)
|
||||
.toList();
|
||||
LightUpdater.get(world).addListener(this);
|
||||
.flatMap(FlwUtil::mapValues)
|
||||
.map(this::createInstance)
|
||||
.filter(Objects::nonNull)
|
||||
.toList();
|
||||
LightUpdater.get(world)
|
||||
.addListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImmutableBox getVolume() {
|
||||
List<BlockPos> out = new ArrayList<>();
|
||||
out.addAll(blockEntity.connections.getFirst()
|
||||
.keySet());
|
||||
.keySet());
|
||||
out.addAll(blockEntity.connections.getSecond()
|
||||
.keySet());
|
||||
.keySet());
|
||||
return GridAlignedBB.containingAll(out);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateLight() {
|
||||
if (instances == null) return;
|
||||
instances.forEach(BezierInstance::updateLight);
|
||||
if (instances == null)
|
||||
return;
|
||||
instances.forEach(BezierTrackInstance::updateLight);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private BezierInstance createInstance(BezierConnection bc) {
|
||||
if (!bc.isPrimary()) return null;
|
||||
return new BezierInstance(bc);
|
||||
private BezierTrackInstance createInstance(BezierConnection bc) {
|
||||
if (!bc.isPrimary())
|
||||
return null;
|
||||
return new BezierTrackInstance(bc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
if (instances == null) return;
|
||||
instances.forEach(BezierInstance::delete);
|
||||
if (instances == null)
|
||||
return;
|
||||
instances.forEach(BezierTrackInstance::delete);
|
||||
}
|
||||
|
||||
private class BezierInstance {
|
||||
private class BezierTrackInstance {
|
||||
|
||||
private final ModelData[] ties;
|
||||
private final ModelData[] left;
|
||||
|
@ -86,17 +93,20 @@ public class TrackInstance extends BlockEntityInstance<TrackTileEntity> {
|
|||
private final BlockPos[] leftLightPos;
|
||||
private final BlockPos[] rightLightPos;
|
||||
|
||||
private BezierInstance(BezierConnection bc) {
|
||||
private @Nullable GirderInstance girder;
|
||||
|
||||
private BezierTrackInstance(BezierConnection bc) {
|
||||
BlockPos tePosition = bc.tePositions.getFirst();
|
||||
girder = bc.hasGirder ? new GirderInstance(bc) : null;
|
||||
|
||||
PoseStack pose = new PoseStack();
|
||||
TransformStack.cast(pose)
|
||||
.translate(getInstancePosition())
|
||||
.nudge((int) bc.tePositions.getFirst()
|
||||
.asLong());
|
||||
.translate(getInstancePosition())
|
||||
.nudge((int) bc.tePositions.getFirst()
|
||||
.asLong());
|
||||
|
||||
var mat = materialManager.cutout(RenderType.cutoutMipped())
|
||||
.material(Materials.TRANSFORMED);
|
||||
.material(Materials.TRANSFORMED);
|
||||
|
||||
int segCount = bc.getSegmentCount();
|
||||
ties = new ModelData[segCount];
|
||||
|
@ -107,82 +117,120 @@ public class TrackInstance extends BlockEntityInstance<TrackTileEntity> {
|
|||
rightLightPos = new BlockPos[segCount];
|
||||
|
||||
mat.getModel(AllBlockPartials.TRACK_TIE)
|
||||
.createInstances(ties);
|
||||
.createInstances(ties);
|
||||
mat.getModel(AllBlockPartials.TRACK_SEGMENT_LEFT)
|
||||
.createInstances(left);
|
||||
.createInstances(left);
|
||||
mat.getModel(AllBlockPartials.TRACK_SEGMENT_RIGHT)
|
||||
.createInstances(right);
|
||||
.createInstances(right);
|
||||
|
||||
Vec3 leftPrevious = null;
|
||||
Vec3 rightPrevious = null;
|
||||
SegmentAngles[] segments = bc.getBakedSegments();
|
||||
for (int i = 1; i < segments.length; i++) {
|
||||
SegmentAngles segment = segments[i];
|
||||
var modelIndex = i - 1;
|
||||
|
||||
for (BezierConnection.Segment segment : bc) {
|
||||
Vec3 left = segment.position.add(segment.normal.scale(.965f));
|
||||
Vec3 right = segment.position.subtract(segment.normal.scale(.965f));
|
||||
ties[modelIndex].setTransform(pose)
|
||||
.mulPose(segment.tieTransform);
|
||||
tiesLightPos[modelIndex] = segment.lightPosition.offset(tePosition);
|
||||
|
||||
if (leftPrevious != null) {
|
||||
var modelIndex = segment.index - 1;
|
||||
{
|
||||
// Tie
|
||||
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);
|
||||
}
|
||||
for (boolean first : Iterate.trueAndFalse) {
|
||||
(first ? this.left : this.right)[modelIndex].setTransform(pose)
|
||||
.mulPose(segment.railTransforms.get(first));
|
||||
(first ? leftLightPos : rightLightPos)[modelIndex] = segment.lightPosition.offset(tePosition);
|
||||
}
|
||||
|
||||
leftPrevious = left;
|
||||
rightPrevious = right;
|
||||
}
|
||||
|
||||
updateLight();
|
||||
}
|
||||
|
||||
void delete() {
|
||||
for (ModelData d : ties) d.delete();
|
||||
for (ModelData d : left) d.delete();
|
||||
for (ModelData d : right) d.delete();
|
||||
for (ModelData d : ties)
|
||||
d.delete();
|
||||
for (ModelData d : left)
|
||||
d.delete();
|
||||
for (ModelData d : right)
|
||||
d.delete();
|
||||
if (girder != null)
|
||||
girder.delete();
|
||||
}
|
||||
|
||||
void updateLight() {
|
||||
for (int i = 0; i < ties.length; i++) {
|
||||
for (int i = 0; i < ties.length; 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]);
|
||||
}
|
||||
for (int i = 0; i < right.length; i++) {
|
||||
for (int i = 0; i < right.length; 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;
|
||||
|
||||
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.repack.joml.Math;
|
||||
import com.jozufozu.flywheel.util.transform.TransformStack;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
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.GirderAngles;
|
||||
import com.simibubi.create.content.logistics.trains.BezierConnection.SegmentAngles;
|
||||
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.utility.AngleHelper;
|
||||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
import com.simibubi.create.foundation.utility.VecHelper;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.client.renderer.LevelRenderer;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
|
@ -23,6 +30,7 @@ import net.minecraft.core.BlockPos;
|
|||
import net.minecraft.core.Direction.Axis;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public class TrackRenderer extends SafeTileEntityRenderer<TrackTileEntity> {
|
||||
|
@ -46,162 +54,63 @@ public class TrackRenderer extends SafeTileEntityRenderer<TrackTileEntity> {
|
|||
|
||||
ms.pushPose();
|
||||
BlockPos tePosition = bc.tePositions.getFirst();
|
||||
BlockState air = Blocks.AIR.defaultBlockState();
|
||||
ClientLevel level = Minecraft.getInstance().level;
|
||||
SegmentAngles[] segments = bc.getBakedSegments();
|
||||
|
||||
TransformStack.cast(ms)
|
||||
.nudge((int) tePosition.asLong());
|
||||
|
||||
if (bc.hasGirder)
|
||||
renderGirder(bc, ms, vb, tePosition);
|
||||
renderGirder(bc, ms, vb, tePosition);
|
||||
|
||||
Vec3 previous1 = null;
|
||||
Vec3 previous2 = null;
|
||||
for (int i = 1; i < segments.length; i++) {
|
||||
SegmentAngles segment = segments[i];
|
||||
int light = LevelRenderer.getLightColor(level, segment.lightPosition.offset(tePosition));
|
||||
|
||||
for (BezierConnection.Segment segment : bc) {
|
||||
Vec3 rail1 = segment.position.add(segment.normal.scale(.965f));
|
||||
Vec3 rail2 = segment.position.subtract(segment.normal.scale(.965f));
|
||||
CachedBufferer.partial(TRACK_TIE, air)
|
||||
.mulPose(segment.tieTransform)
|
||||
.disableDiffuseMult()
|
||||
.light(light)
|
||||
.renderInto(ms, vb);
|
||||
|
||||
if (previous1 != null) {
|
||||
int centralLight = 0;
|
||||
|
||||
{
|
||||
// Tie
|
||||
Vec3 railMiddle = rail1.add(rail2)
|
||||
.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;
|
||||
for (boolean first : Iterate.trueAndFalse)
|
||||
CachedBufferer.partial(first ? TRACK_SEGMENT_LEFT : TRACK_SEGMENT_RIGHT, air)
|
||||
.mulPose(segment.railTransforms.get(first))
|
||||
.disableDiffuseMult()
|
||||
.light(light)
|
||||
.renderInto(ms, vb);
|
||||
}
|
||||
|
||||
ms.popPose();
|
||||
}
|
||||
|
||||
private static void renderGirder(BezierConnection bc, PoseStack ms, VertexConsumer vb, BlockPos tePosition) {
|
||||
Vec3 previousG11 = null;
|
||||
Vec3 previousG21 = null;
|
||||
Vec3 previousG12 = null;
|
||||
Vec3 previousG22 = null;
|
||||
if (!bc.hasGirder)
|
||||
return;
|
||||
|
||||
for (BezierConnection.Segment segment : bc) {
|
||||
Vec3 rail1 = segment.position.add(segment.normal.scale(.965f));
|
||||
Vec3 rail2 = segment.position.subtract(segment.normal.scale(.965f));
|
||||
BlockState air = Blocks.AIR.defaultBlockState();
|
||||
ClientLevel level = Minecraft.getInstance().level;
|
||||
GirderAngles[] girders = bc.getBakedGirders();
|
||||
|
||||
Vec3 upNormal = segment.derivative.normalize()
|
||||
.cross(segment.normal);
|
||||
Vec3 firstGirderOffset = upNormal.scale(-8 / 16f);
|
||||
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);
|
||||
for (int i = 1; i < girders.length; i++) {
|
||||
GirderAngles segment = girders[i];
|
||||
int light = LevelRenderer.getLightColor(level, segment.lightPosition.offset(tePosition));
|
||||
|
||||
if (previousG11 != null) {
|
||||
Vec3 railMiddle = rail1.add(rail2)
|
||||
.scale(.5);
|
||||
int centralLight = LevelRenderer.getLightColor(Minecraft.getInstance().level,
|
||||
new BlockPos(railMiddle).offset(tePosition));
|
||||
Vec3 normal = segment.normal;
|
||||
float l = 2.2f;
|
||||
for (boolean first : Iterate.trueAndFalse) {
|
||||
CachedBufferer.partial(GIRDER_SEGMENT_2, air)
|
||||
.mulPose(segment.beams.get(first))
|
||||
.disableDiffuseMult()
|
||||
.light(light)
|
||||
.renderInto(ms, vb);
|
||||
|
||||
for (boolean first : Iterate.trueAndFalse) {
|
||||
for (boolean top : Iterate.trueAndFalse) {
|
||||
Vec3 railI = top ? first ? g11 : g12 : first ? g21 : g22;
|
||||
Vec3 prevI = top ? first ? previousG11 : previousG12 : first ? previousG21 : previousG22;
|
||||
Vec3 diff = railI.subtract(prevI);
|
||||
Vec3 angles = getModelAngles(normal, diff);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
for (boolean top : Iterate.trueAndFalse)
|
||||
CachedBufferer.partial(GIRDER_SEGMENT, air)
|
||||
.mulPose(segment.beamCaps.get(top)
|
||||
.get(first))
|
||||
.disableDiffuseMult()
|
||||
.light(light)
|
||||
.renderInto(ms, vb);
|
||||
}
|
||||
|
||||
previousG11 = g11;
|
||||
previousG12 = g12;
|
||||
previousG21 = g21;
|
||||
previousG22 = g22;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,9 +10,9 @@
|
|||
"to": [2, 4, 8],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]},
|
||||
"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"},
|
||||
"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"}
|
||||
}
|
||||
}
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 297 B After Width: | Height: | Size: 404 B |
Loading…
Reference in a new issue