mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-11-10 12:02:48 +01:00
Instanced entities are lit
This commit is contained in:
parent
1ce141850b
commit
b4a1fbf2c7
11 changed files with 220 additions and 70 deletions
|
@ -26,7 +26,7 @@ import net.minecraft.world.World;
|
|||
public class Backend {
|
||||
public static final Logger log = LogManager.getLogger(Backend.class);
|
||||
|
||||
private static final Backend INSTANCE = new Backend();
|
||||
public static Backend INSTANCE;
|
||||
|
||||
public static Backend getInstance() {
|
||||
return INSTANCE;
|
||||
|
|
|
@ -83,6 +83,10 @@ public class InstancedRenderDispatcher {
|
|||
getTiles(te.getWorld()).queueUpdate(te);
|
||||
}
|
||||
|
||||
public static void enqueueUpdate(Entity entity) {
|
||||
getEntities(entity.world).queueUpdate(entity);
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onBeginFrame(BeginFrameEvent event) {
|
||||
Contexts.WORLD.getMaterialManager(event.getWorld())
|
||||
|
|
|
@ -54,6 +54,35 @@ public abstract class EntityInstance<E extends Entity> implements IInstance {
|
|||
*/
|
||||
public abstract void remove();
|
||||
|
||||
/**
|
||||
* Update instance data here. Good for when data doesn't change very often and when animations are GPU based.
|
||||
* Don't query lighting data here, that's handled separately in {@link #updateLight()}.
|
||||
*
|
||||
* <br><br> If your animations are complex or more CPU driven, see {@link IDynamicInstance} or {@link ITickableInstance}.
|
||||
*/
|
||||
public void update() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after construction and when a light update occurs in the world.
|
||||
*
|
||||
* <br> If your model needs it, update light here.
|
||||
*/
|
||||
public void updateLight() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Just before {@link #update()} would be called, <code>shouldReset()</code> is checked.
|
||||
* If this function returns <code>true</code>, then this instance will be {@link #remove removed},
|
||||
* and another instance will be constructed to replace it. This allows for more sane resource
|
||||
* acquisition compared to trying to update everything within the lifetime of an instance.
|
||||
*
|
||||
* @return <code>true</code> if this instance should be discarded and refreshed.
|
||||
*/
|
||||
public boolean shouldReset() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* In order to accommodate for floating point precision errors at high coordinates,
|
||||
* {@link TileInstanceManager}s are allowed to arbitrarily adjust the origin, and
|
||||
|
|
|
@ -3,6 +3,7 @@ package com.jozufozu.flywheel.backend.instancing.entity;
|
|||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
|
@ -26,7 +27,7 @@ public class EntityInstanceManager implements MaterialManager.OriginShiftListene
|
|||
public final MaterialManager<?> materialManager;
|
||||
|
||||
protected final ArrayList<Entity> queuedAdditions;
|
||||
//protected final ConcurrentHashMap.KeySetView<Entity, Boolean> queuedUpdates;
|
||||
protected final ConcurrentHashMap.KeySetView<Entity, Boolean> queuedUpdates;
|
||||
|
||||
protected final Map<Entity, EntityInstance<?>> instances;
|
||||
protected final Object2ObjectOpenHashMap<Entity, ITickableInstance> tickableInstances;
|
||||
|
@ -37,7 +38,7 @@ public class EntityInstanceManager implements MaterialManager.OriginShiftListene
|
|||
|
||||
public EntityInstanceManager(MaterialManager<?> materialManager) {
|
||||
this.materialManager = materialManager;
|
||||
//this.queuedUpdates = ConcurrentHashMap.newKeySet(64);
|
||||
this.queuedUpdates = ConcurrentHashMap.newKeySet(64);
|
||||
this.queuedAdditions = new ArrayList<>(64);
|
||||
this.instances = new HashMap<>();
|
||||
|
||||
|
@ -72,12 +73,12 @@ public class EntityInstanceManager implements MaterialManager.OriginShiftListene
|
|||
instance.tick();
|
||||
}
|
||||
}
|
||||
//
|
||||
// queuedUpdates.forEach(te -> {
|
||||
// queuedUpdates.remove(te);
|
||||
//
|
||||
// update(te);
|
||||
// });
|
||||
|
||||
queuedUpdates.forEach(te -> {
|
||||
queuedUpdates.remove(te);
|
||||
|
||||
update(te);
|
||||
});
|
||||
}
|
||||
|
||||
public void beginFrame(ActiveRenderInfo info) {
|
||||
|
@ -126,16 +127,16 @@ public class EntityInstanceManager implements MaterialManager.OriginShiftListene
|
|||
}
|
||||
}
|
||||
|
||||
// public <T extends Entity> void onLightUpdate(T tile) {
|
||||
// if (!Backend.getInstance().canUseInstancing()) return;
|
||||
//
|
||||
// if (tile instanceof IInstanceRendered) {
|
||||
// EntityInstance<? super T> instance = getInstance(tile, false);
|
||||
//
|
||||
// if (instance != null)
|
||||
// instance.updateLight();
|
||||
// }
|
||||
// }
|
||||
public <T extends Entity> void onLightUpdate(T tile) {
|
||||
if (!Backend.getInstance().canUseInstancing()) return;
|
||||
|
||||
if (tile instanceof IInstanceRendered) {
|
||||
EntityInstance<? super T> instance = getInstance(tile, false);
|
||||
|
||||
if (instance != null)
|
||||
instance.updateLight();
|
||||
}
|
||||
}
|
||||
|
||||
public <T extends Entity> void add(T entity) {
|
||||
if (!Backend.getInstance().canUseInstancing()) return;
|
||||
|
@ -145,24 +146,24 @@ public class EntityInstanceManager implements MaterialManager.OriginShiftListene
|
|||
}
|
||||
}
|
||||
|
||||
// public <T extends Entity> void update(T tile) {
|
||||
// if (!Backend.getInstance().canUseInstancing()) return;
|
||||
//
|
||||
// if (tile instanceof IInstanceRendered) {
|
||||
// EntityInstance<? super T> instance = getInstance(tile, false);
|
||||
//
|
||||
// if (instance != null) {
|
||||
//
|
||||
// if (instance.shouldReset()) {
|
||||
// removeInternal(tile, instance);
|
||||
//
|
||||
// createInternal(tile);
|
||||
// } else {
|
||||
// instance.update();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
public <T extends Entity> void update(T tile) {
|
||||
if (!Backend.getInstance().canUseInstancing()) return;
|
||||
|
||||
if (tile instanceof IInstanceRendered) {
|
||||
EntityInstance<? super T> instance = getInstance(tile, false);
|
||||
|
||||
if (instance != null) {
|
||||
|
||||
if (instance.shouldReset()) {
|
||||
removeInternal(tile, instance);
|
||||
|
||||
createInternal(tile);
|
||||
} else {
|
||||
instance.update();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public <T extends Entity> void remove(T entity) {
|
||||
if (!Backend.getInstance().canUseInstancing()) return;
|
||||
|
@ -178,11 +179,11 @@ public class EntityInstanceManager implements MaterialManager.OriginShiftListene
|
|||
queuedAdditions.add(tile);
|
||||
}
|
||||
|
||||
// public synchronized <T extends Entity> void queueUpdate(T tile) {
|
||||
// if (!Backend.getInstance().canUseInstancing()) return;
|
||||
//
|
||||
// queuedUpdates.add(tile);
|
||||
// }
|
||||
public synchronized <T extends Entity> void queueUpdate(T tile) {
|
||||
if (!Backend.getInstance().canUseInstancing()) return;
|
||||
|
||||
queuedUpdates.add(tile);
|
||||
}
|
||||
|
||||
protected synchronized void processQueuedAdditions() {
|
||||
if (queuedAdditions.size() > 0) {
|
||||
|
@ -233,7 +234,7 @@ public class EntityInstanceManager implements MaterialManager.OriginShiftListene
|
|||
EntityInstance<? super T> renderer = InstancedRenderRegistry.getInstance().create(materialManager, tile);
|
||||
|
||||
if (renderer != null) {
|
||||
//renderer.updateLight();
|
||||
renderer.updateLight();
|
||||
instances.put(tile, renderer);
|
||||
|
||||
if (renderer instanceof IDynamicInstance)
|
||||
|
|
45
src/main/java/com/jozufozu/flywheel/core/AtlasStitcher.java
Normal file
45
src/main/java/com/jozufozu/flywheel/core/AtlasStitcher.java
Normal file
|
@ -0,0 +1,45 @@
|
|||
package com.jozufozu.flywheel.core;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.inventory.container.PlayerContainer;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.client.event.TextureStitchEvent;
|
||||
import net.minecraftforge.eventbus.api.IEventBus;
|
||||
|
||||
/**
|
||||
* This is primarily for hacking entity textures into the block atlas.
|
||||
*/
|
||||
public class AtlasStitcher {
|
||||
public static AtlasStitcher INSTANCE;
|
||||
|
||||
public static AtlasStitcher getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
public AtlasStitcher(IEventBus modEventBus) {
|
||||
modEventBus.addListener(this::onTextureStitch);
|
||||
}
|
||||
|
||||
private final List<StitchedSprite> sprites = new ArrayList<>();
|
||||
|
||||
public StitchedSprite get(ResourceLocation loc) {
|
||||
StitchedSprite sprite = new StitchedSprite(loc);
|
||||
|
||||
sprites.add(sprite);
|
||||
|
||||
return sprite;
|
||||
}
|
||||
|
||||
public void onTextureStitch(TextureStitchEvent.Pre event) {
|
||||
if (!event.getMap()
|
||||
.getId()
|
||||
.equals(PlayerContainer.BLOCK_ATLAS_TEXTURE))
|
||||
return;
|
||||
|
||||
sprites.stream()
|
||||
.map(StitchedSprite::getLoc)
|
||||
.forEach(event::addSprite);
|
||||
}
|
||||
}
|
31
src/main/java/com/jozufozu/flywheel/core/StitchedSprite.java
Normal file
31
src/main/java/com/jozufozu/flywheel/core/StitchedSprite.java
Normal file
|
@ -0,0 +1,31 @@
|
|||
package com.jozufozu.flywheel.core;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.inventory.container.PlayerContainer;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
public class StitchedSprite {
|
||||
|
||||
private final ResourceLocation loc;
|
||||
|
||||
TextureAtlasSprite sprite;
|
||||
|
||||
public StitchedSprite(ResourceLocation loc) {
|
||||
this.loc = loc;
|
||||
}
|
||||
|
||||
public ResourceLocation getLoc() {
|
||||
return loc;
|
||||
}
|
||||
|
||||
public TextureAtlasSprite getSprite() {
|
||||
if (sprite == null) {
|
||||
sprite = Minecraft.getInstance()
|
||||
.getSpriteAtlas(PlayerContainer.BLOCK_ATLAS_TEXTURE)
|
||||
.apply(loc);
|
||||
}
|
||||
|
||||
return sprite;
|
||||
}
|
||||
}
|
15
src/main/java/com/simibubi/create/AllStitchedTextures.java
Normal file
15
src/main/java/com/simibubi/create/AllStitchedTextures.java
Normal file
|
@ -0,0 +1,15 @@
|
|||
package com.simibubi.create;
|
||||
|
||||
import com.jozufozu.flywheel.core.AtlasStitcher;
|
||||
import com.jozufozu.flywheel.core.StitchedSprite;
|
||||
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
public class AllStitchedTextures {
|
||||
|
||||
public static final StitchedSprite SUPER_GLUE = AtlasStitcher.getInstance().get(new ResourceLocation(Create.ID, "entity/super_glue/slime"));
|
||||
|
||||
public static void init() {
|
||||
|
||||
}
|
||||
}
|
|
@ -6,6 +6,7 @@ import java.util.Map;
|
|||
import java.util.function.Function;
|
||||
|
||||
import com.jozufozu.flywheel.backend.Backend;
|
||||
import com.jozufozu.flywheel.core.AtlasStitcher;
|
||||
import com.jozufozu.flywheel.core.PartialModel;
|
||||
import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher;
|
||||
|
@ -77,7 +78,8 @@ public class CreateClient {
|
|||
modEventBus.addListener(AllParticleTypes::registerFactories);
|
||||
modEventBus.addListener(ClientEvents::loadCompleted);
|
||||
|
||||
Backend.getInstance();
|
||||
Backend.INSTANCE = new Backend();
|
||||
AtlasStitcher.INSTANCE = new AtlasStitcher(modEventBus);
|
||||
}
|
||||
|
||||
public static void clientInit(FMLClientSetupEvent event) {
|
||||
|
@ -88,6 +90,7 @@ public class CreateClient {
|
|||
AllKeys.register();
|
||||
// AllFluids.assignRenderLayers();
|
||||
AllBlockPartials.clientInit();
|
||||
AllStitchedTextures.init();
|
||||
|
||||
PonderIndex.register();
|
||||
PonderIndex.registerTags();
|
||||
|
|
|
@ -12,16 +12,20 @@ import com.jozufozu.flywheel.core.Materials;
|
|||
import com.jozufozu.flywheel.core.instancing.ConditionalInstance;
|
||||
import com.jozufozu.flywheel.core.materials.OrientedData;
|
||||
import com.simibubi.create.AllItems;
|
||||
import com.simibubi.create.AllStitchedTextures;
|
||||
import com.simibubi.create.Create;
|
||||
import com.simibubi.create.foundation.utility.AngleHelper;
|
||||
import com.simibubi.create.foundation.utility.VecHelper;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.vector.Quaternion;
|
||||
import net.minecraft.util.math.vector.Vector3d;
|
||||
import net.minecraft.world.LightType;
|
||||
|
||||
public class GlueInstance extends EntityInstance<SuperGlueEntity> implements ITickableInstance {
|
||||
|
||||
|
@ -33,7 +37,7 @@ public class GlueInstance extends EntityInstance<SuperGlueEntity> implements ITi
|
|||
public GlueInstance(MaterialManager<?> materialManager, SuperGlueEntity entity) {
|
||||
super(materialManager, entity);
|
||||
|
||||
Instancer<OrientedData> instancer = materialManager.getMaterial(Materials.ORIENTED, TEXTURE)
|
||||
Instancer<OrientedData> instancer = materialManager.getMaterial(Materials.ORIENTED)
|
||||
.get(entity.getType(), GlueInstance::supplyModel);
|
||||
|
||||
Direction face = entity.getFacingDirection();
|
||||
|
@ -59,9 +63,20 @@ public class GlueInstance extends EntityInstance<SuperGlueEntity> implements ITi
|
|||
|
||||
model.setPosition(getInstancePosition())
|
||||
.setPivot(0, 0, 0)
|
||||
.setRotation(rotation)
|
||||
.setSkyLight(15)
|
||||
.setBlockLight(15);
|
||||
.setRotation(rotation);
|
||||
|
||||
updateLight(model);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateLight() {
|
||||
model.get().ifPresent(this::updateLight);
|
||||
}
|
||||
|
||||
private void updateLight(OrientedData model) {
|
||||
BlockPos pos = entity.getHangingPosition();
|
||||
model.setBlockLight(world.getLightLevel(LightType.BLOCK, pos))
|
||||
.setSkyLight(world.getLightLevel(LightType.SKY, pos));
|
||||
}
|
||||
|
||||
private boolean shouldShow() {
|
||||
|
@ -99,17 +114,19 @@ public class GlueInstance extends EntityInstance<SuperGlueEntity> implements ITi
|
|||
|
||||
VecBuffer buffer = VecBuffer.allocate(Formats.UNLIT_MODEL.getStride() * 8);
|
||||
|
||||
TextureAtlasSprite sprite = AllStitchedTextures.SUPER_GLUE.getSprite();
|
||||
|
||||
// pos normal uv
|
||||
// inside quad
|
||||
buffer.putVec3((float) a1.x, (float) a1.y, (float) a1.z).putVec3((byte) 0, (byte) 0, (byte) -127).putVec2(1f, 0f);
|
||||
buffer.putVec3((float) a2.x, (float) a2.y, (float) a2.z).putVec3((byte) 0, (byte) 0, (byte) -127).putVec2(1f, 1f);
|
||||
buffer.putVec3((float) a3.x, (float) a3.y, (float) a3.z).putVec3((byte) 0, (byte) 0, (byte) -127).putVec2(0f, 1f);
|
||||
buffer.putVec3((float) a4.x, (float) a4.y, (float) a4.z).putVec3((byte) 0, (byte) 0, (byte) -127).putVec2(0f, 0f);
|
||||
buffer.putVec3((float) a1.x, (float) a1.y, (float) a1.z).putVec3((byte) 0, (byte) 0, (byte) -127).putVec2(sprite.getMaxU(), sprite.getMinV());
|
||||
buffer.putVec3((float) a2.x, (float) a2.y, (float) a2.z).putVec3((byte) 0, (byte) 0, (byte) -127).putVec2(sprite.getMaxU(), sprite.getMaxV());
|
||||
buffer.putVec3((float) a3.x, (float) a3.y, (float) a3.z).putVec3((byte) 0, (byte) 0, (byte) -127).putVec2(sprite.getMinU(), sprite.getMaxV());
|
||||
buffer.putVec3((float) a4.x, (float) a4.y, (float) a4.z).putVec3((byte) 0, (byte) 0, (byte) -127).putVec2(sprite.getMinU(), sprite.getMinV());
|
||||
// outside quad
|
||||
buffer.putVec3((float) b4.x, (float) b4.y, (float) b4.z).putVec3((byte) 0, (byte) 0, (byte) 127).putVec2(0f, 0f);
|
||||
buffer.putVec3((float) b3.x, (float) b3.y, (float) b3.z).putVec3((byte) 0, (byte) 0, (byte) 127).putVec2(0f, 1f);
|
||||
buffer.putVec3((float) b2.x, (float) b2.y, (float) b2.z).putVec3((byte) 0, (byte) 0, (byte) 127).putVec2(1f, 1f);
|
||||
buffer.putVec3((float) b1.x, (float) b1.y, (float) b1.z).putVec3((byte) 0, (byte) 0, (byte) 127).putVec2(1f, 0f);
|
||||
buffer.putVec3((float) b4.x, (float) b4.y, (float) b4.z).putVec3((byte) 0, (byte) 0, (byte) 127).putVec2(sprite.getMinU(), sprite.getMinV());
|
||||
buffer.putVec3((float) b3.x, (float) b3.y, (float) b3.z).putVec3((byte) 0, (byte) 0, (byte) 127).putVec2(sprite.getMinU(), sprite.getMaxV());
|
||||
buffer.putVec3((float) b2.x, (float) b2.y, (float) b2.z).putVec3((byte) 0, (byte) 0, (byte) 127).putVec2(sprite.getMaxU(), sprite.getMaxV());
|
||||
buffer.putVec3((float) b1.x, (float) b1.y, (float) b1.z).putVec3((byte) 0, (byte) 0, (byte) 127).putVec2(sprite.getMaxU(), sprite.getMinV());
|
||||
|
||||
buffer.rewind();
|
||||
|
||||
|
|
|
@ -40,15 +40,16 @@ public abstract class LightUpdateMixin extends AbstractChunkProvider {
|
|||
|
||||
if (chunk != null) {
|
||||
chunk.getTileEntityMap()
|
||||
.entrySet()
|
||||
.stream()
|
||||
.filter(entry -> SectionPos.toChunk(entry.getKey()
|
||||
.getY()) == sectionY)
|
||||
.map(Map.Entry::getValue)
|
||||
.forEach(tile -> {
|
||||
InstancedRenderDispatcher.getTiles(world)
|
||||
.onLightUpdate(tile);
|
||||
});
|
||||
.entrySet()
|
||||
.stream()
|
||||
.filter(entry -> SectionPos.toChunk(entry.getKey()
|
||||
.getY()) == sectionY)
|
||||
.map(Map.Entry::getValue)
|
||||
.forEach(InstancedRenderDispatcher.getTiles(world)::onLightUpdate);
|
||||
|
||||
if (sectionY >= 0) // TODO: 1.17
|
||||
chunk.getEntityLists()[sectionY]
|
||||
.forEach(InstancedRenderDispatcher.getEntities(world)::onLightUpdate);
|
||||
}
|
||||
|
||||
LightUpdater.getInstance()
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package com.simibubi.create.foundation.mixin.flywheel.light;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
|
@ -13,6 +15,7 @@ import net.minecraft.client.Minecraft;
|
|||
import net.minecraft.client.network.play.ClientPlayNetHandler;
|
||||
import net.minecraft.client.world.ClientWorld;
|
||||
import net.minecraft.network.play.server.SUpdateLightPacket;
|
||||
import net.minecraft.util.ClassInheritanceMultiMap;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
|
||||
@Mixin(ClientPlayNetHandler.class)
|
||||
|
@ -34,11 +37,12 @@ public class NetworkLightUpdateMixin {
|
|||
|
||||
if (chunk != null) {
|
||||
chunk.getTileEntityMap()
|
||||
.values()
|
||||
.forEach(tile -> {
|
||||
InstancedRenderDispatcher.getTiles(world)
|
||||
.onLightUpdate(tile);
|
||||
});
|
||||
.values()
|
||||
.forEach(InstancedRenderDispatcher.getTiles(world)::onLightUpdate);
|
||||
|
||||
Arrays.stream(chunk.getEntityLists())
|
||||
.flatMap(ClassInheritanceMultiMap::stream)
|
||||
.forEach(InstancedRenderDispatcher.getEntities(world)::onLightUpdate);
|
||||
}
|
||||
|
||||
LightUpdater.getInstance()
|
||||
|
|
Loading…
Reference in a new issue