mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2024-12-27 07:26:48 +01:00
Basic model abstraction
- Stop providing a buffered model supplier - Instead, provide an IModel supplier - IModel exposes basic properties of models - IModel exposes a method to copy the model to a VecBuffer
This commit is contained in:
parent
7ad7512e7e
commit
721b3b8633
11 changed files with 225 additions and 105 deletions
|
@ -15,6 +15,8 @@ import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
|
|||
import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer;
|
||||
import com.jozufozu.flywheel.backend.material.MaterialSpec;
|
||||
import com.jozufozu.flywheel.backend.model.BufferedModel;
|
||||
import com.jozufozu.flywheel.core.model.IModel;
|
||||
import com.jozufozu.flywheel.core.model.ModelUtil;
|
||||
import com.jozufozu.flywheel.util.AttribUtil;
|
||||
|
||||
import net.minecraft.util.math.vector.Vector3i;
|
||||
|
@ -23,7 +25,7 @@ public class Instancer<D extends InstanceData> {
|
|||
|
||||
public final Supplier<Vector3i> originCoordinate;
|
||||
|
||||
protected final Supplier<BufferedModel> gen;
|
||||
protected final Supplier<IModel> gen;
|
||||
protected BufferedModel model;
|
||||
|
||||
protected final VertexFormat instanceFormat;
|
||||
|
@ -40,7 +42,7 @@ public class Instancer<D extends InstanceData> {
|
|||
boolean anyToRemove;
|
||||
boolean anyToUpdate;
|
||||
|
||||
public Instancer(Supplier<BufferedModel> model, Supplier<Vector3i> originCoordinate, MaterialSpec<D> spec) {
|
||||
public Instancer(Supplier<IModel> model, Supplier<Vector3i> originCoordinate, MaterialSpec<D> spec) {
|
||||
this.gen = model;
|
||||
this.factory = spec.getInstanceFactory();
|
||||
this.instanceFormat = spec.getInstanceFormat();
|
||||
|
@ -71,7 +73,7 @@ public class Instancer<D extends InstanceData> {
|
|||
}
|
||||
|
||||
private void init() {
|
||||
model = gen.get();
|
||||
model = ModelUtil.getIndexedModel(gen.get());
|
||||
initialized = true;
|
||||
|
||||
if (model.getVertexCount() <= 0)
|
||||
|
|
|
@ -3,38 +3,32 @@ package com.jozufozu.flywheel.backend.material;
|
|||
import java.nio.Buffer;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import com.google.common.cache.Cache;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.jozufozu.flywheel.backend.RenderWork;
|
||||
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
|
||||
import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer;
|
||||
import com.jozufozu.flywheel.backend.instancing.InstanceData;
|
||||
import com.jozufozu.flywheel.backend.instancing.Instancer;
|
||||
import com.jozufozu.flywheel.backend.model.BufferedModel;
|
||||
import com.jozufozu.flywheel.backend.model.IndexedModel;
|
||||
import com.jozufozu.flywheel.core.PartialModel;
|
||||
import com.jozufozu.flywheel.util.BufferBuilderReader;
|
||||
import com.jozufozu.flywheel.core.model.BlockModel;
|
||||
import com.jozufozu.flywheel.core.model.IModel;
|
||||
import com.jozufozu.flywheel.util.RenderUtil;
|
||||
import com.jozufozu.flywheel.util.VirtualEmptyModelData;
|
||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.BlockModelRenderer;
|
||||
import net.minecraft.client.renderer.BlockRendererDispatcher;
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.client.renderer.model.IBakedModel;
|
||||
import net.minecraft.client.renderer.texture.OverlayTexture;
|
||||
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.vector.Vector3i;
|
||||
|
||||
public class InstanceMaterial<D extends InstanceData> {
|
||||
|
@ -100,7 +94,7 @@ public class InstanceMaterial<D extends InstanceData> {
|
|||
return model(toRender, () -> buildModel(toRender));
|
||||
}
|
||||
|
||||
public Instancer<D> model(Object key, Supplier<BufferedModel> supplier) {
|
||||
public Instancer<D> model(Object key, Supplier<IModel> supplier) {
|
||||
try {
|
||||
return models.get(key, () -> new Instancer<>(supplier, originCoordinate, spec));
|
||||
} catch (ExecutionException e) {
|
||||
|
@ -109,70 +103,18 @@ public class InstanceMaterial<D extends InstanceData> {
|
|||
}
|
||||
}
|
||||
|
||||
private BufferedModel buildModel(BlockState renderedState) {
|
||||
private IModel buildModel(BlockState renderedState) {
|
||||
BlockRendererDispatcher dispatcher = Minecraft.getInstance()
|
||||
.getBlockRenderer();
|
||||
return buildModel(dispatcher.getBlockModel(renderedState), renderedState);
|
||||
}
|
||||
|
||||
private BufferedModel buildModel(IBakedModel model, BlockState renderedState) {
|
||||
private IModel buildModel(IBakedModel model, BlockState renderedState) {
|
||||
return buildModel(model, renderedState, new MatrixStack());
|
||||
}
|
||||
|
||||
private BufferedModel buildModel(IBakedModel model, BlockState referenceState, MatrixStack ms) {
|
||||
BufferBuilderReader reader = new BufferBuilderReader(getBufferBuilder(model, referenceState, ms));
|
||||
private IModel buildModel(IBakedModel model, BlockState referenceState, MatrixStack ms) {
|
||||
|
||||
int vertexCount = reader.getVertexCount();
|
||||
|
||||
ByteBuffer vertices = ByteBuffer.allocate(vertexCount * modelFormat.getStride());
|
||||
vertices.order(ByteOrder.nativeOrder());
|
||||
|
||||
for (int i = 0; i < vertexCount; i++) {
|
||||
vertices.putFloat(reader.getX(i));
|
||||
vertices.putFloat(reader.getY(i));
|
||||
vertices.putFloat(reader.getZ(i));
|
||||
|
||||
vertices.put(reader.getNX(i));
|
||||
vertices.put(reader.getNY(i));
|
||||
vertices.put(reader.getNZ(i));
|
||||
|
||||
vertices.putFloat(reader.getU(i));
|
||||
vertices.putFloat(reader.getV(i));
|
||||
}
|
||||
|
||||
((Buffer) vertices).rewind();
|
||||
|
||||
// return new BufferedModel(GlPrimitive.QUADS, format, vertices, vertexCount);
|
||||
|
||||
return IndexedModel.fromSequentialQuads(modelFormat, vertices, vertexCount);
|
||||
return new BlockModel(modelFormat, model, referenceState, ms);
|
||||
}
|
||||
|
||||
// DOWN, UP, NORTH, SOUTH, WEST, EAST, null
|
||||
private static final Direction[] dirs;
|
||||
|
||||
static {
|
||||
Direction[] directions = Direction.values();
|
||||
|
||||
dirs = Arrays.copyOf(directions, directions.length + 1);
|
||||
}
|
||||
|
||||
public static BufferBuilder getBufferBuilder(IBakedModel model, BlockState referenceState, MatrixStack ms) {
|
||||
Minecraft mc = Minecraft.getInstance();
|
||||
BlockRendererDispatcher dispatcher = mc.getBlockRenderer();
|
||||
BlockModelRenderer blockRenderer = dispatcher.getModelRenderer();
|
||||
BufferBuilder builder = new BufferBuilder(512);
|
||||
|
||||
// BakedQuadWrapper quadReader = new BakedQuadWrapper();
|
||||
//
|
||||
// IModelData modelData = model.getModelData(mc.world, BlockPos.ZERO.up(255), referenceState, VirtualEmptyModelData.INSTANCE);
|
||||
// List<BakedQuad> quads = Arrays.stream(dirs)
|
||||
// .flatMap(dir -> model.getQuads(referenceState, dir, mc.world.rand, modelData).stream())
|
||||
// .collect(Collectors.toList());
|
||||
|
||||
builder.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK);
|
||||
blockRenderer.renderModel(mc.level, model, referenceState, BlockPos.ZERO.above(255), ms, builder, true, mc.level.random, 42, OverlayTexture.NO_OVERLAY, VirtualEmptyModelData.INSTANCE);
|
||||
builder.end();
|
||||
return builder;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
101
src/main/java/com/jozufozu/flywheel/core/model/BlockModel.java
Normal file
101
src/main/java/com/jozufozu/flywheel/core/model/BlockModel.java
Normal file
|
@ -0,0 +1,101 @@
|
|||
package com.jozufozu.flywheel.core.model;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
|
||||
import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer;
|
||||
import com.jozufozu.flywheel.backend.model.ElementBuffer;
|
||||
import com.jozufozu.flywheel.core.QuadConverter;
|
||||
import com.jozufozu.flywheel.util.BufferBuilderReader;
|
||||
import com.jozufozu.flywheel.util.VirtualEmptyModelData;
|
||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.BlockModelRenderer;
|
||||
import net.minecraft.client.renderer.BlockRendererDispatcher;
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.client.renderer.model.IBakedModel;
|
||||
import net.minecraft.client.renderer.texture.OverlayTexture;
|
||||
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
public class BlockModel implements IModel {
|
||||
private static final MatrixStack IDENTITY = new MatrixStack();
|
||||
|
||||
private final BufferBuilderReader reader;
|
||||
|
||||
private final VertexFormat modelFormat;
|
||||
|
||||
public BlockModel(VertexFormat modelFormat, IBakedModel model, BlockState referenceState) {
|
||||
this(modelFormat, model, referenceState, IDENTITY);
|
||||
}
|
||||
|
||||
public BlockModel(VertexFormat modelFormat, IBakedModel model, BlockState referenceState, MatrixStack ms) {
|
||||
this.modelFormat = modelFormat;
|
||||
reader = new BufferBuilderReader(getBufferBuilder(model, referenceState, ms));
|
||||
}
|
||||
|
||||
@Override
|
||||
public VertexFormat format() {
|
||||
return modelFormat;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int vertexCount() {
|
||||
return reader.getVertexCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buffer(VecBuffer buffer) {
|
||||
|
||||
int vertexCount = vertexCount();
|
||||
|
||||
for (int i = 0; i < vertexCount; i++) {
|
||||
buffer.putVec3(reader.getX(i), reader.getY(i), reader.getZ(i));
|
||||
|
||||
buffer.putVec3(reader.getNX(i), reader.getNY(i), reader.getNZ(i));
|
||||
|
||||
buffer.putVec2(reader.getU(i), reader.getV(i));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ElementBuffer createEBO() {
|
||||
return QuadConverter.getInstance()
|
||||
.quads2Tris(vertexCount() / 4);
|
||||
}
|
||||
|
||||
public static BufferBuilder getBufferBuilder(IBakedModel model, BlockState referenceState, MatrixStack ms) {
|
||||
Minecraft mc = Minecraft.getInstance();
|
||||
BlockRendererDispatcher dispatcher = mc.getBlockRenderer();
|
||||
BlockModelRenderer blockRenderer = dispatcher.getModelRenderer();
|
||||
BufferBuilder builder = new BufferBuilder(512);
|
||||
|
||||
// BakedQuadWrapper quadReader = new BakedQuadWrapper();
|
||||
//
|
||||
// IModelData modelData = model.getModelData(mc.world, BlockPos.ZERO.up(255), referenceState, VirtualEmptyModelData.INSTANCE);
|
||||
// List<BakedQuad> quads = Arrays.stream(dirs)
|
||||
// .flatMap(dir -> model.getQuads(referenceState, dir, mc.world.rand, modelData).stream())
|
||||
// .collect(Collectors.toList());
|
||||
|
||||
builder.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK);
|
||||
blockRenderer.renderModel(mc.level, model, referenceState, BlockPos.ZERO.above(255), ms, builder, true, mc.level.random, 42, OverlayTexture.NO_OVERLAY, VirtualEmptyModelData.INSTANCE);
|
||||
builder.end();
|
||||
return builder;
|
||||
}
|
||||
|
||||
// DOWN, UP, NORTH, SOUTH, WEST, EAST, null
|
||||
private static final Direction[] dirs;
|
||||
|
||||
static {
|
||||
Direction[] directions = Direction.values();
|
||||
|
||||
dirs = Arrays.copyOf(directions, directions.length + 1);
|
||||
}
|
||||
}
|
26
src/main/java/com/jozufozu/flywheel/core/model/IModel.java
Normal file
26
src/main/java/com/jozufozu/flywheel/core/model/IModel.java
Normal file
|
@ -0,0 +1,26 @@
|
|||
package com.jozufozu.flywheel.core.model;
|
||||
|
||||
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
|
||||
import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer;
|
||||
import com.jozufozu.flywheel.backend.model.ElementBuffer;
|
||||
|
||||
/**
|
||||
* A model that can be rendered by flywheel.
|
||||
*/
|
||||
public interface IModel {
|
||||
|
||||
/**
|
||||
* Copy this model into the given buffer.
|
||||
*/
|
||||
void buffer(VecBuffer buffer);
|
||||
|
||||
int vertexCount();
|
||||
|
||||
VertexFormat format();
|
||||
|
||||
ElementBuffer createEBO();
|
||||
|
||||
default int size() {
|
||||
return vertexCount() * format().getStride();
|
||||
}
|
||||
}
|
|
@ -1,8 +1,53 @@
|
|||
package com.jozufozu.flywheel.core.model;
|
||||
|
||||
public class ModelPart {
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
|
||||
import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer;
|
||||
import com.jozufozu.flywheel.backend.model.ElementBuffer;
|
||||
import com.jozufozu.flywheel.core.Formats;
|
||||
import com.jozufozu.flywheel.core.QuadConverter;
|
||||
|
||||
public class ModelPart implements IModel {
|
||||
|
||||
private final List<PartBuilder.CuboidBuilder> cuboids;
|
||||
private int vertices;
|
||||
|
||||
public ModelPart(List<PartBuilder.CuboidBuilder> cuboids) {
|
||||
this.cuboids = cuboids;
|
||||
|
||||
vertices = 0;
|
||||
|
||||
for (PartBuilder.CuboidBuilder cuboid : cuboids) {
|
||||
vertices += cuboid.vertices();
|
||||
}
|
||||
}
|
||||
|
||||
public static PartBuilder builder(int sizeU, int sizeV) {
|
||||
return new PartBuilder(sizeU, sizeV);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buffer(VecBuffer buffer) {
|
||||
for (PartBuilder.CuboidBuilder cuboid : cuboids) {
|
||||
cuboid.buffer(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int vertexCount() {
|
||||
return vertices;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VertexFormat format() {
|
||||
return Formats.UNLIT_MODEL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ElementBuffer createEBO() {
|
||||
return QuadConverter.getInstance()
|
||||
.quads2Tris(vertices / 4);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
package com.jozufozu.flywheel.core.model;
|
||||
|
||||
import java.nio.Buffer;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer;
|
||||
import com.jozufozu.flywheel.backend.model.IndexedModel;
|
||||
|
||||
public class ModelUtil {
|
||||
public static IndexedModel getIndexedModel(IModel blockModel) {
|
||||
ByteBuffer vertices = ByteBuffer.allocate(blockModel.size());
|
||||
vertices.order(ByteOrder.nativeOrder());
|
||||
|
||||
blockModel.buffer(new VecBuffer(vertices));
|
||||
|
||||
((Buffer) vertices).rewind();
|
||||
|
||||
return new IndexedModel(blockModel.format(), vertices, blockModel.vertexCount(), blockModel.createEBO());
|
||||
}
|
||||
}
|
|
@ -6,11 +6,9 @@ import java.util.ArrayList;
|
|||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
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;
|
||||
|
@ -18,23 +16,16 @@ import net.minecraft.util.math.vector.Vector3f;
|
|||
|
||||
public class PartBuilder {
|
||||
|
||||
private float sizeU = 64.0F;
|
||||
private float sizeV = 32.0F;
|
||||
private final float sizeU;
|
||||
private final float sizeV;
|
||||
|
||||
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;
|
||||
this.sizeU = (float) sizeU;
|
||||
this.sizeV = (float) sizeV;
|
||||
}
|
||||
|
||||
public PartBuilder sprite(TextureAtlasSprite sprite) {
|
||||
|
@ -46,22 +37,8 @@ public class PartBuilder {
|
|||
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);
|
||||
public ModelPart build() {
|
||||
return new ModelPart(cuboids);
|
||||
}
|
||||
|
||||
private PartBuilder addCuboid(CuboidBuilder builder) {
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
@ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault
|
||||
package com.jozufozu.flywheel.core.model;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
import mcp.MethodsReturnNonnullByDefault;
|
|
@ -64,7 +64,7 @@ public class BellInstance extends TileEntityInstance<BellTileEntity> implements
|
|||
.createInstance();
|
||||
}
|
||||
|
||||
private static BufferedModel createBellModel() {
|
||||
private static ModelPart createBellModel() {
|
||||
return ModelPart.builder(32, 32)
|
||||
.sprite(BellTileEntityRenderer.BELL_RESOURCE_LOCATION.sprite())
|
||||
.cuboid()
|
||||
|
|
|
@ -134,7 +134,7 @@ public class ChestInstance<T extends TileEntity & IChestLid> extends TileEntityI
|
|||
.createInstance();
|
||||
}
|
||||
|
||||
private BufferedModel getBaseModel() {
|
||||
private ModelPart getBaseModel() {
|
||||
|
||||
switch (chestType) {
|
||||
case LEFT:
|
||||
|
@ -167,7 +167,7 @@ public class ChestInstance<T extends TileEntity & IChestLid> extends TileEntityI
|
|||
.build();
|
||||
}
|
||||
|
||||
private BufferedModel getLidModel() {
|
||||
private ModelPart getLidModel() {
|
||||
|
||||
switch (chestType) {
|
||||
case LEFT:
|
||||
|
|
|
@ -101,7 +101,7 @@ public class ShulkerBoxInstance extends TileEntityInstance<ShulkerBoxTileEntity>
|
|||
.createInstance();
|
||||
}
|
||||
|
||||
private BufferedModel makeBaseModel() {
|
||||
private ModelPart makeBaseModel() {
|
||||
return ModelPart.builder(64, 64)
|
||||
.sprite(texture)
|
||||
.cuboid()
|
||||
|
@ -112,7 +112,7 @@ public class ShulkerBoxInstance extends TileEntityInstance<ShulkerBoxTileEntity>
|
|||
.build();
|
||||
}
|
||||
|
||||
private BufferedModel makeLidModel() {
|
||||
private ModelPart makeLidModel() {
|
||||
return ModelPart.builder(64, 64)
|
||||
.sprite(texture)
|
||||
.cuboid()
|
||||
|
|
Loading…
Reference in a new issue