Merge branch 'dev' into shader-pipeline

# Conflicts:
#	src/main/java/com/jozufozu/flywheel/core/WorldContext.java
This commit is contained in:
Jozufozu 2021-07-12 23:53:35 -07:00
commit a2b740f0d8
47 changed files with 1565 additions and 174 deletions

View file

@ -99,6 +99,8 @@ repositories {
dependencies { dependencies {
minecraft "net.minecraftforge:forge:${minecraft_version}-${forge_version}" minecraft "net.minecraftforge:forge:${minecraft_version}-${forge_version}"
//implementation "org.joml:joml:1.10.1"
annotationProcessor 'org.spongepowered:mixin:0.8.2:processor' annotationProcessor 'org.spongepowered:mixin:0.8.2:processor'
} }

View file

@ -1,3 +1,10 @@
0.1.0:
Fixes
- Render layer events are always dispatched, even when the backend is disabled
- Fix a crash when light updates occur close to the world height
- Fix issue with optifine shaders
- Fix PartialModels not being initialized
0.0.3: 0.0.3:
New New
- Include the logo in the mod - Include the logo in the mod

View file

@ -1,7 +1,7 @@
org.gradle.jvmargs=-Xmx3G org.gradle.jvmargs=-Xmx3G
org.gradle.daemon=false org.gradle.daemon=false
# mod version info # mod version info
mod_version=0.0.3 mod_version=0.1.0
mc_update_version=1.16 mc_update_version=1.16
minecraft_version=1.16.5 minecraft_version=1.16.5
forge_version=36.0.42 forge_version=36.0.42

View file

@ -4,6 +4,8 @@ import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.core.AtlasStitcher; import com.jozufozu.flywheel.core.AtlasStitcher;
import com.jozufozu.flywheel.core.Contexts; import com.jozufozu.flywheel.core.Contexts;
import com.jozufozu.flywheel.core.Materials; import com.jozufozu.flywheel.core.Materials;
import com.jozufozu.flywheel.core.PartialModel;
import com.jozufozu.flywheel.vanilla.VanillaInstances;
import net.minecraftforge.eventbus.api.IEventBus; import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
@ -20,5 +22,9 @@ public class FlywheelClient {
modEventBus.addListener(Contexts::flwInit); modEventBus.addListener(Contexts::flwInit);
modEventBus.addListener(Materials::flwInit); modEventBus.addListener(Materials::flwInit);
modEventBus.addListener(PartialModel::onModelRegistry);
modEventBus.addListener(PartialModel::onModelBake);
VanillaInstances.init();
} }
} }

View file

@ -5,6 +5,7 @@ import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.StringReader; import java.io.StringReader;
import java.nio.Buffer;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.channels.Channels; import java.nio.channels.Channels;
import java.nio.channels.FileChannel; import java.nio.channels.FileChannel;
@ -18,7 +19,6 @@ import java.util.function.Predicate;
import java.util.stream.Stream; import java.util.stream.Stream;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
import org.lwjgl.system.MemoryUtil; import org.lwjgl.system.MemoryUtil;
@ -52,7 +52,6 @@ import net.minecraftforge.resource.IResourceType;
import net.minecraftforge.resource.ISelectiveResourceReloadListener; import net.minecraftforge.resource.ISelectiveResourceReloadListener;
import net.minecraftforge.resource.VanillaResourceType; import net.minecraftforge.resource.VanillaResourceType;
@ParametersAreNonnullByDefault
public class ShaderSources implements ISelectiveResourceReloadListener { public class ShaderSources implements ISelectiveResourceReloadListener {
public static final String SHADER_DIR = "flywheel/shaders/"; public static final String SHADER_DIR = "flywheel/shaders/";
public static final String PROGRAM_DIR = "flywheel/programs/"; public static final String PROGRAM_DIR = "flywheel/programs/";
@ -205,7 +204,7 @@ public class ShaderSources implements ISelectiveResourceReloadListener {
try { try {
bytebuffer = readToBuffer(is); bytebuffer = readToBuffer(is);
int i = bytebuffer.position(); int i = bytebuffer.position();
bytebuffer.rewind(); ((Buffer) bytebuffer).rewind();
return MemoryUtil.memASCII(bytebuffer, i); return MemoryUtil.memASCII(bytebuffer, i);
} catch (IOException e) { } catch (IOException e) {

View file

@ -1,5 +1,6 @@
package com.jozufozu.flywheel.backend.gl.buffer; package com.jozufozu.flywheel.backend.gl.buffer;
import java.nio.Buffer;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.ByteOrder; import java.nio.ByteOrder;
@ -29,7 +30,7 @@ public class VecBuffer {
} }
public VecBuffer rewind() { public VecBuffer rewind() {
internal.rewind(); ((Buffer) internal).rewind();
return this; return this;
} }

View file

@ -0,0 +1,130 @@
package com.jozufozu.flywheel.backend.instancing;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D;
import static org.lwjgl.opengl.GL11.glBindTexture;
import static org.lwjgl.opengl.GL13.GL_TEXTURE0;
import static org.lwjgl.opengl.GL13.GL_TEXTURE4;
import static org.lwjgl.opengl.GL13.glActiveTexture;
import java.util.ArrayList;
import java.util.List;
import java.util.SortedSet;
import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.core.Contexts;
import com.jozufozu.flywheel.core.crumbling.CrumblingInstanceManager;
import com.jozufozu.flywheel.core.crumbling.CrumblingMaterialManager;
import com.jozufozu.flywheel.core.crumbling.CrumblingProgram;
import com.jozufozu.flywheel.event.ReloadRenderersEvent;
import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.ActiveRenderInfo;
import net.minecraft.client.renderer.DestroyBlockProgress;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.model.ModelBakery;
import net.minecraft.client.renderer.texture.Texture;
import net.minecraft.client.renderer.texture.TextureManager;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.LazyValue;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.vector.Matrix4f;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
/**
* Responsible for rendering the block breaking overlay for instanced tiles.
*/
@OnlyIn(Dist.CLIENT)
@Mod.EventBusSubscriber(Dist.CLIENT)
public class CrumblingRenderer {
private static final LazyValue<MaterialManager<CrumblingProgram>> materialManager = new LazyValue<>(() -> new CrumblingMaterialManager(Contexts.CRUMBLING));
private static final LazyValue<InstanceManager<TileEntity>> manager = new LazyValue<>(() -> new CrumblingInstanceManager(materialManager.getValue()));
private static final RenderType crumblingLayer = ModelBakery.BLOCK_DESTRUCTION_RENDER_LAYERS.get(0);
public static void renderBreaking(ClientWorld world, Matrix4f viewProjection, double cameraX, double cameraY, double cameraZ) {
if (!Backend.getInstance()
.canUseInstancing(world)) return;
Int2ObjectMap<List<TileEntity>> activeStages = getActiveStageTiles(world);
if (activeStages.isEmpty()) return;
InstanceManager<TileEntity> renderer = manager.getValue();
TextureManager textureManager = Minecraft.getInstance().textureManager;
ActiveRenderInfo info = Minecraft.getInstance().gameRenderer.getActiveRenderInfo();
MaterialManager<CrumblingProgram> materials = materialManager.getValue();
crumblingLayer.startDrawing();
for (Int2ObjectMap.Entry<List<TileEntity>> stage : activeStages.int2ObjectEntrySet()) {
int i = stage.getIntKey();
Texture breaking = textureManager.getTexture(ModelBakery.BLOCK_DESTRUCTION_STAGE_TEXTURES.get(i));
// something about when we call this means that the textures are not ready for use on the first frame they should appear
if (breaking != null) {
stage.getValue().forEach(renderer::add);
renderer.beginFrame(info);
glActiveTexture(GL_TEXTURE4);
glBindTexture(GL_TEXTURE_2D, breaking.getGlTextureId());
materials.render(RenderType.getCutoutMipped(), viewProjection, cameraX, cameraY, cameraZ);
renderer.invalidate();
}
}
crumblingLayer.endDrawing();
glActiveTexture(GL_TEXTURE0);
Texture breaking = textureManager.getTexture(ModelBakery.BLOCK_DESTRUCTION_STAGE_TEXTURES.get(0));
if (breaking != null) glBindTexture(GL_TEXTURE_2D, breaking.getGlTextureId());
}
/**
* Associate each breaking stage with a list of all tile entities at that stage.
*/
private static Int2ObjectMap<List<TileEntity>> getActiveStageTiles(ClientWorld world) {
Long2ObjectMap<SortedSet<DestroyBlockProgress>> breakingProgressions = Minecraft.getInstance().worldRenderer.blockBreakingProgressions;
Int2ObjectMap<List<TileEntity>> breakingEntities = new Int2ObjectArrayMap<>();
for (Long2ObjectMap.Entry<SortedSet<DestroyBlockProgress>> entry : breakingProgressions.long2ObjectEntrySet()) {
BlockPos breakingPos = BlockPos.fromLong(entry.getLongKey());
SortedSet<DestroyBlockProgress> progresses = entry.getValue();
if (progresses != null && !progresses.isEmpty()) {
int blockDamage = progresses.last()
.getPartialBlockDamage();
TileEntity tileEntity = world.getTileEntity(breakingPos);
if (tileEntity != null) {
List<TileEntity> tileEntities = breakingEntities.computeIfAbsent(blockDamage, $ -> new ArrayList<>());
tileEntities.add(tileEntity);
}
}
}
return breakingEntities;
}
@SubscribeEvent
public static void onReloadRenderers(ReloadRenderersEvent event) {
ClientWorld world = event.getWorld();
if (Backend.getInstance()
.canUseInstancing() && world != null) {
materialManager.getValue().delete();
}
}
}

View file

@ -40,6 +40,12 @@ public abstract class InstanceManager<T> implements MaterialManager.OriginShiftL
materialManager.addListener(this); materialManager.addListener(this);
} }
protected abstract boolean canInstance(T obj);
protected abstract IInstance createRaw(T obj);
protected abstract boolean canCreateInstance(T entity);
public void tick(double cameraX, double cameraY, double cameraZ) { public void tick(double cameraX, double cameraY, double cameraZ) {
tick++; tick++;
@ -100,7 +106,7 @@ public abstract class InstanceManager<T> implements MaterialManager.OriginShiftL
if (!Backend.getInstance() if (!Backend.getInstance()
.canUseInstancing()) return; .canUseInstancing()) return;
if (obj instanceof IInstanceRendered) { if (canInstance(obj)) {
addInternal(obj); addInternal(obj);
} }
} }
@ -116,7 +122,7 @@ public abstract class InstanceManager<T> implements MaterialManager.OriginShiftL
if (!Backend.getInstance() if (!Backend.getInstance()
.canUseInstancing()) return; .canUseInstancing()) return;
if (obj instanceof IInstanceRendered) { if (canInstance(obj)) {
IInstance instance = getInstance(obj, false); IInstance instance = getInstance(obj, false);
if (instance != null) { if (instance != null) {
@ -143,7 +149,7 @@ public abstract class InstanceManager<T> implements MaterialManager.OriginShiftL
if (!Backend.getInstance() if (!Backend.getInstance()
.canUseInstancing()) return; .canUseInstancing()) return;
if (obj instanceof IInstanceRendered) { if (canInstance(obj)) {
IInstance instance = getInstance(obj, false); IInstance instance = getInstance(obj, false);
if (instance != null) instance.updateLight(); if (instance != null) instance.updateLight();
@ -154,13 +160,14 @@ public abstract class InstanceManager<T> implements MaterialManager.OriginShiftL
if (!Backend.getInstance() if (!Backend.getInstance()
.canUseInstancing()) return; .canUseInstancing()) return;
if (obj instanceof IInstanceRendered) { if (canInstance(obj)) {
IInstance instance = getInstance(obj, false); IInstance instance = getInstance(obj, false);
if (instance != null) removeInternal(obj, instance); if (instance != null) removeInternal(obj, instance);
} }
} }
public void invalidate() { public void invalidate() {
instances.values().forEach(IInstance::remove);
instances.clear(); instances.clear();
dynamicInstances.clear(); dynamicInstances.clear();
tickableInstances.clear(); tickableInstances.clear();
@ -241,8 +248,4 @@ public abstract class InstanceManager<T> implements MaterialManager.OriginShiftL
invalidate(); invalidate();
instancedTiles.forEach(this::add); instancedTiles.forEach(this::add);
} }
protected abstract IInstance createRaw(T obj);
protected abstract boolean canCreateInstance(T entity);
} }

View file

@ -1,5 +1,6 @@
package com.jozufozu.flywheel.backend.instancing; package com.jozufozu.flywheel.backend.instancing;
import java.nio.Buffer;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.ByteOrder; import java.nio.ByteOrder;
import java.util.Arrays; import java.util.Arrays;
@ -137,7 +138,7 @@ public class InstanceMaterial<D extends InstanceData> {
vertices.putFloat(reader.getV(i)); vertices.putFloat(reader.getV(i));
} }
vertices.rewind(); ((Buffer) vertices).rewind();
// return new BufferedModel(GlPrimitive.QUADS, format, vertices, vertexCount); // return new BufferedModel(GlPrimitive.QUADS, format, vertices, vertexCount);

View file

@ -1,44 +1,22 @@
package com.jozufozu.flywheel.backend.instancing; package com.jozufozu.flywheel.backend.instancing;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D;
import static org.lwjgl.opengl.GL11.glBindTexture;
import static org.lwjgl.opengl.GL13.GL_TEXTURE0;
import static org.lwjgl.opengl.GL13.GL_TEXTURE4;
import static org.lwjgl.opengl.GL13.glActiveTexture;
import java.util.BitSet;
import java.util.SortedSet;
import java.util.Vector;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.instancing.entity.EntityInstanceManager; import com.jozufozu.flywheel.backend.instancing.entity.EntityInstanceManager;
import com.jozufozu.flywheel.backend.instancing.tile.TileInstanceManager; import com.jozufozu.flywheel.backend.instancing.tile.TileInstanceManager;
import com.jozufozu.flywheel.core.Contexts; import com.jozufozu.flywheel.core.Contexts;
import com.jozufozu.flywheel.core.CrumblingInstanceManager; import com.jozufozu.flywheel.core.shader.WorldProgram;
import com.jozufozu.flywheel.event.BeginFrameEvent; import com.jozufozu.flywheel.event.BeginFrameEvent;
import com.jozufozu.flywheel.event.ReloadRenderersEvent; import com.jozufozu.flywheel.event.ReloadRenderersEvent;
import com.jozufozu.flywheel.event.RenderLayerEvent; import com.jozufozu.flywheel.event.RenderLayerEvent;
import com.jozufozu.flywheel.util.AnimationTickHolder; import com.jozufozu.flywheel.util.AnimationTickHolder;
import com.jozufozu.flywheel.util.WorldAttached; import com.jozufozu.flywheel.util.WorldAttached;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.ActiveRenderInfo;
import net.minecraft.client.renderer.DestroyBlockProgress;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.client.renderer.model.ModelBakery;
import net.minecraft.client.renderer.texture.Texture;
import net.minecraft.client.renderer.texture.TextureManager;
import net.minecraft.client.world.ClientWorld; import net.minecraft.client.world.ClientWorld;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.inventory.container.PlayerContainer;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.LazyValue;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.vector.Matrix4f;
import net.minecraft.world.IWorld; import net.minecraft.world.IWorld;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
@ -50,16 +28,10 @@ import net.minecraftforge.fml.common.Mod;
@Mod.EventBusSubscriber(Dist.CLIENT) @Mod.EventBusSubscriber(Dist.CLIENT)
public class InstancedRenderDispatcher { public class InstancedRenderDispatcher {
private static final WorldAttached<InstanceManager<Entity>> entityInstanceManager = new WorldAttached<>(world -> new EntityInstanceManager(Contexts.WORLD.getMaterialManager(world))); private static final WorldAttached<MaterialManager<WorldProgram>> materialManagers = new WorldAttached<>($ -> new MaterialManager<>(Contexts.WORLD));
private static final WorldAttached<InstanceManager<TileEntity>> tileInstanceManager = new WorldAttached<>(world -> new TileInstanceManager(Contexts.WORLD.getMaterialManager(world)));
private static final LazyValue<Vector<CrumblingInstanceManager>> blockBreaking = new LazyValue<>(() -> { private static final WorldAttached<InstanceManager<Entity>> entityInstanceManager = new WorldAttached<>(world -> new EntityInstanceManager(materialManagers.get(world)));
Vector<CrumblingInstanceManager> renderers = new Vector<>(10); private static final WorldAttached<InstanceManager<TileEntity>> tileInstanceManager = new WorldAttached<>(world -> new TileInstanceManager(materialManagers.get(world)));
for (int i = 0; i < 10; i++) {
renderers.add(new CrumblingInstanceManager());
}
return renderers;
});
@Nonnull @Nonnull
public static InstanceManager<TileEntity> getTiles(IWorld world) { public static InstanceManager<TileEntity> getTiles(IWorld world) {
@ -99,7 +71,7 @@ public class InstancedRenderDispatcher {
@SubscribeEvent @SubscribeEvent
public static void onBeginFrame(BeginFrameEvent event) { public static void onBeginFrame(BeginFrameEvent event) {
Contexts.WORLD.getMaterialManager(event.getWorld()) materialManagers.get(event.getWorld())
.checkAndShiftOrigin(event.getInfo()); .checkAndShiftOrigin(event.getInfo());
getTiles(event.getWorld()).beginFrame(event.getInfo()); getTiles(event.getWorld()).beginFrame(event.getInfo());
@ -114,7 +86,7 @@ public class InstancedRenderDispatcher {
event.type.startDrawing(); event.type.startDrawing();
Contexts.WORLD.getMaterialManager(world) materialManagers.get(world)
.render(event.type, event.viewProjection, event.camX, event.camY, event.camZ); .render(event.type, event.viewProjection, event.camX, event.camY, event.camZ);
event.type.endDrawing(); event.type.endDrawing();
@ -129,65 +101,8 @@ public class InstancedRenderDispatcher {
} }
} }
private static final RenderType crumblingLayer = ModelBakery.BLOCK_DESTRUCTION_RENDER_LAYERS.get(0);
public static void renderBreaking(ClientWorld world, Matrix4f viewProjection, double cameraX, double cameraY, double cameraZ) {
if (!Backend.getInstance()
.canUseInstancing(world)) return;
WorldRenderer worldRenderer = Minecraft.getInstance().worldRenderer;
Long2ObjectMap<SortedSet<DestroyBlockProgress>> breakingProgressions = worldRenderer.blockBreakingProgressions;
if (breakingProgressions.isEmpty()) return;
Vector<CrumblingInstanceManager> renderers = blockBreaking.getValue();
BitSet bitSet = new BitSet(10);
for (Long2ObjectMap.Entry<SortedSet<DestroyBlockProgress>> entry : breakingProgressions.long2ObjectEntrySet()) {
BlockPos breakingPos = BlockPos.fromLong(entry.getLongKey());
SortedSet<DestroyBlockProgress> progresses = entry.getValue();
if (progresses != null && !progresses.isEmpty()) {
int blockDamage = progresses.last()
.getPartialBlockDamage();
bitSet.set(blockDamage);
renderers.get(blockDamage)
.add(world.getTileEntity(breakingPos));
}
}
TextureManager textureManager = Minecraft.getInstance().textureManager;
ActiveRenderInfo info = Minecraft.getInstance().gameRenderer.getActiveRenderInfo();
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textureManager.getTexture(PlayerContainer.BLOCK_ATLAS_TEXTURE)
.getGlTextureId());
glActiveTexture(GL_TEXTURE4);
crumblingLayer.startDrawing();
bitSet.stream()
.forEach(i -> {
Texture breaking = textureManager.getTexture(ModelBakery.BLOCK_DESTRUCTION_STAGE_TEXTURES.get(i));
CrumblingInstanceManager renderer = renderers.get(i);
renderer.beginFrame(info);
if (breaking != null) {
glBindTexture(GL_TEXTURE_2D, breaking.getGlTextureId());
renderer.materialManager.render(RenderType.getCutoutMipped(), viewProjection, cameraX, cameraY, cameraZ);
}
renderer.invalidate();
});
crumblingLayer.endDrawing();
glActiveTexture(GL_TEXTURE0);
Texture breaking = textureManager.getTexture(ModelBakery.BLOCK_DESTRUCTION_STAGE_TEXTURES.get(0));
if (breaking != null) glBindTexture(GL_TEXTURE_2D, breaking.getGlTextureId());
}
public static void loadAllInWorld(ClientWorld world) { public static void loadAllInWorld(ClientWorld world) {
Contexts.WORLD.getMaterialManager(world) materialManagers.get(world)
.delete(); .delete();
InstanceManager<TileEntity> tiles = tileInstanceManager.replace(world); InstanceManager<TileEntity> tiles = tileInstanceManager.replace(world);

View file

@ -10,6 +10,8 @@ import com.jozufozu.flywheel.backend.instancing.entity.IEntityInstanceFactory;
import com.jozufozu.flywheel.backend.instancing.tile.ITileInstanceFactory; import com.jozufozu.flywheel.backend.instancing.tile.ITileInstanceFactory;
import com.jozufozu.flywheel.backend.instancing.tile.TileEntityInstance; import com.jozufozu.flywheel.backend.instancing.tile.TileEntityInstance;
import it.unimi.dsi.fastutil.objects.Object2BooleanLinkedOpenHashMap;
import it.unimi.dsi.fastutil.objects.Object2BooleanMap;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType; import net.minecraft.entity.EntityType;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
@ -22,15 +24,54 @@ public class InstancedRenderRegistry {
return INSTANCE; return INSTANCE;
} }
private final Object2BooleanMap<Object> skipRender = new Object2BooleanLinkedOpenHashMap<>();
private final Map<TileEntityType<?>, ITileInstanceFactory<?>> tiles = Maps.newHashMap(); private final Map<TileEntityType<?>, ITileInstanceFactory<?>> tiles = Maps.newHashMap();
private final Map<EntityType<?>, IEntityInstanceFactory<?>> entities = Maps.newHashMap(); private final Map<EntityType<?>, IEntityInstanceFactory<?>> entities = Maps.newHashMap();
public <T extends TileEntity> void register(TileEntityType<? extends T> type, ITileInstanceFactory<? super T> rendererFactory) { protected InstancedRenderRegistry() {
this.tiles.put(type, rendererFactory); skipRender.defaultReturnValue(false);
} }
public <T extends TileEntity> boolean shouldSkipRender(T type) {
return _skipRender(type.getType()) || ((type instanceof IInstanceRendered) && !((IInstanceRendered) type).shouldRenderNormally());
}
public <T extends Entity> boolean shouldSkipRender(T type) {
return _skipRender(type.getType()) || ((type instanceof IInstanceRendered) && !((IInstanceRendered) type).shouldRenderNormally());
}
public <T extends TileEntity> boolean canInstance(TileEntityType<? extends T> type) {
return tiles.containsKey(type);
}
public <T extends Entity> boolean canInstance(EntityType<? extends T> type) {
return entities.containsKey(type);
}
public <T extends TileEntity> TileConfig<? extends T> tile(TileEntityType<? extends T> type) {
return new TileConfig<>(type);
}
public <T extends Entity> EntityConfig<? extends T> entity(EntityType<? extends T> type) {
return new EntityConfig<>(type);
}
/**
* @deprecated will be removed in 0.3.0, use {@link #tile}
*/
@Deprecated
public <T extends TileEntity> void register(TileEntityType<? extends T> type, ITileInstanceFactory<? super T> rendererFactory) {
this.tile(type)
.factory(rendererFactory);
}
/**
* @deprecated will be removed in 0.3.0, use {@link #entity}
*/
@Deprecated
public <T extends Entity> void register(EntityType<? extends T> type, IEntityInstanceFactory<? super T> rendererFactory) { public <T extends Entity> void register(EntityType<? extends T> type, IEntityInstanceFactory<? super T> rendererFactory) {
this.entities.put(type, rendererFactory); this.entity(type)
.factory(rendererFactory);
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@ -54,4 +95,47 @@ public class InstancedRenderRegistry {
else return factory.create(manager, tile); else return factory.create(manager, tile);
} }
private boolean _skipRender(Object o) {
return skipRender.getBoolean(o);
}
public class TileConfig<T extends TileEntity> {
private final TileEntityType<T> type;
public TileConfig(TileEntityType<T> type) {
this.type = type;
}
public TileConfig<T> factory(ITileInstanceFactory<? super T> rendererFactory) {
tiles.put(type, rendererFactory);
return this;
}
public TileConfig<T> setSkipRender(boolean skipRender) {
InstancedRenderRegistry.this.skipRender.put(type, skipRender);
return this;
}
}
public class EntityConfig<T extends Entity> {
private final EntityType<T> type;
public EntityConfig(EntityType<T> type) {
this.type = type;
}
public EntityConfig<T> factory(IEntityInstanceFactory<? super T> rendererFactory) {
entities.put(type, rendererFactory);
return this;
}
public EntityConfig<T> setSkipRender(boolean skipRender) {
InstancedRenderRegistry.this.skipRender.put(type, skipRender);
return this;
}
}
} }

View file

@ -34,7 +34,7 @@ public class MaterialManager<P extends WorldProgram> {
protected final Map<ResourceLocation, ArrayList<MaterialRenderer<P>>> renderers; protected final Map<ResourceLocation, ArrayList<MaterialRenderer<P>>> renderers;
protected final Map<ResourceLocation, Map<MaterialSpec<?>, InstanceMaterial<?>>> materials; protected final Map<ResourceLocation, Map<MaterialSpec<?>, InstanceMaterial<?>>> materials;
private BlockPos originCoordinate = BlockPos.ZERO; protected BlockPos originCoordinate = BlockPos.ZERO;
private final WeakHashSet<OriginShiftListener> listeners; private final WeakHashSet<OriginShiftListener> listeners;

View file

@ -17,6 +17,11 @@ public class EntityInstanceManager extends InstanceManager<Entity> {
super(materialManager); super(materialManager);
} }
@Override
protected boolean canInstance(Entity obj) {
return obj != null && InstancedRenderRegistry.getInstance().canInstance(obj.getType());
}
@Override @Override
protected IInstance createRaw(Entity obj) { protected IInstance createRaw(Entity obj) {
return InstancedRenderRegistry.getInstance() return InstancedRenderRegistry.getInstance()

View file

@ -17,6 +17,11 @@ public class TileInstanceManager extends InstanceManager<TileEntity> {
super(materialManager); super(materialManager);
} }
@Override
protected boolean canInstance(TileEntity obj) {
return obj != null && InstancedRenderRegistry.getInstance().canInstance(obj.getType());
}
@Override @Override
protected IInstance createRaw(TileEntity obj) { protected IInstance createRaw(TileEntity obj) {
return InstancedRenderRegistry.getInstance() return InstancedRenderRegistry.getInstance()

View file

@ -4,6 +4,7 @@ import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.SpecMetaRegistry; import com.jozufozu.flywheel.backend.SpecMetaRegistry;
import com.jozufozu.flywheel.backend.gl.shader.ShaderType; import com.jozufozu.flywheel.backend.gl.shader.ShaderType;
import com.jozufozu.flywheel.core.crumbling.CrumblingProgram;
import com.jozufozu.flywheel.core.shader.WorldFog; import com.jozufozu.flywheel.core.shader.WorldFog;
import com.jozufozu.flywheel.core.shader.WorldProgram; import com.jozufozu.flywheel.core.shader.WorldProgram;
import com.jozufozu.flywheel.core.shader.gamestate.FogStateProvider; import com.jozufozu.flywheel.core.shader.gamestate.FogStateProvider;

View file

@ -1,31 +0,0 @@
package com.jozufozu.flywheel.core;
import static org.lwjgl.opengl.GL20.glUniform2f;
import java.util.List;
import com.jozufozu.flywheel.backend.loading.Program;
import com.jozufozu.flywheel.core.shader.WorldProgram;
import com.jozufozu.flywheel.core.shader.extension.IProgramExtension;
public class CrumblingProgram extends WorldProgram {
protected final int uTextureScale;
protected int uCrumbling;
public CrumblingProgram(Program program, List<IProgramExtension> extensions) {
super(program, extensions);
uTextureScale = getUniformLocation("uTextureScale");
}
@Override
protected void registerSamplers() {
super.registerSamplers();
uCrumbling = setSamplerBinding("uCrumbling", 4);
}
public void setTextureScale(float x, float y) {
glUniform2f(uTextureScale, x, y);
}
}

View file

@ -12,12 +12,13 @@ import net.minecraftforge.client.model.ModelLoader;
/** /**
* A helper class for loading and accessing json models. * A helper class for loading and accessing json models.
* <p> * <br>
* Creating a PartialModel will make the associated modelLocation automatically load. * Creating a PartialModel will make the associated modelLocation automatically load.
* As such, PartialModels must be initialized at or before {@link ModelRegistryEvent}. * PartialModels must be initialized during {@link net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent FMLClientSetupEvent}.
* <br>
* Once {@link ModelBakeEvent} finishes, all PartialModels (with valid modelLocations) * Once {@link ModelBakeEvent} finishes, all PartialModels (with valid modelLocations)
* will have their bakedModel fields populated. * will have their bakedModel fields populated.
* <p> * <br>
* Attempting to create a PartialModel after ModelRegistryEvent will cause an error. * Attempting to create a PartialModel after ModelRegistryEvent will cause an error.
*/ */
public class PartialModel { public class PartialModel {

View file

@ -1,5 +1,6 @@
package com.jozufozu.flywheel.core; package com.jozufozu.flywheel.core;
import java.nio.Buffer;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.ByteOrder; import java.nio.ByteOrder;
import java.util.EnumMap; import java.util.EnumMap;
@ -136,7 +137,7 @@ public class QuadConverter {
type.castAndBuffer(indices, i + 2); type.castAndBuffer(indices, i + 2);
type.castAndBuffer(indices, i + 3); type.castAndBuffer(indices, i + 3);
} }
indices.flip(); ((Buffer) indices).flip();
} }
private GlBuffer getBuffer(GlNumericType type) { private GlBuffer getBuffer(GlNumericType type) {

View file

@ -14,7 +14,6 @@ import com.jozufozu.flywheel.backend.ResourceUtil;
import com.jozufozu.flywheel.backend.ShaderContext; import com.jozufozu.flywheel.backend.ShaderContext;
import com.jozufozu.flywheel.backend.ShaderSources; import com.jozufozu.flywheel.backend.ShaderSources;
import com.jozufozu.flywheel.backend.gl.shader.ShaderType; import com.jozufozu.flywheel.backend.gl.shader.ShaderType;
import com.jozufozu.flywheel.backend.instancing.MaterialManager;
import com.jozufozu.flywheel.backend.instancing.MaterialSpec; import com.jozufozu.flywheel.backend.instancing.MaterialSpec;
import com.jozufozu.flywheel.backend.loading.InstancedArraysTemplate; import com.jozufozu.flywheel.backend.loading.InstancedArraysTemplate;
import com.jozufozu.flywheel.backend.loading.Program; import com.jozufozu.flywheel.backend.loading.Program;
@ -30,7 +29,6 @@ import com.jozufozu.flywheel.core.shader.spec.ProgramState;
import com.jozufozu.flywheel.util.WorldAttached; import com.jozufozu.flywheel.util.WorldAttached;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
import net.minecraft.world.IWorld;
public class WorldContext<P extends WorldProgram> extends ShaderContext<P> { public class WorldContext<P extends WorldProgram> extends ShaderContext<P> {
@ -41,8 +39,6 @@ public class WorldContext<P extends WorldProgram> extends ShaderContext<P> {
protected Supplier<Stream<ResourceLocation>> specStream; protected Supplier<Stream<ResourceLocation>> specStream;
protected TemplateFactory templateFactory; protected TemplateFactory templateFactory;
private final WorldAttached<MaterialManager<P>> worldAttachedMMs = new WorldAttached<>($ -> new MaterialManager<>(this));
private final Map<ShaderType, ResourceLocation> builtins = new EnumMap<>(ShaderType.class); private final Map<ShaderType, ResourceLocation> builtins = new EnumMap<>(ShaderType.class);
private final Map<ShaderType, String> builtinSources = new EnumMap<>(ShaderType.class); private final Map<ShaderType, String> builtinSources = new EnumMap<>(ShaderType.class);
@ -73,10 +69,6 @@ public class WorldContext<P extends WorldProgram> extends ShaderContext<P> {
return this; return this;
} }
public MaterialManager<P> getMaterialManager(IWorld world) {
return worldAttachedMMs.get(world);
}
public WorldContext<P> withSpecStream(Supplier<Stream<ResourceLocation>> specStream) { public WorldContext<P> withSpecStream(Supplier<Stream<ResourceLocation>> specStream) {
this.specStream = specStream; this.specStream = specStream;
return this; return this;
@ -116,13 +108,6 @@ public class WorldContext<P extends WorldProgram> extends ShaderContext<P> {
.forEach(this::loadSpec); .forEach(this::loadSpec);
} }
@Override
public void delete() {
super.delete();
worldAttachedMMs.empty(MaterialManager::delete);
}
@Override @Override
protected Shader getSource(ShaderType type, ResourceLocation name) { protected Shader getSource(ShaderType type, ResourceLocation name) {
Shader source = super.getSource(type, name); Shader source = super.getSource(type, name);

View file

@ -0,0 +1,43 @@
package com.jozufozu.flywheel.core.atlas;
import java.util.HashMap;
import java.util.Map;
import com.jozufozu.flywheel.mixin.atlas.SheetDataAccessor;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.texture.AtlasTexture;
import net.minecraft.client.renderer.texture.Texture;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.util.ResourceLocation;
public class AtlasInfo {
private static final Map<ResourceLocation, SheetData> sheetData = new HashMap<>();
public static AtlasTexture getAtlas(ResourceLocation name) {
Texture texture = Minecraft.getInstance().textureManager.getTexture(name);
if (texture instanceof AtlasTexture)
return (AtlasTexture) texture;
else
return null;
}
public static SheetData getAtlasData(TextureAtlasSprite texture) {
return getAtlasData(texture.getAtlas());
}
public static SheetData getAtlasData(AtlasTexture atlas) {
return getAtlasData(atlas.getId());
}
public static SheetData getAtlasData(ResourceLocation loc) {
return sheetData.get(loc);
}
public static void setAtlasData(ResourceLocation atlas, SheetDataAccessor accessor) {
sheetData.put(atlas, new SheetData(accessor.getWidth(), accessor.getHeight()));
}
}

View file

@ -0,0 +1,11 @@
package com.jozufozu.flywheel.core.atlas;
public class SheetData {
public final int width;
public final int height;
public SheetData(int width, int height) {
this.width = width;
this.height = height;
}
}

View file

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.core; package com.jozufozu.flywheel.core.crumbling;
import com.jozufozu.flywheel.backend.instancing.MaterialManager; import com.jozufozu.flywheel.backend.instancing.MaterialManager;
import com.jozufozu.flywheel.backend.instancing.tile.TileInstanceManager; import com.jozufozu.flywheel.backend.instancing.tile.TileInstanceManager;
@ -6,8 +6,9 @@ import com.jozufozu.flywheel.backend.instancing.tile.TileInstanceManager;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
public class CrumblingInstanceManager extends TileInstanceManager { public class CrumblingInstanceManager extends TileInstanceManager {
public CrumblingInstanceManager() {
super(new MaterialManager<>(Contexts.CRUMBLING)); public CrumblingInstanceManager(MaterialManager<?> materialManager) {
super(materialManager);
} }
@Override @Override

View file

@ -0,0 +1,66 @@
package com.jozufozu.flywheel.core.crumbling;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D;
import static org.lwjgl.opengl.GL11.glBindTexture;
import static org.lwjgl.opengl.GL13.GL_TEXTURE0;
import static org.lwjgl.opengl.GL13.glActiveTexture;
import java.util.ArrayList;
import java.util.Map;
import com.jozufozu.flywheel.backend.instancing.MaterialManager;
import com.jozufozu.flywheel.backend.instancing.MaterialRenderer;
import com.jozufozu.flywheel.core.WorldContext;
import com.jozufozu.flywheel.core.atlas.AtlasInfo;
import com.jozufozu.flywheel.core.atlas.SheetData;
import com.jozufozu.flywheel.core.shader.IProgramCallback;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.texture.TextureManager;
import net.minecraft.inventory.container.PlayerContainer;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.vector.Matrix4f;
public class CrumblingMaterialManager extends MaterialManager<CrumblingProgram> {
public CrumblingMaterialManager(WorldContext<CrumblingProgram> context) {
super(context);
}
/**
* Render every model for every material.
*
* @param layer Which vanilla {@link RenderType} is being drawn?
* @param viewProjection How do we get from camera space to clip space?
* @param callback Provide additional uniforms or state here.
*/
public void render(RenderType layer, Matrix4f viewProjection, double camX, double camY, double camZ, IProgramCallback<CrumblingProgram> callback) {
camX -= originCoordinate.getX();
camY -= originCoordinate.getY();
camZ -= originCoordinate.getZ();
Matrix4f translate = Matrix4f.translate((float) -camX, (float) -camY, (float) -camZ);
translate.multiplyBackward(viewProjection);
TextureManager textureManager = Minecraft.getInstance().textureManager;
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textureManager.getTexture(PlayerContainer.BLOCK_ATLAS_TEXTURE)
.getGlTextureId());
for (MaterialRenderer<CrumblingProgram> material : atlasRenderers) {
material.render(layer, translate, camX, camY, camZ, CrumblingProgram::setDefaultAtlasSize);
}
for (Map.Entry<ResourceLocation, ArrayList<MaterialRenderer<CrumblingProgram>>> entry : renderers.entrySet()) {
glBindTexture(GL_TEXTURE_2D, textureManager.getTexture(entry.getKey())
.getGlTextureId());
SheetData atlasData = AtlasInfo.getAtlasData(entry.getKey());
for (MaterialRenderer<CrumblingProgram> materialRenderer : entry.getValue()) {
materialRenderer.render(layer, translate, camX, camY, camZ, p -> p.setAtlasSize(atlasData.width, atlasData.height));
}
}
}
}

View file

@ -0,0 +1,63 @@
package com.jozufozu.flywheel.core.crumbling;
import static org.lwjgl.opengl.GL20.glUniform2f;
import java.util.List;
import com.jozufozu.flywheel.backend.loading.Program;
import com.jozufozu.flywheel.core.atlas.AtlasInfo;
import com.jozufozu.flywheel.core.atlas.SheetData;
import com.jozufozu.flywheel.core.shader.WorldProgram;
import com.jozufozu.flywheel.core.shader.extension.IProgramExtension;
import net.minecraft.client.renderer.model.ModelBakery;
import net.minecraft.client.renderer.texture.AtlasTexture;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.inventory.container.PlayerContainer;
public class CrumblingProgram extends WorldProgram {
protected final int uTextureScale;
protected int uCrumbling;
public CrumblingProgram(Program program, List<IProgramExtension> extensions) {
super(program, extensions);
uTextureScale = getUniformLocation("uTextureScale");
}
@Override
public void bind() {
super.bind();
setDefaultAtlasSize();
}
@Override
protected void registerSamplers() {
super.registerSamplers();
uCrumbling = setSamplerBinding("uCrumbling", 4);
}
public void setTextureScale(float x, float y) {
glUniform2f(uTextureScale, x, y);
}
public void setDefaultAtlasSize() {
SheetData atlasData = AtlasInfo.getAtlasData(PlayerContainer.BLOCK_ATLAS_TEXTURE);
if (atlasData == null) return;
int width = atlasData.width;
int height = atlasData.height;
setAtlasSize(width, height);
}
public void setAtlasSize(int width, int height) {
AtlasTexture blockAtlas = AtlasInfo.getAtlas(PlayerContainer.BLOCK_ATLAS_TEXTURE);
if (blockAtlas == null) return;
TextureAtlasSprite sprite = blockAtlas.getSprite(ModelBakery.BLOCK_DESTRUCTION_STAGE_TEXTURES.get(0));
setTextureScale(width / (float) sprite.getWidth(), height / (float) sprite.getHeight());
}
}

View file

@ -2,6 +2,7 @@ package com.jozufozu.flywheel.core.materials;
import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer; import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer;
import com.jozufozu.flywheel.backend.instancing.Instancer; import com.jozufozu.flywheel.backend.instancing.Instancer;
import com.jozufozu.flywheel.util.vec.Vec3;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.vector.Quaternion; import net.minecraft.util.math.vector.Quaternion;
@ -19,7 +20,7 @@ public class OrientedData extends BasicData {
private float qX; private float qX;
private float qY; private float qY;
private float qZ; private float qZ;
private float qW; private float qW = 1;
public OrientedData(Instancer<?> owner) { public OrientedData(Instancer<?> owner) {
super(owner); super(owner);
@ -41,6 +42,11 @@ public class OrientedData extends BasicData {
return this; return this;
} }
public OrientedData nudge(Vec3 pos) {
return nudge(pos.getX(), pos.getY(), pos.getZ());
}
public OrientedData nudge(float x, float y, float z) { public OrientedData nudge(float x, float y, float z) {
this.posX += x; this.posX += x;
this.posY += y; this.posY += y;
@ -57,6 +63,10 @@ public class OrientedData extends BasicData {
return setPosition((float) pos.getX(), (float) pos.getY(), (float) pos.getZ()); return setPosition((float) pos.getX(), (float) pos.getY(), (float) pos.getZ());
} }
public OrientedData setPivot(Vec3 pos) {
return setPivot(pos.getX(), pos.getY(), pos.getZ());
}
public OrientedData setPivot(float x, float y, float z) { public OrientedData setPivot(float x, float y, float z) {
this.pivotX = x; this.pivotX = x;
this.pivotY = y; this.pivotY = y;

View file

@ -0,0 +1,8 @@
package com.jozufozu.flywheel.core.model;
public class ModelPart {
public static PartBuilder builder(int sizeU, int sizeV) {
return new PartBuilder(sizeU, sizeV);
}
}

View file

@ -0,0 +1,194 @@
package com.jozufozu.flywheel.core.model;
import static com.jozufozu.flywheel.util.RenderMath.nb;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;
import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer;
import com.jozufozu.flywheel.backend.model.BufferedModel;
import com.jozufozu.flywheel.backend.model.IndexedModel;
import com.jozufozu.flywheel.core.Formats;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.util.Direction;
import net.minecraft.util.math.vector.Vector3f;
public class PartBuilder {
private float sizeU = 64.0F;
private float sizeV = 32.0F;
private TextureAtlasSprite sprite;
private final List<CuboidBuilder> cuboids = new ArrayList<>();
public PartBuilder() { }
public PartBuilder(int sizeU, int sizeV) {
this.setTextureSize(sizeU, sizeV);
}
public PartBuilder setTextureSize(int textureWidth, int textureHeight) {
this.sizeU = (float)textureWidth;
this.sizeV = (float)textureHeight;
return this;
}
public PartBuilder sprite(TextureAtlasSprite sprite) {
this.sprite = sprite;
return this;
}
public CuboidBuilder cuboid() {
return new CuboidBuilder(this);
}
public BufferedModel build() {
int vertices = 0;
for (CuboidBuilder cuboid : cuboids) {
vertices += cuboid.vertices();
}
VecBuffer buffer = VecBuffer.allocate(vertices * Formats.UNLIT_MODEL.getStride());
for (CuboidBuilder cuboid : cuboids) {
cuboid.buffer(buffer);
}
buffer.rewind();
return IndexedModel.fromSequentialQuads(Formats.UNLIT_MODEL, buffer.unwrap(), vertices);
}
private PartBuilder addCuboid(CuboidBuilder builder) {
cuboids.add(builder);
return this;
}
public static class CuboidBuilder {
TextureAtlasSprite sprite;
Set<Direction> visibleFaces = EnumSet.allOf(Direction.class);
int textureOffsetU;
int textureOffsetV;
float posX1;
float posY1;
float posZ1;
float posX2;
float posY2;
float posZ2;
final PartBuilder partBuilder;
CuboidBuilder(PartBuilder partBuilder) {
this.partBuilder = partBuilder;
this.sprite = partBuilder.sprite;
}
public CuboidBuilder textureOffset(int u, int v) {
this.textureOffsetU = u;
this.textureOffsetV = v;
return this;
}
public CuboidBuilder start(float x, float y, float z) {
this.posX1 = x;
this.posY1 = y;
this.posZ1 = z;
return this;
}
public CuboidBuilder end(float x, float y, float z) {
this.posX2 = x;
this.posY2 = y;
this.posZ2 = z;
return this;
}
public CuboidBuilder size(float x, float y, float z) {
this.posX2 = posX1 + x;
this.posY2 = posY1 + y;
this.posZ2 = posZ1 + z;
return this;
}
public CuboidBuilder sprite(TextureAtlasSprite sprite) {
this.sprite = sprite;
return this;
}
public PartBuilder endCuboid() {
return partBuilder.addCuboid(this);
}
public int vertices() {
return visibleFaces.size() * 4;
}
public void buffer(VecBuffer buffer) {
float sizeX = posX2 - posX1;
float sizeY = posY2 - posY1;
float sizeZ = posZ2 - posZ1;
Vector3f lll = new Vector3f(posX1 / 16f, posY1 / 16f, posZ1 / 16f);
Vector3f hll = new Vector3f(posX2 / 16f, posY1 / 16f, posZ1 / 16f);
Vector3f hhl = new Vector3f(posX2 / 16f, posY2 / 16f, posZ1 / 16f);
Vector3f lhl = new Vector3f(posX1 / 16f, posY2 / 16f, posZ1 / 16f);
Vector3f llh = new Vector3f(posX1 / 16f, posY1 / 16f, posZ2 / 16f);
Vector3f hlh = new Vector3f(posX2 / 16f, posY1 / 16f, posZ2 / 16f);
Vector3f hhh = new Vector3f(posX2 / 16f, posY2 / 16f, posZ2 / 16f);
Vector3f lhh = new Vector3f(posX1 / 16f, posY2 / 16f, posZ2 / 16f);
float f4 = getU((float)textureOffsetU);
float f5 = getU((float)textureOffsetU + sizeZ);
float f6 = getU((float)textureOffsetU + sizeZ + sizeX);
float f7 = getU((float)textureOffsetU + sizeZ + sizeX + sizeX);
float f8 = getU((float)textureOffsetU + sizeZ + sizeX + sizeZ);
float f9 = getU((float)textureOffsetU + sizeZ + sizeX + sizeZ + sizeX);
float f10 = getV((float)textureOffsetV);
float f11 = getV((float)textureOffsetV + sizeZ);
float f12 = getV((float)textureOffsetV + sizeZ + sizeY);
quad(buffer, new Vector3f[]{hlh, llh, lll, hll}, f5, f10, f6, f11, Direction.DOWN);
quad(buffer, new Vector3f[]{hhl, lhl, lhh, hhh}, f6, f11, f7, f10, Direction.UP);
quad(buffer, new Vector3f[]{lll, llh, lhh, lhl}, f4, f11, f5, f12, Direction.WEST);
quad(buffer, new Vector3f[]{hll, lll, lhl, hhl}, f5, f11, f6, f12, Direction.NORTH);
quad(buffer, new Vector3f[]{hlh, hll, hhl, hhh}, f6, f11, f8, f12, Direction.EAST);
quad(buffer, new Vector3f[]{llh, hlh, hhh, lhh}, f8, f11, f9, f12, Direction.SOUTH);
}
public void quad(VecBuffer buffer, Vector3f[] vertices, float minU, float minV, float maxU, float maxV, Direction dir) {
Vector3f normal = dir.getUnitVector();
buffer.putVec3(vertices[0].getX(), vertices[0].getY(), vertices[0].getZ()).putVec3(nb(normal.getX()), nb(normal.getY()), nb(normal.getZ())).putVec2(maxU, minV);
buffer.putVec3(vertices[1].getX(), vertices[1].getY(), vertices[1].getZ()).putVec3(nb(normal.getX()), nb(normal.getY()), nb(normal.getZ())).putVec2(minU, minV);
buffer.putVec3(vertices[2].getX(), vertices[2].getY(), vertices[2].getZ()).putVec3(nb(normal.getX()), nb(normal.getY()), nb(normal.getZ())).putVec2(minU, maxV);
buffer.putVec3(vertices[3].getX(), vertices[3].getY(), vertices[3].getZ()).putVec3(nb(normal.getX()), nb(normal.getY()), nb(normal.getZ())).putVec2(maxU, maxV);
}
public float getU(float u) {
if (sprite != null)
return sprite.getInterpolatedU(u * 16 / partBuilder.sizeU);
else
return u;
}
public float getV(float v) {
if (sprite != null)
return sprite.getInterpolatedV(v * 16 / partBuilder.sizeV);
else
return v;
}
}
}

View file

@ -0,0 +1,118 @@
package com.jozufozu.flywheel.core.model;
import net.minecraft.util.Direction;
import net.minecraft.util.math.vector.Vector3f;
public class Readable {
public static class ModelBox {
private final TexturedQuad[] quads;
public final float posX1;
public final float posY1;
public final float posZ1;
public final float posX2;
public final float posY2;
public final float posZ2;
public ModelBox(int texOffU, int texOffV, float posX1, float posY1, float posZ1, float sizeX, float sizeY, float sizeZ, float growX, float growY, float growZ, boolean mirror, float texWidth, float texHeight) {
this.posX1 = posX1;
this.posY1 = posY1;
this.posZ1 = posZ1;
this.posX2 = posX1 + sizeX;
this.posY2 = posY1 + sizeY;
this.posZ2 = posZ1 + sizeZ;
this.quads = new TexturedQuad[6];
float posX2 = posX1 + sizeX;
float posY2 = posY1 + sizeY;
float posZ2 = posZ1 + sizeZ;
posX1 = posX1 - growX;
posY1 = posY1 - growY;
posZ1 = posZ1 - growZ;
posX2 = posX2 + growX;
posY2 = posY2 + growY;
posZ2 = posZ2 + growZ;
if (mirror) {
float tmp = posX2;
posX2 = posX1;
posX1 = tmp;
}
PositionTextureVertex lll = new PositionTextureVertex(posX1, posY1, posZ1, 0.0F, 0.0F);
PositionTextureVertex hll = new PositionTextureVertex(posX2, posY1, posZ1, 0.0F, 8.0F);
PositionTextureVertex hhl = new PositionTextureVertex(posX2, posY2, posZ1, 8.0F, 8.0F);
PositionTextureVertex lhl = new PositionTextureVertex(posX1, posY2, posZ1, 8.0F, 0.0F);
PositionTextureVertex llh = new PositionTextureVertex(posX1, posY1, posZ2, 0.0F, 0.0F);
PositionTextureVertex hlh = new PositionTextureVertex(posX2, posY1, posZ2, 0.0F, 8.0F);
PositionTextureVertex hhh = new PositionTextureVertex(posX2, posY2, posZ2, 8.0F, 8.0F);
PositionTextureVertex lhh = new PositionTextureVertex(posX1, posY2, posZ2, 8.0F, 0.0F);
float f4 = (float)texOffU;
float f5 = (float)texOffU + sizeZ;
float f6 = (float)texOffU + sizeZ + sizeX;
float f7 = (float)texOffU + sizeZ + sizeX + sizeX;
float f8 = (float)texOffU + sizeZ + sizeX + sizeZ;
float f9 = (float)texOffU + sizeZ + sizeX + sizeZ + sizeX;
float f10 = (float)texOffV;
float f11 = (float)texOffV + sizeZ;
float f12 = (float)texOffV + sizeZ + sizeY;
this.quads[2] = new TexturedQuad(new PositionTextureVertex[]{hlh, llh, lll, hll}, f5, f10, f6, f11, texWidth, texHeight, mirror, Direction.DOWN);
this.quads[3] = new TexturedQuad(new PositionTextureVertex[]{hhl, lhl, lhh, hhh}, f6, f11, f7, f10, texWidth, texHeight, mirror, Direction.UP);
this.quads[1] = new TexturedQuad(new PositionTextureVertex[]{lll, llh, lhh, lhl}, f4, f11, f5, f12, texWidth, texHeight, mirror, Direction.WEST);
this.quads[4] = new TexturedQuad(new PositionTextureVertex[]{hll, lll, lhl, hhl}, f5, f11, f6, f12, texWidth, texHeight, mirror, Direction.NORTH);
this.quads[0] = new TexturedQuad(new PositionTextureVertex[]{hlh, hll, hhl, hhh}, f6, f11, f8, f12, texWidth, texHeight, mirror, Direction.EAST);
this.quads[5] = new TexturedQuad(new PositionTextureVertex[]{llh, hlh, hhh, lhh}, f8, f11, f9, f12, texWidth, texHeight, mirror, Direction.SOUTH);
}
}
public static class PositionTextureVertex {
public final float x;
public final float y;
public final float z;
public final float u;
public final float v;
public PositionTextureVertex(float x, float y, float z) {
this(x, y, z, 0, 0);
}
public PositionTextureVertex(float x, float y, float z, float u, float v) {
this.x = x;
this.y = y;
this.z = z;
this.u = u;
this.v = v;
}
public PositionTextureVertex setTexturePosition(float u, float v) {
return new PositionTextureVertex(x, y, z, u, v);
}
}
public static class TexturedQuad {
public final PositionTextureVertex[] vertices;
public final Vector3f normal;
public TexturedQuad(PositionTextureVertex[] vertices, float minU, float minV, float maxU, float maxV, float texWidth, float texHeight, boolean p_i225951_8_, Direction p_i225951_9_) {
this.vertices = vertices;
float w = 0.0F / texWidth;
float h = 0.0F / texHeight;
vertices[0] = vertices[0].setTexturePosition(maxU / texWidth - w, minV / texHeight + h);
vertices[1] = vertices[1].setTexturePosition(minU / texWidth + w, minV / texHeight + h);
vertices[2] = vertices[2].setTexturePosition(minU / texWidth + w, maxV / texHeight - h);
vertices[3] = vertices[3].setTexturePosition(maxU / texWidth - w, maxV / texHeight - h);
if (p_i225951_8_) {
int i = vertices.length;
for(int j = 0; j < i / 2; ++j) {
PositionTextureVertex modelrenderer$positiontexturevertex = vertices[j];
vertices[j] = vertices[i - 1 - j];
vertices[i - 1 - j] = modelrenderer$positiontexturevertex;
}
}
this.normal = p_i225951_9_.getUnitVector();
if (p_i225951_8_) {
this.normal.multiplyComponentwise(-1.0F, 1.0F, 1.0F);
}
}
}
}

View file

@ -0,0 +1,6 @@
@ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault
package com.jozufozu.flywheel.core;
import javax.annotation.ParametersAreNonnullByDefault;
import mcp.MethodsReturnNonnullByDefault;

View file

@ -10,7 +10,7 @@ import org.spongepowered.asm.mixin.injection.Redirect;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.instancing.IInstanceRendered; import com.jozufozu.flywheel.backend.instancing.InstancedRenderRegistry;
import net.minecraft.client.renderer.WorldRenderer; import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.client.world.ClientWorld; import net.minecraft.client.world.ClientWorld;
@ -28,7 +28,9 @@ public class CancelEntityRenderMixin {
.canUseInstancing()) { .canUseInstancing()) {
ArrayList<Entity> filtered = Lists.newArrayList(entities); ArrayList<Entity> filtered = Lists.newArrayList(entities);
filtered.removeIf(entity -> entity instanceof IInstanceRendered && !((IInstanceRendered) entity).shouldRenderNormally());
InstancedRenderRegistry r = InstancedRenderRegistry.getInstance();
filtered.removeIf(r::shouldSkipRender);
return filtered; return filtered;
} }
@ -42,7 +44,9 @@ public class CancelEntityRenderMixin {
.canUseInstancing()) { .canUseInstancing()) {
ArrayList<Entity> filtered = Lists.newArrayList(classInheritanceMultiMap); ArrayList<Entity> filtered = Lists.newArrayList(classInheritanceMultiMap);
filtered.removeIf(entity -> entity instanceof IInstanceRendered && !((IInstanceRendered) entity).shouldRenderNormally());
InstancedRenderRegistry r = InstancedRenderRegistry.getInstance();
filtered.removeIf(r::shouldSkipRender);
return filtered.iterator(); return filtered.iterator();
} }

View file

@ -8,7 +8,7 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.instancing.IInstanceRendered; import com.jozufozu.flywheel.backend.instancing.InstancedRenderRegistry;
import net.minecraft.client.renderer.chunk.ChunkRenderDispatcher; import net.minecraft.client.renderer.chunk.ChunkRenderDispatcher;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
@ -31,7 +31,8 @@ public class CancelTileEntityRenderMixin {
.canUseInstancing()) { .canUseInstancing()) {
List<TileEntity> tiles = cir.getReturnValue(); List<TileEntity> tiles = cir.getReturnValue();
tiles.removeIf(tile -> tile instanceof IInstanceRendered && !((IInstanceRendered) tile).shouldRenderNormally()); InstancedRenderRegistry r = InstancedRenderRegistry.getInstance();
tiles.removeIf(r::shouldSkipRender);
} }
} }
} }

View file

@ -9,6 +9,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.OptifineHandler; import com.jozufozu.flywheel.backend.OptifineHandler;
import com.jozufozu.flywheel.backend.instancing.CrumblingRenderer;
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
import com.jozufozu.flywheel.event.BeginFrameEvent; import com.jozufozu.flywheel.event.BeginFrameEvent;
import com.jozufozu.flywheel.event.ReloadRenderersEvent; import com.jozufozu.flywheel.event.ReloadRenderersEvent;
@ -81,7 +82,7 @@ public class RenderHooksMixin {
.getProjectionMatrix()); .getProjectionMatrix());
Vector3d cameraPos = info.getProjectedView(); Vector3d cameraPos = info.getProjectedView();
InstancedRenderDispatcher.renderBreaking(world, viewProjection, cameraPos.x, cameraPos.y, cameraPos.z); CrumblingRenderer.renderBreaking(world, viewProjection, cameraPos.x, cameraPos.y, cameraPos.z);
if (!OptifineHandler.usingShaders()) GL20.glUseProgram(0); if (!OptifineHandler.usingShaders()) GL20.glUseProgram(0);
} }

View file

@ -12,7 +12,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import com.jozufozu.flywheel.backend.instancing.InstanceManager; import com.jozufozu.flywheel.backend.instancing.InstanceManager;
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
import com.jozufozu.flywheel.backend.instancing.tile.TileInstanceManager;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World; import net.minecraft.world.World;

View file

@ -0,0 +1,32 @@
package com.jozufozu.flywheel.mixin.atlas;
import java.util.stream.Stream;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import com.jozufozu.flywheel.core.atlas.AtlasInfo;
import net.minecraft.client.renderer.texture.AtlasTexture;
import net.minecraft.profiler.IProfiler;
import net.minecraft.resources.IResourceManager;
import net.minecraft.util.ResourceLocation;
@Mixin(AtlasTexture.class)
public abstract class AtlasDataMixin {
@Shadow
public abstract ResourceLocation getId();
@Inject(method = "stitch", at = @At("RETURN"))
public void stealAtlasData(IResourceManager resourceManager, Stream<ResourceLocation> locationStream, IProfiler profiler, int mipMapLevels, CallbackInfoReturnable<AtlasTexture.SheetData> cir) {
AtlasTexture.SheetData value = cir.getReturnValue();
SheetDataAccessor dataAccessor = (SheetDataAccessor) value;
AtlasInfo.setAtlasData(getId(), dataAccessor);
}
}

View file

@ -0,0 +1,17 @@
package com.jozufozu.flywheel.mixin.atlas;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import net.minecraft.client.renderer.texture.AtlasTexture;
@Mixin(AtlasTexture.SheetData.class)
public interface SheetDataAccessor {
@Accessor("width")
int getWidth();
@Accessor("height")
int getHeight();
}

View file

@ -9,8 +9,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import com.jozufozu.flywheel.backend.instancing.InstanceManager; import com.jozufozu.flywheel.backend.instancing.InstanceManager;
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
import com.jozufozu.flywheel.backend.instancing.entity.EntityInstanceManager;
import com.jozufozu.flywheel.backend.instancing.tile.TileInstanceManager;
import com.jozufozu.flywheel.light.LightUpdater; import com.jozufozu.flywheel.light.LightUpdater;
import com.jozufozu.flywheel.util.ChunkUtil; import com.jozufozu.flywheel.util.ChunkUtil;

View file

@ -0,0 +1,8 @@
package com.jozufozu.flywheel.util;
public class RenderMath {
public static byte nb(float f) {
return (byte) (f * 127);
}
}

View file

@ -12,7 +12,7 @@ import net.minecraft.world.IWorld;
public class WorldAttached<T> { public class WorldAttached<T> {
Map<IWorld, T> attached; private final Map<IWorld, T> attached;
private final Function<IWorld, T> factory; private final Function<IWorld, T> factory;
public WorldAttached(Function<IWorld, T> factory) { public WorldAttached(Function<IWorld, T> factory) {

View file

@ -0,0 +1,36 @@
package com.jozufozu.flywheel.util.transform;
import com.mojang.blaze3d.matrix.MatrixStack;
import net.minecraft.util.math.vector.Quaternion;
public class MatrixTransformStack implements TransformStack {
private final MatrixStack internal = new MatrixStack();
public MatrixStack unwrap() {
return internal;
}
@Override
public TransformStack translate(double x, double y, double z) {
internal.translate(x, y, z);
return this;
}
@Override
public TransformStack multiply(Quaternion quaternion) {
internal.multiply(quaternion);
return this;
}
@Override
public TransformStack push() {
return this;
}
@Override
public TransformStack pop() {
return this;
}
}

View file

@ -0,0 +1,90 @@
package com.jozufozu.flywheel.util.transform;
import java.util.ArrayDeque;
import java.util.Deque;
import net.minecraft.util.math.vector.Quaternion;
public class QuaternionTransformStack implements TransformStack {
private final Deque<Transform> stack;
public QuaternionTransformStack() {
stack = new ArrayDeque<>();
stack.add(new Transform());
}
@Override
public TransformStack translate(double x, double y, double z) {
Transform peek = stack.peek();
double qx = peek.qx;
double qy = peek.qy;
double qz = peek.qz;
double qw = peek.qw;
peek.x += qw * x + qy * z - qz * y;
peek.y += qw * y - qx * z + qz * x;
peek.z += qw * z + qx * y - qy * x;
return this;
}
@Override
public TransformStack multiply(Quaternion quaternion) {
return this;
}
@Override
public TransformStack push() {
stack.push(stack.peek().copy());
return this;
}
@Override
public TransformStack pop() {
if (stack.size() == 1) {
stack.peek().loadIdentity();
} else {
stack.pop();
}
return this;
}
private static class Transform {
public double qx;
public double qy;
public double qz;
public double qw;
public double x;
public double y;
public double z;
public Transform() {
qw = 1.0;
}
public void loadIdentity() {
x = y = z = 0.0;
qx = qy = qz = 0.0;
qw = 1.0;
}
public Transform copy() {
Transform transform = new Transform();
transform.qx = this.qx;
transform.qy = this.qy;
transform.qz = this.qz;
transform.qw = this.qw;
transform.x = this.x;
transform.y = this.y;
transform.z = this.z;
return transform;
}
}
}

View file

@ -0,0 +1,79 @@
package com.jozufozu.flywheel.util.transform;
import net.minecraft.util.Direction;
import net.minecraft.util.math.vector.Quaternion;
import net.minecraft.util.math.vector.Vector3d;
import net.minecraft.util.math.vector.Vector3f;
import net.minecraft.util.math.vector.Vector3i;
public interface TransformStack {
Vector3d CENTER = new Vector3d(0.5, 0.5, 0.5);
TransformStack translate(double x, double y, double z);
TransformStack multiply(Quaternion quaternion);
TransformStack push();
TransformStack pop();
default TransformStack rotate(Direction axis, float radians) {
if (radians == 0)
return this;
return multiply(axis.getUnitVector()
.getRadialQuaternion(radians));
}
default TransformStack rotate(double angle, Direction.Axis axis) {
Vector3f vec =
axis == Direction.Axis.X ? Vector3f.POSITIVE_X : axis == Direction.Axis.Y ? Vector3f.POSITIVE_Y : Vector3f.POSITIVE_Z;
return multiply(vec, angle);
}
default TransformStack rotateX(double angle) {
return multiply(Vector3f.POSITIVE_X, angle);
}
default TransformStack rotateY(double angle) {
return multiply(Vector3f.POSITIVE_Y, angle);
}
default TransformStack rotateZ(double angle) {
return multiply(Vector3f.POSITIVE_Z, angle);
}
default TransformStack centre() {
return translate(CENTER);
}
default TransformStack unCentre() {
return translateBack(CENTER);
}
default TransformStack translate(Vector3i vec) {
return translate(vec.getX(), vec.getY(), vec.getZ());
}
default TransformStack translate(Vector3d vec) {
return translate(vec.x, vec.y, vec.z);
}
default TransformStack translateBack(Vector3d vec) {
return translate(-vec.x, -vec.y, -vec.z);
}
default TransformStack nudge(int id) {
long randomBits = (long) id * 31L * 493286711L;
randomBits = randomBits * randomBits * 4392167121L + randomBits * 98761L;
float xNudge = (((float) (randomBits >> 16 & 7L) + 0.5F) / 8.0F - 0.5F) * 0.004F;
float yNudge = (((float) (randomBits >> 20 & 7L) + 0.5F) / 8.0F - 0.5F) * 0.004F;
float zNudge = (((float) (randomBits >> 24 & 7L) + 0.5F) / 8.0F - 0.5F) * 0.004F;
return translate(xNudge, yNudge, zNudge);
}
default TransformStack multiply(Vector3f axis, double angle) {
if (angle == 0)
return this;
return multiply(axis.getDegreesQuaternion((float) angle));
}
}

View file

@ -0,0 +1,80 @@
package com.jozufozu.flywheel.util.vec;
import net.minecraft.util.math.vector.Quaternion;
import net.minecraft.util.math.vector.Vector3f;
public class Vec3 {
public static final Vec3 NEGATIVE_X = new Vec3(-1.0F, 0.0F, 0.0F);
public static final Vec3 POSITIVE_X = new Vec3(1.0F, 0.0F, 0.0F);
public static final Vec3 NEGATIVE_Y = new Vec3(0.0F, -1.0F, 0.0F);
public static final Vec3 POSITIVE_Y = new Vec3(0.0F, 1.0F, 0.0F);
public static final Vec3 NEGATIVE_Z = new Vec3(0.0F, 0.0F, -1.0F);
public static final Vec3 POSITIVE_Z = new Vec3(0.0F, 0.0F, 1.0F);
private float x;
private float y;
private float z;
public Vec3(float x, float y, float z) {
this.x = x;
this.y = y;
this.z = z;
}
public float getX() {
return x;
}
public float getY() {
return y;
}
public float getZ() {
return z;
}
public Vec3 multiply(Quaternion quat) {
Vec4 vec4 = new Vec4(this, 1f);
vec4.multiply(quat);
return set(vec4.getX(), vec4.getY(), vec4.getZ());
}
public Vec3 copy() {
return new Vec3(x, y, z);
}
public Vector3f convert() {
return new Vector3f(x, y, z);
}
public Vec3 set(float x, float y, float z) {
this.x = x;
this.y = y;
this.z = z;
return this;
}
public Vec3 add(Vec3 v) {
return add(v.x, v.y, v.z);
}
public Vec3 add(float x, float y, float z) {
this.x += x;
this.y += y;
this.z += z;
return this;
}
public Vec3 sub(Vec3 v) {
return sub(v.x, v.y, v.z);
}
public Vec3 sub(float x, float y, float z) {
this.x -= x;
this.y -= y;
this.z -= z;
return this;
}
}

View file

@ -0,0 +1,66 @@
package com.jozufozu.flywheel.util.vec;
import net.minecraft.util.math.vector.Quaternion;
public class Vec4 {
private float x;
private float y;
private float z;
private float w;
public Vec4(float x, float y, float z, float w) {
this.x = x;
this.y = y;
this.z = z;
this.w = w;
}
public Vec4(Vec3 vec3) {
this(vec3, 0);
}
public Vec4(Vec3 vec3, float w) {
this.x = vec3.getX();
this.y = vec3.getY();
this.z = vec3.getZ();
this.w = w;
}
public Vec4 multiply(Quaternion quat) {
Quaternion quaternion = new Quaternion(quat);
quaternion.multiply(new Quaternion(this.getX(), this.getY(), this.getZ(), 0.0F));
Quaternion quaternion1 = new Quaternion(quat);
quaternion1.conjugate();
quaternion.multiply(quaternion1);
return set(quaternion.getX(), quaternion.getY(), quaternion.getZ(), this.getW());
}
public Vec3 xyz() {
return new Vec3(x, y, z);
}
public float getX() {
return x;
}
public float getY() {
return y;
}
public float getZ() {
return z;
}
public float getW() {
return w;
}
public Vec4 set(float x, float y, float z, float w) {
this.x = x;
this.y = y;
this.z = z;
this.w = w;
return this;
}
}

View file

@ -0,0 +1,80 @@
package com.jozufozu.flywheel.vanilla;
import com.jozufozu.flywheel.backend.instancing.IDynamicInstance;
import com.jozufozu.flywheel.backend.instancing.MaterialManager;
import com.jozufozu.flywheel.backend.instancing.tile.TileEntityInstance;
import com.jozufozu.flywheel.backend.model.BufferedModel;
import com.jozufozu.flywheel.core.Materials;
import com.jozufozu.flywheel.core.materials.OrientedData;
import com.jozufozu.flywheel.core.model.ModelPart;
import com.jozufozu.flywheel.util.AnimationTickHolder;
import net.minecraft.client.renderer.tileentity.BellTileEntityRenderer;
import net.minecraft.tileentity.BellTileEntity;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.vector.Quaternion;
import net.minecraft.util.math.vector.Vector3f;
public class BellInstance extends TileEntityInstance<BellTileEntity> implements IDynamicInstance {
private final OrientedData bell;
private float lastRingTime = Float.NaN;
public BellInstance(MaterialManager<?> materialManager, BellTileEntity tile) {
super(materialManager, tile);
bell = createBellInstance()
.setPivot(0.5f, 0.75f, 0.5f)
.setPosition(getInstancePosition());
}
@Override
public void beginFrame() {
float ringTime = (float)tile.ringingTicks + AnimationTickHolder.getPartialTicks();
if (ringTime == lastRingTime) return;
lastRingTime = ringTime;
if (tile.isRinging) {
float angle = MathHelper.sin(ringTime / (float) Math.PI) / (4.0F + ringTime / 3.0F);
Vector3f ringAxis = tile.ringDirection.rotateYCCW().getUnitVector();
bell.setRotation(ringAxis.getRadialQuaternion(angle));
} else {
bell.setRotation(Quaternion.IDENTITY);
}
}
@Override
public void updateLight() {
relight(getWorldPosition(), bell);
}
@Override
public void remove() {
bell.delete();
}
private OrientedData createBellInstance() {
return materialManager.getMaterial(Materials.ORIENTED)
.get(tile.getType(), BellInstance::createBellModel)
.createInstance();
}
private static BufferedModel createBellModel() {
return ModelPart.builder(32, 32)
.sprite(BellTileEntityRenderer.field_217653_c.getSprite())
.cuboid()
.start(5.0F, 6.0F, 5.0F)
.size(6.0F, 7.0F, 6.0F)
.endCuboid()
.cuboid()
.textureOffset(0, 13)
.start(4.0F, 4.0F, 4.0F)
.size(8.0F, 2.0F, 8.0F)
.endCuboid()
.build();
}
}

View file

@ -0,0 +1,216 @@
package com.jozufozu.flywheel.vanilla;
import java.util.Calendar;
import javax.annotation.Nonnull;
import com.jozufozu.flywheel.backend.instancing.IDynamicInstance;
import com.jozufozu.flywheel.backend.instancing.MaterialManager;
import com.jozufozu.flywheel.backend.instancing.tile.TileEntityInstance;
import com.jozufozu.flywheel.backend.model.BufferedModel;
import com.jozufozu.flywheel.core.Materials;
import com.jozufozu.flywheel.core.materials.ModelData;
import com.jozufozu.flywheel.core.materials.OrientedData;
import com.jozufozu.flywheel.core.model.ModelPart;
import com.jozufozu.flywheel.util.AnimationTickHolder;
import com.jozufozu.flywheel.util.transform.MatrixTransformStack;
import it.unimi.dsi.fastutil.floats.Float2FloatFunction;
import net.minecraft.block.AbstractChestBlock;
import net.minecraft.block.Block;
import net.minecraft.block.ChestBlock;
import net.minecraft.client.renderer.Atlases;
import net.minecraft.client.renderer.model.RenderMaterial;
import net.minecraft.state.properties.ChestType;
import net.minecraft.tileentity.ChestTileEntity;
import net.minecraft.tileentity.IChestLid;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.tileentity.TileEntityMerger;
import net.minecraft.util.math.vector.Quaternion;
import net.minecraft.util.math.vector.Vector3f;
public class ChestInstance<T extends TileEntity & IChestLid> extends TileEntityInstance<T> implements IDynamicInstance {
private final OrientedData body;
private final ModelData lid;
private final Float2FloatFunction lidProgress;
private final RenderMaterial renderMaterial;
@Nonnull
private final ChestType chestType;
private final Quaternion baseRotation;
private float lastProgress = Float.NaN;
public ChestInstance(MaterialManager<?> materialManager, T tile) {
super(materialManager, tile);
Block block = blockState.getBlock();
chestType = blockState.contains(ChestBlock.TYPE) ? blockState.get(ChestBlock.TYPE) : ChestType.SINGLE;
renderMaterial = Atlases.getChestTexture(tile, chestType, isChristmas());
body = baseInstance()
.setPosition(getInstancePosition());
lid = lidInstance();
if (block instanceof AbstractChestBlock) {
// MatrixStack stack = new MatrixStack();
//
// stack.push();
float horizontalAngle = blockState.get(ChestBlock.FACING).getHorizontalAngle();
baseRotation = Vector3f.POSITIVE_Y.getDegreesQuaternion(-horizontalAngle);
body.setRotation(baseRotation);
AbstractChestBlock<?> chestBlock = (AbstractChestBlock<?>) block;
TileEntityMerger.ICallbackWrapper<? extends ChestTileEntity> wrapper = chestBlock.getBlockEntitySource(blockState, world, getWorldPosition(), true);
this.lidProgress = wrapper.apply(ChestBlock.getAnimationProgressRetriever(tile));
} else {
baseRotation = Quaternion.IDENTITY;
lidProgress = $ -> 0f;
}
}
@Override
public void beginFrame() {
float progress = lidProgress.get(AnimationTickHolder.getPartialTicks());
if (lastProgress == progress) return;
lastProgress = progress;
progress = 1.0F - progress;
progress = 1.0F - progress * progress * progress;
float angleX = -(progress * ((float) Math.PI / 2F));
MatrixTransformStack stack = new MatrixTransformStack();
stack.translate(getInstancePosition())
.translate(0, 9f/16f, 0)
.centre()
.multiply(baseRotation)
.unCentre()
.translate(0, 0, 1f / 16f)
.multiply(Vector3f.POSITIVE_X.getRadialQuaternion(angleX))
.translate(0, 0, -1f / 16f);
lid.setTransform(stack.unwrap());
}
@Override
public void updateLight() {
relight(getWorldPosition(), body, lid);
}
@Override
public void remove() {
body.delete();
lid.delete();
}
private OrientedData baseInstance() {
return materialManager.getMaterial(Materials.ORIENTED, renderMaterial.getAtlasId())
.get("base_" + renderMaterial.getTextureId(), this::getBaseModel)
.createInstance();
}
private ModelData lidInstance() {
return materialManager.getMaterial(Materials.TRANSFORMED, renderMaterial.getAtlasId())
.get("lid_" + renderMaterial.getTextureId(), this::getLidModel)
.createInstance();
}
private BufferedModel getBaseModel() {
switch (chestType) {
case LEFT:
return ModelPart.builder(64, 64)
.sprite(renderMaterial.getSprite())
.cuboid()
.textureOffset(0, 19)
.start(0, 0, 1)
.size(15, 10, 14)
.endCuboid()
.build();
case RIGHT:
return ModelPart.builder(64, 64)
.sprite(renderMaterial.getSprite())
.cuboid()
.textureOffset(0, 19)
.start(1, 0, 1)
.size(15, 10, 14)
.endCuboid()
.build();
}
return ModelPart.builder(64, 64)
.sprite(renderMaterial.getSprite())
.cuboid()
.textureOffset(0, 19)
.start(1, 0, 1)
.end(15, 10, 15)
.endCuboid()
.build();
}
private BufferedModel getLidModel() {
switch (chestType) {
case LEFT:
return ModelPart.builder(64, 64)
.sprite(renderMaterial.getSprite())
.cuboid()
.textureOffset(0, 0)
.start(0, 0, 1)
.size(15, 5, 14)
.endCuboid()
.cuboid()
.start(0, -2, 15)
.size(1, 4, 1)
.endCuboid()
.build();
case RIGHT:
return ModelPart.builder(64, 64)
.sprite(renderMaterial.getSprite())
.cuboid()
.textureOffset(0, 0)
.start(1, 0, 1)
.size(15, 5, 14)
.endCuboid()
.cuboid()
.start(15, -2, 15)
.size(1, 4, 1)
.endCuboid()
.build();
}
return ModelPart.builder(64, 64)
.sprite(renderMaterial.getSprite())
.cuboid()
.textureOffset(0, 0)
.start(1, 0, 1)
.size(14, 5, 14)
.endCuboid()
.cuboid()
.start(7, -2, 15)
.size(2, 4, 1)
.endCuboid()
.build();
}
public static boolean isChristmas() {
Calendar calendar = Calendar.getInstance();
return calendar.get(Calendar.MONTH) + 1 == 12 && calendar.get(Calendar.DATE) >= 24 && calendar.get(Calendar.DATE) <= 26;
}
}

View file

@ -0,0 +1,47 @@
package com.jozufozu.flywheel.vanilla;
import com.jozufozu.flywheel.backend.instancing.InstancedRenderRegistry;
import net.minecraft.tileentity.TileEntityType;
/**
* TODO:
* <table>
* <tr><td>{@link TileEntityType#SIGN}</td><td> {@link net.minecraft.client.renderer.tileentity.SignTileEntityRenderer SignTileEntityRenderer}</td></tr>
* <tr><td>{@link TileEntityType#MOB_SPAWNER}</td><td> {@link net.minecraft.client.renderer.tileentity.MobSpawnerTileEntityRenderer MobSpawnerTileEntityRenderer}</td></tr>
* <tr><td>{@link TileEntityType#PISTON}</td><td> {@link net.minecraft.client.renderer.tileentity.PistonTileEntityRenderer PistonTileEntityRenderer}</td></tr>
* <tr><td>{@link TileEntityType#ENCHANTING_TABLE}</td><td> {@link net.minecraft.client.renderer.tileentity.EnchantmentTableTileEntityRenderer EnchantmentTableTileEntityRenderer}</td></tr>
* <tr><td>{@link TileEntityType#LECTERN}</td><td> {@link net.minecraft.client.renderer.tileentity.LecternTileEntityRenderer LecternTileEntityRenderer}</td></tr>
* <tr><td>{@link TileEntityType#END_PORTAL}</td><td> {@link net.minecraft.client.renderer.tileentity.EndPortalTileEntityRenderer EndPortalTileEntityRenderer}</td></tr>
* <tr><td>{@link TileEntityType#END_GATEWAY}</td><td> {@link net.minecraft.client.renderer.tileentity.EndGatewayTileEntityRenderer EndGatewayTileEntityRenderer}</td></tr>
* <tr><td>{@link TileEntityType#BEACON}</td><td> {@link net.minecraft.client.renderer.tileentity.BeaconTileEntityRenderer BeaconTileEntityRenderer}</td></tr>
* <tr><td>{@link TileEntityType#SKULL}</td><td> {@link net.minecraft.client.renderer.tileentity.SkullTileEntityRenderer SkullTileEntityRenderer}</td></tr>
* <tr><td>{@link TileEntityType#BANNER}</td><td> {@link net.minecraft.client.renderer.tileentity.BannerTileEntityRenderer BannerTileEntityRenderer}</td></tr>
* <tr><td>{@link TileEntityType#STRUCTURE_BLOCK}</td><td> {@link net.minecraft.client.renderer.tileentity.StructureTileEntityRenderer StructureTileEntityRenderer}</td></tr>
* <tr><td>{@link TileEntityType#SHULKER_BOX}</td><td> {@link net.minecraft.client.renderer.tileentity.ShulkerBoxTileEntityRenderer ShulkerBoxTileEntityRenderer}</td></tr>
* <tr><td>{@link TileEntityType#BED}</td><td> {@link net.minecraft.client.renderer.tileentity.BedTileEntityRenderer BedTileEntityRenderer}</td></tr>
* <tr><td>{@link TileEntityType#CONDUIT}</td><td> {@link net.minecraft.client.renderer.tileentity.ConduitTileEntityRenderer ConduitTileEntityRenderer}</td></tr>
* <tr><td>{@link TileEntityType#BELL}</td><td> {@link net.minecraft.client.renderer.tileentity.BellTileEntityRenderer BellTileEntityRenderer}</td></tr>
* <tr><td>{@link TileEntityType#CAMPFIRE}</td><td> {@link net.minecraft.client.renderer.tileentity.CampfireTileEntityRenderer CampfireTileEntityRenderer}</td></tr>
* </table>
*/
public class VanillaInstances {
public static void init() {
InstancedRenderRegistry r = InstancedRenderRegistry.getInstance();
r.tile(TileEntityType.CHEST)
.setSkipRender(true)
.factory(ChestInstance::new);
r.tile(TileEntityType.ENDER_CHEST)
.setSkipRender(true)
.factory(ChestInstance::new);
r.tile(TileEntityType.TRAPPED_CHEST)
.setSkipRender(true)
.factory(ChestInstance::new);
r.tile(TileEntityType.BELL)
.setSkipRender(true)
.factory(BellInstance::new);
}
}

View file

@ -15,6 +15,8 @@
"StoreProjectionMatrixMixin", "StoreProjectionMatrixMixin",
"TileRemoveMixin", "TileRemoveMixin",
"TileWorldHookMixin", "TileWorldHookMixin",
"atlas.AtlasDataMixin",
"atlas.SheetDataAccessor",
"light.LightUpdateMixin", "light.LightUpdateMixin",
"light.NetworkLightUpdateMixin" "light.NetworkLightUpdateMixin"
], ],