mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-12-29 08:27:03 +01:00
Merge remote-tracking branch 'origin/mc1.15/dev' into mc1.16/dev
# Conflicts: # src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionCollider.java # src/main/java/com/simibubi/create/content/curiosities/TreeFertilizerItem.java
This commit is contained in:
commit
78fbb52ddc
15 changed files with 306 additions and 108 deletions
|
@ -50,10 +50,7 @@ import com.simibubi.create.content.contraptions.components.press.PressInstance;
|
||||||
import com.simibubi.create.content.contraptions.components.saw.SawInstance;
|
import com.simibubi.create.content.contraptions.components.saw.SawInstance;
|
||||||
import com.simibubi.create.content.contraptions.components.saw.SawRenderer;
|
import com.simibubi.create.content.contraptions.components.saw.SawRenderer;
|
||||||
import com.simibubi.create.content.contraptions.components.saw.SawTileEntity;
|
import com.simibubi.create.content.contraptions.components.saw.SawTileEntity;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.bearing.BearingRenderer;
|
import com.simibubi.create.content.contraptions.components.structureMovement.bearing.*;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.bearing.ClockworkBearingTileEntity;
|
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.bearing.MechanicalBearingTileEntity;
|
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.bearing.WindmillBearingTileEntity;
|
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.chassis.ChassisTileEntity;
|
import com.simibubi.create.content.contraptions.components.structureMovement.chassis.ChassisTileEntity;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.chassis.StickerInstance;
|
import com.simibubi.create.content.contraptions.components.structureMovement.chassis.StickerInstance;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.chassis.StickerRenderer;
|
import com.simibubi.create.content.contraptions.components.structureMovement.chassis.StickerRenderer;
|
||||||
|
@ -380,21 +377,21 @@ public class AllTileEntities {
|
||||||
|
|
||||||
public static final TileEntityEntry<WindmillBearingTileEntity> WINDMILL_BEARING = Create.registrate()
|
public static final TileEntityEntry<WindmillBearingTileEntity> WINDMILL_BEARING = Create.registrate()
|
||||||
.tileEntity("windmill_bearing", WindmillBearingTileEntity::new)
|
.tileEntity("windmill_bearing", WindmillBearingTileEntity::new)
|
||||||
.instance(() -> BackHalfShaftInstance::new)
|
.instance(() -> BearingInstance::new)
|
||||||
.validBlocks(AllBlocks.WINDMILL_BEARING)
|
.validBlocks(AllBlocks.WINDMILL_BEARING)
|
||||||
.renderer(() -> BearingRenderer::new)
|
.renderer(() -> BearingRenderer::new)
|
||||||
.register();
|
.register();
|
||||||
|
|
||||||
public static final TileEntityEntry<MechanicalBearingTileEntity> MECHANICAL_BEARING = Create.registrate()
|
public static final TileEntityEntry<MechanicalBearingTileEntity> MECHANICAL_BEARING = Create.registrate()
|
||||||
.tileEntity("mechanical_bearing", MechanicalBearingTileEntity::new)
|
.tileEntity("mechanical_bearing", MechanicalBearingTileEntity::new)
|
||||||
.instance(() -> BackHalfShaftInstance::new)
|
.instance(() -> BearingInstance::new)
|
||||||
.validBlocks(AllBlocks.MECHANICAL_BEARING)
|
.validBlocks(AllBlocks.MECHANICAL_BEARING)
|
||||||
.renderer(() -> BearingRenderer::new)
|
.renderer(() -> BearingRenderer::new)
|
||||||
.register();
|
.register();
|
||||||
|
|
||||||
public static final TileEntityEntry<ClockworkBearingTileEntity> CLOCKWORK_BEARING = Create.registrate()
|
public static final TileEntityEntry<ClockworkBearingTileEntity> CLOCKWORK_BEARING = Create.registrate()
|
||||||
.tileEntity("clockwork_bearing", ClockworkBearingTileEntity::new)
|
.tileEntity("clockwork_bearing", ClockworkBearingTileEntity::new)
|
||||||
.instance(() -> BackHalfShaftInstance::new)
|
.instance(() -> BearingInstance::new)
|
||||||
.validBlocks(AllBlocks.CLOCKWORK_BEARING)
|
.validBlocks(AllBlocks.CLOCKWORK_BEARING)
|
||||||
.renderer(() -> BearingRenderer::new)
|
.renderer(() -> BearingRenderer::new)
|
||||||
.register();
|
.register();
|
||||||
|
|
|
@ -13,6 +13,7 @@ import org.apache.commons.lang3.mutable.MutableInt;
|
||||||
import org.apache.commons.lang3.mutable.MutableObject;
|
import org.apache.commons.lang3.mutable.MutableObject;
|
||||||
|
|
||||||
import com.google.common.base.Predicates;
|
import com.google.common.base.Predicates;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.simibubi.create.AllBlocks;
|
import com.simibubi.create.AllBlocks;
|
||||||
import com.simibubi.create.AllMovementBehaviours;
|
import com.simibubi.create.AllMovementBehaviours;
|
||||||
import com.simibubi.create.content.contraptions.components.actors.BlockBreakingMovementBehaviour;
|
import com.simibubi.create.content.contraptions.components.actors.BlockBreakingMovementBehaviour;
|
||||||
|
@ -221,6 +222,7 @@ public class ContraptionCollider {
|
||||||
totalResponse = VecHelper.rotate(totalResponse, yawOffset, Axis.Y);
|
totalResponse = VecHelper.rotate(totalResponse, yawOffset, Axis.Y);
|
||||||
collisionNormal = rotationMatrix.transform(collisionNormal);
|
collisionNormal = rotationMatrix.transform(collisionNormal);
|
||||||
collisionNormal = VecHelper.rotate(collisionNormal, yawOffset, Axis.Y);
|
collisionNormal = VecHelper.rotate(collisionNormal, yawOffset, Axis.Y);
|
||||||
|
collisionNormal = collisionNormal.normalize();
|
||||||
collisionLocation = rotationMatrix.transform(collisionLocation);
|
collisionLocation = rotationMatrix.transform(collisionLocation);
|
||||||
collisionLocation = VecHelper.rotate(collisionLocation, yawOffset, Axis.Y);
|
collisionLocation = VecHelper.rotate(collisionLocation, yawOffset, Axis.Y);
|
||||||
rotationMatrix.transpose();
|
rotationMatrix.transpose();
|
||||||
|
@ -248,17 +250,12 @@ public class ContraptionCollider {
|
||||||
boolean hasNormal = !collisionNormal.equals(Vector3d.ZERO);
|
boolean hasNormal = !collisionNormal.equals(Vector3d.ZERO);
|
||||||
boolean anyCollision = hardCollision || temporalCollision;
|
boolean anyCollision = hardCollision || temporalCollision;
|
||||||
|
|
||||||
if (bounce > 0 && hasNormal && anyCollision) {
|
if (bounce > 0 && hasNormal && anyCollision && bounceEntity(entity, collisionNormal, contraptionEntity, bounce)) {
|
||||||
collisionNormal = collisionNormal.normalize();
|
|
||||||
Vector3d newNormal = collisionNormal.crossProduct(collisionNormal.crossProduct(entityMotionNoTemporal))
|
|
||||||
.normalize();
|
|
||||||
if (bounceEntity(entity, newNormal, contraptionEntity, bounce)) {
|
|
||||||
entity.world.playSound(playerType == PlayerType.CLIENT ? (PlayerEntity) entity : null,
|
entity.world.playSound(playerType == PlayerType.CLIENT ? (PlayerEntity) entity : null,
|
||||||
entity.getX(), entity.getY(), entity.getZ(), SoundEvents.BLOCK_SLIME_BLOCK_FALL,
|
entity.getX(), entity.getY(), entity.getZ(), SoundEvents.BLOCK_SLIME_BLOCK_FALL,
|
||||||
SoundCategory.BLOCKS, .5f, 1);
|
SoundCategory.BLOCKS, .5f, 1);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (temporalCollision) {
|
if (temporalCollision) {
|
||||||
double idealVerticalMotion = motionResponse.y;
|
double idealVerticalMotion = motionResponse.y;
|
||||||
|
@ -288,7 +285,6 @@ public class ContraptionCollider {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bounce == 0 && slide > 0 && hasNormal && anyCollision && rotation.hasVerticalRotation()) {
|
if (bounce == 0 && slide > 0 && hasNormal && anyCollision && rotation.hasVerticalRotation()) {
|
||||||
collisionNormal = collisionNormal.normalize();
|
|
||||||
Vector3d motionIn = entityMotionNoTemporal.mul(0, 1, 0)
|
Vector3d motionIn = entityMotionNoTemporal.mul(0, 1, 0)
|
||||||
.add(0, -.01f, 0);
|
.add(0, -.01f, 0);
|
||||||
Vector3d slideNormal = collisionNormal.crossProduct(motionIn.crossProduct(collisionNormal))
|
Vector3d slideNormal = collisionNormal.crossProduct(motionIn.crossProduct(collisionNormal))
|
||||||
|
@ -346,35 +342,14 @@ public class ContraptionCollider {
|
||||||
return false;
|
return false;
|
||||||
if (entity.bypassesLandingEffects())
|
if (entity.bypassesLandingEffects())
|
||||||
return false;
|
return false;
|
||||||
if (normal.equals(Vector3d.ZERO))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
Vector3d contraptionVec = Vector3d.ZERO;
|
|
||||||
Vector3d contactPointMotion = contraption.getContactPointMotion(entity.getPositionVec());
|
Vector3d contactPointMotion = contraption.getContactPointMotion(entity.getPositionVec());
|
||||||
Vector3d motion = entity.getMotion()
|
Vector3d motion = entity.getMotion().subtract(contactPointMotion);
|
||||||
.subtract(contactPointMotion);
|
Vector3d deltav = normal.scale(factor*2*motion.dotProduct(normal));
|
||||||
|
if (deltav.dotProduct(deltav) < 0.1f)
|
||||||
Vector3d v2 = motion.crossProduct(normal)
|
|
||||||
.normalize();
|
|
||||||
if (v2 != Vector3d.ZERO)
|
|
||||||
contraptionVec = normal.scale(contraptionVec.dotProduct(normal))
|
|
||||||
.add(v2.scale(contraptionVec.dotProduct(v2)));
|
|
||||||
else
|
|
||||||
v2 = normal.crossProduct(normal.add(Math.random(), Math.random(), Math.random()))
|
|
||||||
.normalize();
|
|
||||||
|
|
||||||
Vector3d v3 = normal.crossProduct(v2);
|
|
||||||
motion = motion.subtract(contraptionVec);
|
|
||||||
Vector3d lr = new Vector3d(factor * motion.dotProduct(normal), -motion.dotProduct(v2), -motion.dotProduct(v3));
|
|
||||||
|
|
||||||
if (lr.dotProduct(lr) > 1 / 16f) {
|
|
||||||
Vector3d newMot = contactPointMotion.add(normal.x * lr.x + v2.x * lr.y + v3.x * lr.z,
|
|
||||||
normal.y * lr.x + v2.y * lr.y + v3.y * lr.z, normal.z * lr.x + v2.z * lr.y + v3.z * lr.z);
|
|
||||||
entity.setMotion(newMot);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
entity.setMotion(entity.getMotion().subtract(deltav));
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Vector3d getWorldToLocalTranslation(Entity entity, AbstractContraptionEntity contraptionEntity) {
|
public static Vector3d getWorldToLocalTranslation(Entity entity, AbstractContraptionEntity contraptionEntity) {
|
||||||
|
|
|
@ -8,15 +8,6 @@ public class NonStationaryLighter<C extends Contraption> extends ContraptionLigh
|
||||||
super(contraption);
|
super(contraption);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected GridAlignedBB contraptionBoundsToVolume(GridAlignedBB bounds) {
|
|
||||||
bounds.grow(2); // so we have at least enough data on the edges to avoid artifacts and have smooth lighting
|
|
||||||
bounds.minY = Math.max(bounds.minY, 0);
|
|
||||||
bounds.maxY = Math.min(bounds.maxY, 255);
|
|
||||||
|
|
||||||
return bounds;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void tick(RenderedContraption owner) {
|
public void tick(RenderedContraption owner) {
|
||||||
super.tick(owner);
|
super.tick(owner);
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
package com.simibubi.create.content.contraptions.components.structureMovement.bearing;
|
||||||
|
|
||||||
|
import net.minecraft.client.renderer.Quaternion;
|
||||||
|
import net.minecraft.client.renderer.Vector3f;
|
||||||
|
import net.minecraft.state.properties.BlockStateProperties;
|
||||||
|
import net.minecraft.util.Direction;
|
||||||
|
|
||||||
|
import com.simibubi.create.AllBlockPartials;
|
||||||
|
import com.simibubi.create.content.contraptions.base.BackHalfShaftInstance;
|
||||||
|
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
|
||||||
|
import com.simibubi.create.foundation.render.backend.core.OrientedData;
|
||||||
|
import com.simibubi.create.foundation.render.backend.instancing.IDynamicInstance;
|
||||||
|
import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer;
|
||||||
|
import com.simibubi.create.foundation.utility.AngleHelper;
|
||||||
|
import com.simibubi.create.foundation.utility.AnimationTickHolder;
|
||||||
|
|
||||||
|
public class BearingInstance<B extends KineticTileEntity & IBearingTileEntity> extends BackHalfShaftInstance implements IDynamicInstance {
|
||||||
|
final B bearing;
|
||||||
|
|
||||||
|
final OrientedData topInstance;
|
||||||
|
|
||||||
|
final Vector3f rotationAxis;
|
||||||
|
final Quaternion blockOrientation;
|
||||||
|
|
||||||
|
public BearingInstance(InstancedTileRenderer<?> modelManager, B tile) {
|
||||||
|
super(modelManager, tile);
|
||||||
|
this.bearing = tile;
|
||||||
|
|
||||||
|
Direction facing = blockState.get(BlockStateProperties.FACING);
|
||||||
|
rotationAxis = Direction.getFacingFromAxis(Direction.AxisDirection.POSITIVE, axis).getUnitVector();
|
||||||
|
|
||||||
|
blockOrientation = getBlockStateOrientation(facing);
|
||||||
|
|
||||||
|
AllBlockPartials top =
|
||||||
|
bearing.isWoodenTop() ? AllBlockPartials.BEARING_TOP_WOODEN : AllBlockPartials.BEARING_TOP;
|
||||||
|
|
||||||
|
topInstance = getOrientedMaterial().getModel(top, blockState).createInstance();
|
||||||
|
|
||||||
|
topInstance.setPosition(getInstancePosition()).setRotation(blockOrientation);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void beginFrame() {
|
||||||
|
|
||||||
|
float interpolatedAngle = bearing.getInterpolatedAngle(AnimationTickHolder.getPartialTicks() - 1);
|
||||||
|
Quaternion rot = rotationAxis.getDegreesQuaternion(interpolatedAngle);
|
||||||
|
|
||||||
|
rot.multiply(blockOrientation);
|
||||||
|
|
||||||
|
topInstance.setRotation(rot);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateLight() {
|
||||||
|
super.updateLight();
|
||||||
|
relight(pos, topInstance);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remove() {
|
||||||
|
super.remove();
|
||||||
|
topInstance.delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
static Quaternion getBlockStateOrientation(Direction facing) {
|
||||||
|
Quaternion orientation;
|
||||||
|
|
||||||
|
if (facing.getAxis().isHorizontal()) {
|
||||||
|
orientation = Vector3f.POSITIVE_Y.getDegreesQuaternion(AngleHelper.horizontalAngle(facing.getOpposite()));
|
||||||
|
} else {
|
||||||
|
orientation = Quaternion.IDENTITY.copy();
|
||||||
|
}
|
||||||
|
|
||||||
|
orientation.multiply(Vector3f.POSITIVE_X.getDegreesQuaternion(-90 - AngleHelper.verticalAngle(facing)));
|
||||||
|
return orientation;
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,6 +5,7 @@ import com.simibubi.create.AllBlockPartials;
|
||||||
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
|
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
|
||||||
import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer;
|
import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer;
|
||||||
import com.simibubi.create.foundation.render.SuperByteBuffer;
|
import com.simibubi.create.foundation.render.SuperByteBuffer;
|
||||||
|
import com.simibubi.create.foundation.render.backend.FastRenderDispatcher;
|
||||||
import com.simibubi.create.foundation.utility.AngleHelper;
|
import com.simibubi.create.foundation.utility.AngleHelper;
|
||||||
|
|
||||||
import net.minecraft.client.renderer.IRenderTypeBuffer;
|
import net.minecraft.client.renderer.IRenderTypeBuffer;
|
||||||
|
@ -22,6 +23,9 @@ public class BearingRenderer extends KineticTileEntityRenderer {
|
||||||
@Override
|
@Override
|
||||||
protected void renderSafe(KineticTileEntity te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer,
|
protected void renderSafe(KineticTileEntity te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer,
|
||||||
int light, int overlay) {
|
int light, int overlay) {
|
||||||
|
|
||||||
|
if (FastRenderDispatcher.available(te.getWorld())) return;
|
||||||
|
|
||||||
super.renderSafe(te, partialTicks, ms, buffer, light, overlay);
|
super.renderSafe(te, partialTicks, ms, buffer, light, overlay);
|
||||||
|
|
||||||
IBearingTileEntity bearingTe = (IBearingTileEntity) te;
|
IBearingTileEntity bearingTe = (IBearingTileEntity) te;
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
package com.simibubi.create.content.contraptions.components.structureMovement.bearing;
|
||||||
|
|
||||||
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.client.renderer.Quaternion;
|
||||||
|
import net.minecraft.client.renderer.Vector3f;
|
||||||
|
import net.minecraft.state.properties.BlockStateProperties;
|
||||||
|
import net.minecraft.util.Direction;
|
||||||
|
|
||||||
|
import com.simibubi.create.AllBlockPartials;
|
||||||
|
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
|
||||||
|
import com.simibubi.create.content.contraptions.components.structureMovement.render.ActorInstance;
|
||||||
|
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionKineticRenderer;
|
||||||
|
import com.simibubi.create.foundation.render.backend.core.OrientedData;
|
||||||
|
import com.simibubi.create.foundation.utility.AnimationTickHolder;
|
||||||
|
|
||||||
|
public class StabilizedBearingInstance extends ActorInstance {
|
||||||
|
|
||||||
|
final OrientedData topInstance;
|
||||||
|
|
||||||
|
final Direction facing;
|
||||||
|
final Vector3f rotationAxis;
|
||||||
|
final Quaternion blockOrientation;
|
||||||
|
|
||||||
|
public StabilizedBearingInstance(ContraptionKineticRenderer modelManager, MovementContext context) {
|
||||||
|
super(modelManager, context);
|
||||||
|
|
||||||
|
BlockState blockState = context.state;
|
||||||
|
|
||||||
|
facing = blockState.get(BlockStateProperties.FACING);
|
||||||
|
rotationAxis = Direction.getFacingFromAxis(Direction.AxisDirection.POSITIVE, facing.getAxis()).getUnitVector();
|
||||||
|
|
||||||
|
blockOrientation = BearingInstance.getBlockStateOrientation(facing);
|
||||||
|
|
||||||
|
topInstance = modelManager.getOrientedMaterial().getModel(AllBlockPartials.BEARING_TOP, blockState).createInstance();
|
||||||
|
|
||||||
|
topInstance.setPosition(context.localPos)
|
||||||
|
.setRotation(blockOrientation)
|
||||||
|
.setBlockLight(localBlockLight());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void beginFrame() {
|
||||||
|
float counterRotationAngle = StabilizedBearingMovementBehaviour.getCounterRotationAngle(context, facing, AnimationTickHolder.getPartialTicks());
|
||||||
|
|
||||||
|
Quaternion rotation = rotationAxis.getDegreesQuaternion(counterRotationAngle);
|
||||||
|
|
||||||
|
rotation.multiply(blockOrientation);
|
||||||
|
|
||||||
|
topInstance.setRotation(rotation);
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,12 +7,16 @@ import com.simibubi.create.content.contraptions.components.structureMovement.Con
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour;
|
import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
|
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.OrientedContraptionEntity;
|
import com.simibubi.create.content.contraptions.components.structureMovement.OrientedContraptionEntity;
|
||||||
|
import com.simibubi.create.content.contraptions.components.structureMovement.render.ActorInstance;
|
||||||
|
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionKineticRenderer;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher;
|
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher;
|
||||||
import com.simibubi.create.foundation.render.SuperByteBuffer;
|
import com.simibubi.create.foundation.render.SuperByteBuffer;
|
||||||
|
import com.simibubi.create.foundation.render.backend.FastRenderDispatcher;
|
||||||
import com.simibubi.create.foundation.utility.AngleHelper;
|
import com.simibubi.create.foundation.utility.AngleHelper;
|
||||||
import com.simibubi.create.foundation.utility.AnimationTickHolder;
|
import com.simibubi.create.foundation.utility.AnimationTickHolder;
|
||||||
|
|
||||||
import net.minecraft.client.renderer.IRenderTypeBuffer;
|
import net.minecraft.client.renderer.IRenderTypeBuffer;
|
||||||
|
import net.minecraft.client.renderer.Quaternion;
|
||||||
import net.minecraft.client.renderer.RenderType;
|
import net.minecraft.client.renderer.RenderType;
|
||||||
import net.minecraft.state.properties.BlockStateProperties;
|
import net.minecraft.state.properties.BlockStateProperties;
|
||||||
import net.minecraft.util.Direction;
|
import net.minecraft.util.Direction;
|
||||||
|
@ -20,27 +24,56 @@ import net.minecraft.util.Direction.Axis;
|
||||||
import net.minecraftforge.api.distmarker.Dist;
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
public class StabilizedBearingMovementBehaviour extends MovementBehaviour {
|
public class StabilizedBearingMovementBehaviour extends MovementBehaviour {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@OnlyIn(Dist.CLIENT)
|
@OnlyIn(Dist.CLIENT)
|
||||||
public void renderInContraption(MovementContext context, MatrixStack ms, MatrixStack msLocal,
|
public void renderInContraption(MovementContext context, MatrixStack ms, MatrixStack msLocal,
|
||||||
IRenderTypeBuffer buffer) {
|
IRenderTypeBuffer buffer) {
|
||||||
|
if (FastRenderDispatcher.available()) return;
|
||||||
|
|
||||||
Direction facing = context.state.get(BlockStateProperties.FACING);
|
Direction facing = context.state.get(BlockStateProperties.FACING);
|
||||||
AllBlockPartials top = AllBlockPartials.BEARING_TOP;
|
AllBlockPartials top = AllBlockPartials.BEARING_TOP;
|
||||||
SuperByteBuffer superBuffer = top.renderOn(context.state);
|
SuperByteBuffer superBuffer = top.renderOn(context.state);
|
||||||
float renderPartialTicks = AnimationTickHolder.getPartialTicks();
|
float renderPartialTicks = AnimationTickHolder.getPartialTicks();
|
||||||
|
|
||||||
// rotate to match blockstate
|
// rotate to match blockstate
|
||||||
Axis axis = facing.getAxis();
|
Quaternion orientation = BearingInstance.getBlockStateOrientation(facing);
|
||||||
if (axis.isHorizontal())
|
|
||||||
superBuffer.rotateCentered(Direction.UP,
|
|
||||||
AngleHelper.rad(AngleHelper.horizontalAngle(facing.getOpposite())));
|
|
||||||
superBuffer.rotateCentered(Direction.EAST, AngleHelper.rad(-90 - AngleHelper.verticalAngle(facing)));
|
|
||||||
|
|
||||||
// rotate against parent
|
// rotate against parent
|
||||||
|
float angle = getCounterRotationAngle(context, facing, renderPartialTicks) * facing.getAxisDirection().getOffset();
|
||||||
|
|
||||||
|
Quaternion rotation = facing.getUnitVector().getDegreesQuaternion(angle);
|
||||||
|
|
||||||
|
rotation.multiply(orientation);
|
||||||
|
|
||||||
|
orientation = rotation;
|
||||||
|
|
||||||
|
superBuffer.rotateCentered(orientation);
|
||||||
|
|
||||||
|
// render
|
||||||
|
superBuffer.light(msLocal.peek()
|
||||||
|
.getModel(), ContraptionRenderDispatcher.getLightOnContraption(context));
|
||||||
|
superBuffer.renderInto(ms, buffer.getBuffer(RenderType.getSolid()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasSpecialInstancedRendering() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public ActorInstance createInstance(ContraptionKineticRenderer kr, MovementContext context) {
|
||||||
|
return new StabilizedBearingInstance(kr, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
static float getCounterRotationAngle(MovementContext context, Direction facing, float renderPartialTicks) {
|
||||||
float offset = 0;
|
float offset = 0;
|
||||||
int offsetMultiplier = facing.getAxisDirection().getOffset();
|
|
||||||
|
Axis axis = facing.getAxis();
|
||||||
|
|
||||||
AbstractContraptionEntity entity = context.contraption.entity;
|
AbstractContraptionEntity entity = context.contraption.entity;
|
||||||
if (entity instanceof ControlledContraptionEntity) {
|
if (entity instanceof ControlledContraptionEntity) {
|
||||||
|
@ -58,13 +91,8 @@ public class StabilizedBearingMovementBehaviour extends MovementBehaviour {
|
||||||
offset = -orientedCE.getPitch(renderPartialTicks);
|
offset = -orientedCE.getPitch(renderPartialTicks);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (offset != 0)
|
return offset;
|
||||||
superBuffer.rotateCentered(Direction.UP, AngleHelper.rad(offset * offsetMultiplier));
|
|
||||||
|
|
||||||
// render
|
|
||||||
superBuffer.light(msLocal.peek()
|
|
||||||
.getModel(), ContraptionRenderDispatcher.getLightOnContraption(context));
|
|
||||||
superBuffer.renderInto(ms, buffer.getBuffer(RenderType.getSolid()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,8 +31,8 @@ public class TreeFertilizerItem extends Item {
|
||||||
return ActionResultType.SUCCESS;
|
return ActionResultType.SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
TreesDreamWorld world = new TreesDreamWorld((ServerWorld) context.getWorld(), context.getPos());
|
|
||||||
BlockPos saplingPos = context.getPos();
|
BlockPos saplingPos = context.getPos();
|
||||||
|
TreesDreamWorld world = new TreesDreamWorld((ServerWorld) context.getWorld(), saplingPos);
|
||||||
|
|
||||||
for (BlockPos pos : BlockPos.getAllInBoxMutable(-1, 0, -1, 1, 0, 1)) {
|
for (BlockPos pos : BlockPos.getAllInBoxMutable(-1, 0, -1, 1, 0, 1)) {
|
||||||
if (context.getWorld()
|
if (context.getWorld()
|
||||||
|
@ -45,8 +45,8 @@ public class TreeFertilizerItem extends Item {
|
||||||
state.with(SaplingBlock.STAGE, 1));
|
state.with(SaplingBlock.STAGE, 1));
|
||||||
|
|
||||||
for (BlockPos pos : world.blocksAdded.keySet()) {
|
for (BlockPos pos : world.blocksAdded.keySet()) {
|
||||||
BlockPos actualPos = pos.add(saplingPos)
|
BlockPos actualPos = pos.add(saplingPos).down(10);
|
||||||
.down(10);
|
BlockState newState = world.blocksAdded.get(pos);
|
||||||
|
|
||||||
// Don't replace Bedrock
|
// Don't replace Bedrock
|
||||||
if (context.getWorld()
|
if (context.getWorld()
|
||||||
|
@ -54,21 +54,15 @@ public class TreeFertilizerItem extends Item {
|
||||||
.getBlockHardness(context.getWorld(), actualPos) == -1)
|
.getBlockHardness(context.getWorld(), actualPos) == -1)
|
||||||
continue;
|
continue;
|
||||||
// Don't replace solid blocks with leaves
|
// Don't replace solid blocks with leaves
|
||||||
if (!world.getBlockState(pos)
|
if (!newState.isNormalCube(world, pos)
|
||||||
.isNormalCube(world, pos)
|
|
||||||
&& !context.getWorld()
|
&& !context.getWorld()
|
||||||
.getBlockState(actualPos)
|
.getBlockState(actualPos)
|
||||||
.getCollisionShape(context.getWorld(), actualPos)
|
.getCollisionShape(context.getWorld(), actualPos)
|
||||||
.isEmpty())
|
.isEmpty())
|
||||||
continue;
|
continue;
|
||||||
if (world.getBlockState(pos)
|
|
||||||
.getBlock() == Blocks.GRASS_BLOCK
|
|
||||||
|| world.getBlockState(pos)
|
|
||||||
.getBlock() == Blocks.PODZOL)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
context.getWorld()
|
context.getWorld()
|
||||||
.setBlockState(actualPos, world.getBlockState(pos));
|
.setBlockState(actualPos, newState);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (context.getPlayer() != null && !context.getPlayer()
|
if (context.getPlayer() != null && !context.getPlayer()
|
||||||
|
@ -84,21 +78,27 @@ public class TreeFertilizerItem extends Item {
|
||||||
|
|
||||||
private class TreesDreamWorld extends PlacementSimulationServerWorld {
|
private class TreesDreamWorld extends PlacementSimulationServerWorld {
|
||||||
private final BlockPos saplingPos;
|
private final BlockPos saplingPos;
|
||||||
|
private final BlockState soil;
|
||||||
|
|
||||||
protected TreesDreamWorld(ServerWorld wrapped, BlockPos saplingPos) {
|
protected TreesDreamWorld(ServerWorld wrapped, BlockPos saplingPos) {
|
||||||
super(wrapped);
|
super(wrapped);
|
||||||
this.saplingPos = saplingPos;
|
this.saplingPos = saplingPos;
|
||||||
|
soil = wrapped.getBlockState(saplingPos.down());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BlockState getBlockState(BlockPos pos) {
|
public BlockState getBlockState(BlockPos pos) {
|
||||||
if (pos.getY() <= 9)
|
if (pos.getY() <= 9)
|
||||||
return world.getBlockState(saplingPos.down());
|
return soil;
|
||||||
return super.getBlockState(pos);
|
return super.getBlockState(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean setBlockState(BlockPos pos, BlockState newState, int flags) {
|
||||||
|
if (newState.getBlock() == Blocks.PODZOL)
|
||||||
|
return true;
|
||||||
|
return super.setBlockState(pos, newState, flags);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,9 +30,15 @@ public class ArmInstance extends SingleRotatingInstance implements IDynamicInsta
|
||||||
|
|
||||||
private final ArrayList<ModelData> models;
|
private final ArrayList<ModelData> models;
|
||||||
private final ArmTileEntity arm;
|
private final ArmTileEntity arm;
|
||||||
|
private final Boolean ceiling;
|
||||||
|
|
||||||
private boolean firstTick = true;
|
private boolean firstTick = true;
|
||||||
|
|
||||||
|
private float baseAngle = Float.NaN;
|
||||||
|
private float lowerArmAngle = Float.NaN;
|
||||||
|
private float upperArmAngle = Float.NaN;
|
||||||
|
private float headAngle = Float.NaN;
|
||||||
|
|
||||||
public ArmInstance(InstancedTileRenderer<?> modelManager, ArmTileEntity tile) {
|
public ArmInstance(InstancedTileRenderer<?> modelManager, ArmTileEntity tile) {
|
||||||
super(modelManager, tile);
|
super(modelManager, tile);
|
||||||
|
|
||||||
|
@ -51,31 +57,49 @@ public class ArmInstance extends SingleRotatingInstance implements IDynamicInsta
|
||||||
clawGrips = Lists.newArrayList(clawGrip1, clawGrip2);
|
clawGrips = Lists.newArrayList(clawGrip1, clawGrip2);
|
||||||
models = Lists.newArrayList(base, lowerBody, upperBody, head, claw, clawGrip1, clawGrip2);
|
models = Lists.newArrayList(base, lowerBody, upperBody, head, claw, clawGrip1, clawGrip2);
|
||||||
arm = tile;
|
arm = tile;
|
||||||
|
ceiling = blockState.get(ArmBlock.CEILING);
|
||||||
|
|
||||||
animateArm(false);
|
animateArm(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void beginFrame() {
|
public void beginFrame() {
|
||||||
|
if (arm.phase == ArmTileEntity.Phase.DANCING) {
|
||||||
|
animateArm(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
boolean settled = arm.baseAngle.settled() && arm.lowerArmAngle.settled() && arm.upperArmAngle.settled() && arm.headAngle.settled();
|
float pt = AnimationTickHolder.getPartialTicks();
|
||||||
boolean rave = arm.phase == ArmTileEntity.Phase.DANCING;
|
|
||||||
|
|
||||||
if (!settled || rave || firstTick)
|
float baseAngleNow = this.arm.baseAngle.get(pt);
|
||||||
animateArm(rave);
|
float lowerArmAngleNow = this.arm.lowerArmAngle.get(pt);
|
||||||
|
float upperArmAngleNow = this.arm.upperArmAngle.get(pt);
|
||||||
|
float headAngleNow = this.arm.headAngle.get(pt);
|
||||||
|
|
||||||
|
boolean settled = MathHelper.epsilonEquals(baseAngle, baseAngleNow)
|
||||||
|
&& MathHelper.epsilonEquals(lowerArmAngle, lowerArmAngleNow)
|
||||||
|
&& MathHelper.epsilonEquals(upperArmAngle, upperArmAngleNow)
|
||||||
|
&& MathHelper.epsilonEquals(headAngle, headAngleNow);
|
||||||
|
|
||||||
|
this.baseAngle = baseAngleNow;
|
||||||
|
this.lowerArmAngle = lowerArmAngleNow;
|
||||||
|
this.upperArmAngle = upperArmAngleNow;
|
||||||
|
this.headAngle = headAngleNow;
|
||||||
|
|
||||||
|
if (!settled || firstTick)
|
||||||
|
animateArm(false);
|
||||||
|
|
||||||
if (settled)
|
if (settled)
|
||||||
firstTick = false;
|
firstTick = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void animateArm(boolean rave) {
|
private void animateArm(boolean rave) {
|
||||||
float pt = AnimationTickHolder.getPartialTicks();
|
|
||||||
int color = 0xFFFFFF;
|
|
||||||
|
|
||||||
float baseAngle = this.arm.baseAngle.get(pt);
|
int color;
|
||||||
float lowerArmAngle = this.arm.lowerArmAngle.get(pt) - 135;
|
float baseAngle;
|
||||||
float upperArmAngle = this.arm.upperArmAngle.get(pt) - 90;
|
float lowerArmAngle;
|
||||||
float headAngle = this.arm.headAngle.get(pt);
|
float upperArmAngle;
|
||||||
|
float headAngle;
|
||||||
|
|
||||||
if (rave) {
|
if (rave) {
|
||||||
float renderTick = AnimationTickHolder.getRenderTime(this.arm.getWorld()) + (tile.hashCode() % 64);
|
float renderTick = AnimationTickHolder.getRenderTime(this.arm.getWorld()) + (tile.hashCode() % 64);
|
||||||
|
@ -83,7 +107,15 @@ public class ArmInstance extends SingleRotatingInstance implements IDynamicInsta
|
||||||
lowerArmAngle = MathHelper.lerp((MathHelper.sin(renderTick / 4) + 1) / 2, -45, 15);
|
lowerArmAngle = MathHelper.lerp((MathHelper.sin(renderTick / 4) + 1) / 2, -45, 15);
|
||||||
upperArmAngle = MathHelper.lerp((MathHelper.sin(renderTick / 8) + 1) / 4, -45, 95);
|
upperArmAngle = MathHelper.lerp((MathHelper.sin(renderTick / 8) + 1) / 4, -45, 95);
|
||||||
headAngle = -lowerArmAngle;
|
headAngle = -lowerArmAngle;
|
||||||
|
|
||||||
color = ColorHelper.rainbowColor(AnimationTickHolder.getTicks() * 100);
|
color = ColorHelper.rainbowColor(AnimationTickHolder.getTicks() * 100);
|
||||||
|
} else {
|
||||||
|
baseAngle = this.baseAngle;
|
||||||
|
lowerArmAngle = this.lowerArmAngle - 135;
|
||||||
|
upperArmAngle = this.upperArmAngle - 90;
|
||||||
|
headAngle = this.headAngle;
|
||||||
|
|
||||||
|
color = 0xFFFFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
MatrixStack msLocal = new MatrixStack();
|
MatrixStack msLocal = new MatrixStack();
|
||||||
|
@ -91,7 +123,7 @@ public class ArmInstance extends SingleRotatingInstance implements IDynamicInsta
|
||||||
msr.translate(getInstancePosition());
|
msr.translate(getInstancePosition());
|
||||||
msr.centre();
|
msr.centre();
|
||||||
|
|
||||||
if (blockState.get(ArmBlock.CEILING))
|
if (ceiling)
|
||||||
msr.rotateX(180);
|
msr.rotateX(180);
|
||||||
|
|
||||||
ArmRenderer.transformBase(msr, baseAngle);
|
ArmRenderer.transformBase(msr, baseAngle);
|
||||||
|
|
|
@ -196,11 +196,21 @@ public class SuperByteBuffer extends TemplateBuffer {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SuperByteBuffer rotate(Quaternion q) {
|
||||||
|
transforms.multiply(q);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public SuperByteBuffer rotateCentered(Direction axis, float radians) {
|
public SuperByteBuffer rotateCentered(Direction axis, float radians) {
|
||||||
return translate(.5f, .5f, .5f).rotate(axis, radians)
|
return translate(.5f, .5f, .5f).rotate(axis, radians)
|
||||||
.translate(-.5f, -.5f, -.5f);
|
.translate(-.5f, -.5f, -.5f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SuperByteBuffer rotateCentered(Quaternion q) {
|
||||||
|
return translate(.5f, .5f, .5f).rotate(q)
|
||||||
|
.translate(-.5f, -.5f, -.5f);
|
||||||
|
}
|
||||||
|
|
||||||
public SuperByteBuffer shiftUV(SpriteShiftEntry entry) {
|
public SuperByteBuffer shiftUV(SpriteShiftEntry entry) {
|
||||||
this.spriteShiftFunc = (builder, u, v) -> {
|
this.spriteShiftFunc = (builder, u, v) -> {
|
||||||
float targetU = entry.getTarget().getInterpolatedU((getUnInterpolatedU(entry.getOriginal(), u)));
|
float targetU = entry.getTarget().getInterpolatedU((getUnInterpolatedU(entry.getOriginal(), u)));
|
||||||
|
|
|
@ -1,19 +1,17 @@
|
||||||
package com.simibubi.create.foundation.render.backend;
|
package com.simibubi.create.foundation.render.backend;
|
||||||
|
|
||||||
import java.nio.FloatBuffer;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import com.simibubi.create.foundation.render.backend.gl.GlFog;
|
import com.simibubi.create.foundation.render.backend.gl.GlFog;
|
||||||
import com.simibubi.create.foundation.render.backend.gl.shader.*;
|
import com.simibubi.create.foundation.render.backend.gl.shader.*;
|
||||||
import com.simibubi.create.foundation.render.backend.gl.versioned.GlFeatureCompat;
|
import com.simibubi.create.foundation.render.backend.gl.versioned.GlCompat;
|
||||||
import com.simibubi.create.foundation.render.backend.instancing.IFlywheelWorld;
|
import com.simibubi.create.foundation.render.backend.instancing.IFlywheelWorld;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.lwjgl.opengl.GL;
|
import org.lwjgl.opengl.GL;
|
||||||
import org.lwjgl.opengl.GLCapabilities;
|
import org.lwjgl.opengl.GLCapabilities;
|
||||||
import org.lwjgl.system.MemoryUtil;
|
|
||||||
|
|
||||||
import com.simibubi.create.foundation.config.AllConfigs;
|
import com.simibubi.create.foundation.config.AllConfigs;
|
||||||
|
|
||||||
|
@ -28,7 +26,7 @@ public class Backend {
|
||||||
|
|
||||||
public static final Logger log = LogManager.getLogger(Backend.class);
|
public static final Logger log = LogManager.getLogger(Backend.class);
|
||||||
public static GLCapabilities capabilities;
|
public static GLCapabilities capabilities;
|
||||||
public static GlFeatureCompat compat;
|
public static GlCompat compat;
|
||||||
|
|
||||||
private static boolean instancingAvailable;
|
private static boolean instancingAvailable;
|
||||||
private static boolean enabled;
|
private static boolean enabled;
|
||||||
|
@ -97,7 +95,7 @@ public class Backend {
|
||||||
public static void refresh() {
|
public static void refresh() {
|
||||||
capabilities = GL.createCapabilities();
|
capabilities = GL.createCapabilities();
|
||||||
|
|
||||||
compat = new GlFeatureCompat(capabilities);
|
compat = new GlCompat(capabilities);
|
||||||
|
|
||||||
instancingAvailable = compat.vertexArrayObjectsSupported() &&
|
instancingAvailable = compat.vertexArrayObjectsSupported() &&
|
||||||
compat.drawInstancedSupported() &&
|
compat.drawInstancedSupported() &&
|
||||||
|
|
|
@ -1,17 +1,16 @@
|
||||||
package com.simibubi.create.foundation.render.backend;
|
package com.simibubi.create.foundation.render.backend;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.collect.Sets;
|
|
||||||
import com.mojang.blaze3d.systems.RenderSystem;
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
import com.simibubi.create.foundation.render.backend.gl.GlFogMode;
|
import com.simibubi.create.foundation.render.backend.gl.GlFogMode;
|
||||||
import com.simibubi.create.foundation.render.backend.gl.shader.*;
|
import com.simibubi.create.foundation.render.backend.gl.shader.*;
|
||||||
import com.simibubi.create.foundation.render.backend.gl.versioned.GlFeatureCompat;
|
|
||||||
import net.minecraft.resources.IResource;
|
import net.minecraft.resources.IResource;
|
||||||
import net.minecraft.resources.IResourceManager;
|
import net.minecraft.resources.IResourceManager;
|
||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
import net.minecraftforge.resource.IResourceType;
|
import net.minecraftforge.resource.IResourceType;
|
||||||
import net.minecraftforge.resource.VanillaResourceType;
|
import net.minecraftforge.resource.VanillaResourceType;
|
||||||
import org.lwjgl.opengl.GL;
|
|
||||||
import org.lwjgl.system.MemoryUtil;
|
import org.lwjgl.system.MemoryUtil;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
|
|
@ -4,6 +4,7 @@ import org.lwjgl.opengl.GL20;
|
||||||
|
|
||||||
import com.simibubi.create.foundation.render.backend.Backend;
|
import com.simibubi.create.foundation.render.backend.Backend;
|
||||||
import com.simibubi.create.foundation.render.backend.gl.GlObject;
|
import com.simibubi.create.foundation.render.backend.gl.GlObject;
|
||||||
|
import com.simibubi.create.foundation.render.backend.gl.versioned.GlCompat;
|
||||||
|
|
||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
|
||||||
|
@ -17,7 +18,7 @@ public class GlShader extends GlObject {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
int handle = GL20.glCreateShader(type.glEnum);
|
int handle = GL20.glCreateShader(type.glEnum);
|
||||||
|
|
||||||
GL20.glShaderSource(handle, source);
|
GlCompat.safeShaderSource(handle, source);
|
||||||
GL20.glCompileShader(handle);
|
GL20.glCompileShader(handle);
|
||||||
|
|
||||||
String log = GL20.glGetShaderInfoLog(handle);
|
String log = GL20.glGetShaderInfoLog(handle);
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
package com.simibubi.create.foundation.render.backend.gl.versioned;
|
package com.simibubi.create.foundation.render.backend.gl.versioned;
|
||||||
|
|
||||||
|
import org.lwjgl.PointerBuffer;
|
||||||
|
import org.lwjgl.opengl.GL20C;
|
||||||
import org.lwjgl.opengl.GLCapabilities;
|
import org.lwjgl.opengl.GLCapabilities;
|
||||||
|
import org.lwjgl.system.MemoryStack;
|
||||||
|
import org.lwjgl.system.MemoryUtil;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -13,7 +17,7 @@ import java.util.function.Consumer;
|
||||||
* Each field stores an enum variant that provides access to the
|
* Each field stores an enum variant that provides access to the
|
||||||
* most appropriate version of a feature for the current system.
|
* most appropriate version of a feature for the current system.
|
||||||
*/
|
*/
|
||||||
public class GlFeatureCompat {
|
public class GlCompat {
|
||||||
public final MapBuffer mapBuffer;
|
public final MapBuffer mapBuffer;
|
||||||
|
|
||||||
public final VertexArrayObject vertexArrayObject;
|
public final VertexArrayObject vertexArrayObject;
|
||||||
|
@ -22,7 +26,7 @@ public class GlFeatureCompat {
|
||||||
|
|
||||||
public final RGPixelFormat pixelFormat;
|
public final RGPixelFormat pixelFormat;
|
||||||
|
|
||||||
public GlFeatureCompat(GLCapabilities caps) {
|
public GlCompat(GLCapabilities caps) {
|
||||||
mapBuffer = getLatest(MapBuffer.class, caps);
|
mapBuffer = getLatest(MapBuffer.class, caps);
|
||||||
|
|
||||||
vertexArrayObject = getLatest(VertexArrayObject.class, caps);
|
vertexArrayObject = getLatest(VertexArrayObject.class, caps);
|
||||||
|
@ -85,5 +89,33 @@ public class GlFeatureCompat {
|
||||||
|
|
||||||
return Arrays.stream(constants).filter(it -> it.supported(caps)).findFirst().get();
|
return Arrays.stream(constants).filter(it -> it.supported(caps)).findFirst().get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copied from:
|
||||||
|
* <br> https://github.com/grondag/canvas/commit/820bf754092ccaf8d0c169620c2ff575722d7d96
|
||||||
|
*
|
||||||
|
* <p>Identical in function to {@link GL20C#glShaderSource(int, CharSequence)} but
|
||||||
|
* passes a null pointer for string length to force the driver to rely on the null
|
||||||
|
* terminator for string length. This is a workaround for an apparent flaw with some
|
||||||
|
* AMD drivers that don't receive or interpret the length correctly, resulting in
|
||||||
|
* an access violation when the driver tries to read past the string memory.
|
||||||
|
*
|
||||||
|
* <p>Hat tip to fewizz for the find and the fix.
|
||||||
|
*/
|
||||||
|
public static void safeShaderSource(int glId, CharSequence source) {
|
||||||
|
final MemoryStack stack = MemoryStack.stackGet();
|
||||||
|
final int stackPointer = stack.getPointer();
|
||||||
|
|
||||||
|
try {
|
||||||
|
final ByteBuffer sourceBuffer = MemoryUtil.memUTF8(source, true);
|
||||||
|
final PointerBuffer pointers = stack.mallocPointer(1);
|
||||||
|
pointers.put(sourceBuffer);
|
||||||
|
|
||||||
|
GL20C.nglShaderSource(glId, 1, pointers.address0(), 0);
|
||||||
|
org.lwjgl.system.APIUtil.apiArrayFree(pointers.address0(), 1);
|
||||||
|
} finally {
|
||||||
|
stack.setPointer(stackPointer);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,7 @@ public abstract class InstancedTileRenderer<P extends BasicProgram> {
|
||||||
protected Map<MaterialType<?>, RenderMaterial<P, ?>> materials = new HashMap<>();
|
protected Map<MaterialType<?>, RenderMaterial<P, ?>> materials = new HashMap<>();
|
||||||
|
|
||||||
protected int frame;
|
protected int frame;
|
||||||
|
protected int tick;
|
||||||
|
|
||||||
protected InstancedTileRenderer() {
|
protected InstancedTileRenderer() {
|
||||||
registerMaterials();
|
registerMaterials();
|
||||||
|
@ -43,6 +44,8 @@ public abstract class InstancedTileRenderer<P extends BasicProgram> {
|
||||||
public abstract void registerMaterials();
|
public abstract void registerMaterials();
|
||||||
|
|
||||||
public void tick(double cameraX, double cameraY, double cameraZ) {
|
public void tick(double cameraX, double cameraY, double cameraZ) {
|
||||||
|
tick++;
|
||||||
|
|
||||||
// integer camera pos
|
// integer camera pos
|
||||||
int cX = (int) cameraX;
|
int cX = (int) cameraX;
|
||||||
int cY = (int) cameraY;
|
int cY = (int) cameraY;
|
||||||
|
@ -61,7 +64,7 @@ public abstract class InstancedTileRenderer<P extends BasicProgram> {
|
||||||
int dY = pos.getY() - cY;
|
int dY = pos.getY() - cY;
|
||||||
int dZ = pos.getZ() - cZ;
|
int dZ = pos.getZ() - cZ;
|
||||||
|
|
||||||
if ((frame % getUpdateDivisor(dX, dY, dZ)) == 0)
|
if ((tick % getUpdateDivisor(dX, dY, dZ)) == 0)
|
||||||
instance.tick();
|
instance.tick();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -198,9 +201,9 @@ public abstract class InstancedTileRenderer<P extends BasicProgram> {
|
||||||
int dY = worldPos.getY() - cY;
|
int dY = worldPos.getY() - cY;
|
||||||
int dZ = worldPos.getZ() - cZ;
|
int dZ = worldPos.getZ() - cZ;
|
||||||
|
|
||||||
float dot = dX * lookX + dY * lookY + dZ * lookZ;
|
float dot = (dX + lookX * 2) * lookX + (dY + lookY * 2) * lookY + (dZ + lookZ * 2) * lookZ;
|
||||||
|
|
||||||
if (dot < 0) return false; // is it behind the camera?
|
if (dot < 0) return false; // is it more than 2 blocks behind the camera?
|
||||||
|
|
||||||
return (frame % getUpdateDivisor(dX, dY, dZ)) == 0;
|
return (frame % getUpdateDivisor(dX, dY, dZ)) == 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue