mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2025-02-10 20:25:03 +01:00
Merge remote-tracking branch 'origin/1.18/dev' into 1.18/fabric/dev
Conflicts: build.gradle src/main/java/com/jozufozu/flywheel/Flywheel.java src/main/java/com/jozufozu/flywheel/config/FlwPackets.java src/main/java/com/jozufozu/flywheel/core/model/ModelTransformer.java src/main/java/com/jozufozu/flywheel/core/model/ModelUtil.java
This commit is contained in:
commit
c4ef94f5f5
43 changed files with 979 additions and 270 deletions
|
@ -21,6 +21,12 @@ java.toolchain.languageVersion = JavaLanguageVersion.of(17)
|
||||||
println('Java: ' + System.getProperty('java.version') + ' JVM: ' + System.getProperty('java.vm.version') + '(' + System.getProperty('java.vendor') + ') Arch: ' + System.getProperty('os.arch'))
|
println('Java: ' + System.getProperty('java.version') + ' JVM: ' + System.getProperty('java.vm.version') + '(' + System.getProperty('java.vendor') + ') Arch: ' + System.getProperty('os.arch'))
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
|
maven {
|
||||||
|
url 'https://www.cursemaven.com'
|
||||||
|
content {
|
||||||
|
includeGroup "curse.maven"
|
||||||
|
}
|
||||||
|
}
|
||||||
maven {
|
maven {
|
||||||
name 'tterrag maven'
|
name 'tterrag maven'
|
||||||
url 'https://maven.tterrag.com/'
|
url 'https://maven.tterrag.com/'
|
||||||
|
@ -49,6 +55,8 @@ dependencies {
|
||||||
// Fabric API
|
// Fabric API
|
||||||
modImplementation "net.fabricmc.fabric-api:fabric-api:${fabric_version}"
|
modImplementation "net.fabricmc.fabric-api:fabric-api:${fabric_version}"
|
||||||
|
|
||||||
|
modCompileOnly 'curse.maven:starlight-521783:3554912'
|
||||||
|
|
||||||
implementation 'com.google.code.findbugs:jsr305:3.0.2'
|
implementation 'com.google.code.findbugs:jsr305:3.0.2'
|
||||||
modCompileOnly 'maven.modrinth:indium:1.0.2-alpha1+mc1.18'
|
modCompileOnly 'maven.modrinth:indium:1.0.2-alpha1+mc1.18'
|
||||||
modCompileOnly 'io.vram:frex-fabric-mc118:6.0.229'
|
modCompileOnly 'io.vram:frex-fabric-mc118:6.0.229'
|
||||||
|
|
|
@ -1,4 +1,12 @@
|
||||||
0.4.1a:
|
0.5.0:
|
||||||
|
New
|
||||||
|
- Added parallel batching backend, effectively a CPU instancer.
|
||||||
|
- Now partially compatible with starlight.
|
||||||
|
Technical/API
|
||||||
|
- Much more flexible vertex formats.
|
||||||
|
- Do instance updates/ticking entirely async.
|
||||||
|
|
||||||
|
0.4.2-rc:
|
||||||
Fixes
|
Fixes
|
||||||
- Partially fix crash on intel and mesa drivers (needs Create to update)
|
- Partially fix crash on intel and mesa drivers (needs Create to update)
|
||||||
- Fix garbage rendering on AMD GPUs
|
- Fix garbage rendering on AMD GPUs
|
||||||
|
|
|
@ -8,7 +8,7 @@ import net.minecraft.resources.ResourceLocation;
|
||||||
public class Flywheel {
|
public class Flywheel {
|
||||||
|
|
||||||
public static final String ID = "flywheel";
|
public static final String ID = "flywheel";
|
||||||
public static final Logger log = LogManager.getLogger(Flywheel.class);
|
public static final Logger LOGGER = LogManager.getLogger(Flywheel.class);
|
||||||
|
|
||||||
public static ResourceLocation rl(String path) {
|
public static ResourceLocation rl(String path) {
|
||||||
return new ResourceLocation(ID, path);
|
return new ResourceLocation(ID, path);
|
||||||
|
|
|
@ -58,6 +58,6 @@ public class FlywheelClient implements ClientModInitializer {
|
||||||
// Only thing I've seen that's close to a fix is to force the class to load before trying to use it.
|
// Only thing I've seen that's close to a fix is to force the class to load before trying to use it.
|
||||||
// From the SpongePowered discord:
|
// From the SpongePowered discord:
|
||||||
// https://discord.com/channels/142425412096491520/626802111455297538/675007581168599041
|
// https://discord.com/channels/142425412096491520/626802111455297538/675007581168599041
|
||||||
Flywheel.log.info("Successfully loaded {}", PausedPartialTickAccessor.class.getName());
|
Flywheel.LOGGER.info("Successfully loaded {}", PausedPartialTickAccessor.class.getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,9 +18,7 @@ public abstract class GlObject {
|
||||||
|
|
||||||
protected final void checkHandle() {
|
protected final void checkHandle() {
|
||||||
if (this.isInvalid()) {
|
if (this.isInvalid()) {
|
||||||
String descriptor = getDescriptor();
|
throw new IllegalStateException("handle is not valid.");
|
||||||
String message = (descriptor == null ? "" : (descriptor + " ")) + "handle is not valid.";
|
|
||||||
throw new IllegalStateException(message);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,10 +31,8 @@ public abstract class GlObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void delete() {
|
public void delete() {
|
||||||
if (isInvalid()) {
|
if (this.isInvalid()) {
|
||||||
String descriptor = getDescriptor();
|
throw new IllegalStateException("handle already deleted.");
|
||||||
String message = (descriptor == null ? "" : (descriptor + " ")) + "handle already deleted.";
|
|
||||||
throw new IllegalStateException(message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteInternal(handle);
|
deleteInternal(handle);
|
||||||
|
@ -45,7 +41,4 @@ public abstract class GlObject {
|
||||||
|
|
||||||
protected abstract void deleteInternal(int handle);
|
protected abstract void deleteInternal(int handle);
|
||||||
|
|
||||||
protected String getDescriptor() {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
package com.jozufozu.flywheel.backend.gl;
|
package com.jozufozu.flywheel.backend.gl;
|
||||||
|
|
||||||
|
import org.lwjgl.opengl.GL20;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.core.layout.BufferLayout;
|
||||||
|
import com.jozufozu.flywheel.core.layout.LayoutItem;
|
||||||
import com.jozufozu.flywheel.mixin.BufferUploaderAccessor;
|
import com.jozufozu.flywheel.mixin.BufferUploaderAccessor;
|
||||||
import com.jozufozu.flywheel.util.AttribUtil;
|
|
||||||
import com.mojang.blaze3d.platform.GlStateManager;
|
import com.mojang.blaze3d.platform.GlStateManager;
|
||||||
|
|
||||||
public class GlVertexArray extends GlObject {
|
public class GlVertexArray extends GlObject {
|
||||||
|
@ -20,11 +23,28 @@ public class GlVertexArray extends GlObject {
|
||||||
BufferUploaderAccessor.flywheel$setLastVAO(0);
|
BufferUploaderAccessor.flywheel$setLastVAO(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void enableArrays(int count) {
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
GL20.glEnableVertexAttribArray(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void disableArrays(int count) {
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
GL20.glDisableVertexAttribArray(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void bindAttributes(int startIndex, BufferLayout type) {
|
||||||
|
int offset = 0;
|
||||||
|
for (LayoutItem spec : type.getLayoutItems()) {
|
||||||
|
spec.vertexAttribPointer(type.getStride(), startIndex, offset);
|
||||||
|
startIndex += spec.getAttributeCount();
|
||||||
|
offset += spec.getSize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected void deleteInternal(int handle) {
|
protected void deleteInternal(int handle) {
|
||||||
GlStateManager._glDeleteVertexArrays(handle);
|
GlStateManager._glDeleteVertexArrays(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void enableArrays(int count) {
|
|
||||||
AttribUtil.enableArrays(count);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ public enum GlError {
|
||||||
// TODO: build flag? to enable or disable this function
|
// TODO: build flag? to enable or disable this function
|
||||||
GlError err = GlError.poll();
|
GlError err = GlError.poll();
|
||||||
if (err != null) {
|
if (err != null) {
|
||||||
Flywheel.log.error("{}: {}", err.name(), context.get());
|
Flywheel.LOGGER.error("{}: {}", err.name(), context.get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -139,7 +139,7 @@ public class ParallelTaskEngine implements TaskEngine {
|
||||||
try {
|
try {
|
||||||
job.run();
|
job.run();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Flywheel.log.error(e);
|
Flywheel.LOGGER.error(e);
|
||||||
} finally {
|
} finally {
|
||||||
ParallelTaskEngine.this.wg.done();
|
ParallelTaskEngine.this.wg.done();
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,13 +51,7 @@ public class BatchedMaterialGroup implements MaterialGroup {
|
||||||
|
|
||||||
for (BatchedMaterial<?> material : materials.values()) {
|
for (BatchedMaterial<?> material : materials.values()) {
|
||||||
for (CPUInstancer<?> instancer : material.models.values()) {
|
for (CPUInstancer<?> instancer : material.models.values()) {
|
||||||
if (consumer.hasOverlay()) {
|
instancer.sbb.context.outputColorDiffuse = !consumer.hasOverlay();
|
||||||
instancer.sbb.context.fullNormalTransform = false;
|
|
||||||
instancer.sbb.context.outputColorDiffuse = false;
|
|
||||||
} else {
|
|
||||||
instancer.sbb.context.fullNormalTransform = false;
|
|
||||||
instancer.sbb.context.outputColorDiffuse = true;
|
|
||||||
}
|
|
||||||
instancer.submitTasks(stack, pool, consumer);
|
instancer.submitTasks(stack, pool, consumer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,6 @@ import com.jozufozu.flywheel.backend.instancing.TaskEngine;
|
||||||
import com.jozufozu.flywheel.backend.model.DirectVertexConsumer;
|
import com.jozufozu.flywheel.backend.model.DirectVertexConsumer;
|
||||||
import com.jozufozu.flywheel.core.model.Model;
|
import com.jozufozu.flywheel.core.model.Model;
|
||||||
import com.jozufozu.flywheel.core.model.ModelTransformer;
|
import com.jozufozu.flywheel.core.model.ModelTransformer;
|
||||||
import com.jozufozu.flywheel.util.Color;
|
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||||
|
|
||||||
|
@ -22,7 +21,6 @@ public class CPUInstancer<D extends InstanceData> extends AbstractInstancer<D> {
|
||||||
batchingType = type;
|
batchingType = type;
|
||||||
|
|
||||||
sbb = new ModelTransformer(modelData);
|
sbb = new ModelTransformer(modelData);
|
||||||
modelData.configure(sbb.context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void submitTasks(PoseStack stack, TaskEngine pool, DirectVertexConsumer consumer) {
|
void submitTasks(PoseStack stack, TaskEngine pool, DirectVertexConsumer consumer) {
|
||||||
|
@ -44,15 +42,11 @@ public class CPUInstancer<D extends InstanceData> extends AbstractInstancer<D> {
|
||||||
private void drawRange(PoseStack stack, VertexConsumer buffer, int from, int to) {
|
private void drawRange(PoseStack stack, VertexConsumer buffer, int from, int to) {
|
||||||
ModelTransformer.Params params = new ModelTransformer.Params();
|
ModelTransformer.Params params = new ModelTransformer.Params();
|
||||||
|
|
||||||
// Color color = Color.generateFromLong(from);
|
|
||||||
|
|
||||||
for (D d : data.subList(from, to)) {
|
for (D d : data.subList(from, to)) {
|
||||||
params.loadDefault();
|
params.loadDefault();
|
||||||
|
|
||||||
batchingType.transform(d, params);
|
batchingType.transform(d, params);
|
||||||
|
|
||||||
//params.color(color.getRGB());
|
|
||||||
|
|
||||||
sbb.renderInto(params, stack, buffer);
|
sbb.renderInto(params, stack, buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,11 +67,6 @@ public class CPUInstancer<D extends InstanceData> extends AbstractInstancer<D> {
|
||||||
data.removeIf(InstanceData::isRemoved);
|
data.removeIf(InstanceData::isRemoved);
|
||||||
anyToRemove = false;
|
anyToRemove = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (false) {
|
|
||||||
this.sbb.context.outputColorDiffuse = false;
|
|
||||||
this.sbb.context.fullNormalTransform = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -8,13 +8,13 @@ import com.jozufozu.flywheel.api.struct.Instanced;
|
||||||
import com.jozufozu.flywheel.api.struct.StructWriter;
|
import com.jozufozu.flywheel.api.struct.StructWriter;
|
||||||
import com.jozufozu.flywheel.backend.Backend;
|
import com.jozufozu.flywheel.backend.Backend;
|
||||||
import com.jozufozu.flywheel.backend.gl.GlVertexArray;
|
import com.jozufozu.flywheel.backend.gl.GlVertexArray;
|
||||||
import com.jozufozu.flywheel.core.layout.BufferLayout;
|
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer;
|
import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer;
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
|
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer;
|
import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer;
|
||||||
import com.jozufozu.flywheel.backend.instancing.AbstractInstancer;
|
import com.jozufozu.flywheel.backend.instancing.AbstractInstancer;
|
||||||
import com.jozufozu.flywheel.backend.model.BufferedModel;
|
import com.jozufozu.flywheel.backend.model.BufferedModel;
|
||||||
import com.jozufozu.flywheel.backend.model.ModelAllocator;
|
import com.jozufozu.flywheel.backend.model.ModelAllocator;
|
||||||
|
import com.jozufozu.flywheel.core.layout.BufferLayout;
|
||||||
import com.jozufozu.flywheel.core.model.Model;
|
import com.jozufozu.flywheel.core.model.Model;
|
||||||
|
|
||||||
public class GPUInstancer<D extends InstanceData> extends AbstractInstancer<D> {
|
public class GPUInstancer<D extends InstanceData> extends AbstractInstancer<D> {
|
||||||
|
@ -73,14 +73,14 @@ public class GPUInstancer<D extends InstanceData> extends AbstractInstancer<D> {
|
||||||
model = modelAllocator.alloc(modelData, arenaModel -> {
|
model = modelAllocator.alloc(modelData, arenaModel -> {
|
||||||
vao.bind();
|
vao.bind();
|
||||||
|
|
||||||
arenaModel.setupState();
|
arenaModel.setupState(vao);
|
||||||
});
|
});
|
||||||
|
|
||||||
vao.bind();
|
vao.bind();
|
||||||
|
vao.enableArrays(model.getAttributeCount() + instanceFormat.getAttributeCount());
|
||||||
|
|
||||||
instanceVBO = GlBuffer.requestPersistent(GlBufferType.ARRAY_BUFFER);
|
instanceVBO = GlBuffer.requestPersistent(GlBufferType.ARRAY_BUFFER);
|
||||||
instanceVBO.setGrowthMargin(instanceFormat.getStride() * 16);
|
instanceVBO.setGrowthMargin(instanceFormat.getStride() * 16);
|
||||||
vao.enableArrays(model.getAttributeCount() + instanceFormat.getAttributeCount());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isInitialized() {
|
public boolean isInitialized() {
|
||||||
|
@ -137,7 +137,7 @@ public class GPUInstancer<D extends InstanceData> extends AbstractInstancer<D> {
|
||||||
try (MappedBuffer buf = instanceVBO.getBuffer(offset, length)) {
|
try (MappedBuffer buf = instanceVBO.getBuffer(offset, length)) {
|
||||||
MemoryUtil.memSet(MemoryUtil.memAddress(buf.unwrap()), 0, length);
|
MemoryUtil.memSet(MemoryUtil.memAddress(buf.unwrap()), 0, length);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Flywheel.log.error("Error clearing buffer tail:", e);
|
Flywheel.LOGGER.error("Error clearing buffer tail:", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -159,7 +159,7 @@ public class GPUInstancer<D extends InstanceData> extends AbstractInstancer<D> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Flywheel.log.error("Error updating GPUInstancer:", e);
|
Flywheel.LOGGER.error("Error updating GPUInstancer:", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,24 +175,24 @@ public class GPUInstancer<D extends InstanceData> extends AbstractInstancer<D> {
|
||||||
writer.write(datum);
|
writer.write(datum);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Flywheel.log.error("Error reallocating GPUInstancer:", e);
|
Flywheel.LOGGER.error("Error reallocating GPUInstancer:", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
glInstanceCount = size;
|
glInstanceCount = size;
|
||||||
|
|
||||||
informAttribDivisors();
|
bindInstanceAttributes();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void informAttribDivisors() {
|
private void bindInstanceAttributes() {
|
||||||
int staticAttributes = model.getAttributeCount();
|
int attributeBaseIndex = model.getAttributeCount();
|
||||||
instanceFormat.vertexAttribPointers(staticAttributes);
|
vao.bindAttributes(attributeBaseIndex, instanceFormat);
|
||||||
|
|
||||||
for (int i = 0; i < instanceFormat.getAttributeCount(); i++) {
|
for (int i = 0; i < instanceFormat.getAttributeCount(); i++) {
|
||||||
Backend.getInstance().compat.instancedArrays.vertexAttribDivisor(i + staticAttributes, 1);
|
Backend.getInstance().compat.instancedArrays.vertexAttribDivisor(attributeBaseIndex + i, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,48 +1,54 @@
|
||||||
package com.jozufozu.flywheel.backend.model;
|
package com.jozufozu.flywheel.backend.model;
|
||||||
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.gl.GlVertexArray;
|
import com.jozufozu.flywheel.backend.gl.GlVertexArray;
|
||||||
import com.jozufozu.flywheel.core.model.Model;
|
import com.jozufozu.flywheel.core.model.Model;
|
||||||
import com.jozufozu.flywheel.util.AttribUtil;
|
|
||||||
|
|
||||||
public class ArrayModelRenderer extends ModelRenderer {
|
public class ArrayModelRenderer {
|
||||||
|
|
||||||
|
private final Model model;
|
||||||
protected GlVertexArray vao;
|
protected GlVertexArray vao;
|
||||||
|
protected BufferedModel vbo;
|
||||||
|
protected boolean initialized;
|
||||||
|
|
||||||
public ArrayModelRenderer(Supplier<Model> model) {
|
public ArrayModelRenderer(Model model) {
|
||||||
super(model);
|
this.model = model;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
|
* Renders this model, checking first if there is anything to render.
|
||||||
|
*/
|
||||||
public void draw() {
|
public void draw() {
|
||||||
if (!initialized) init();
|
if (!initialized) init();
|
||||||
if (!isValid()) return;
|
if (!isValid()) return;
|
||||||
|
|
||||||
vao.bind();
|
vao.bind();
|
||||||
|
|
||||||
model.drawCall();
|
vbo.drawCall();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void init() {
|
protected void init() {
|
||||||
initialized = true;
|
initialized = true;
|
||||||
Model model = modelSupplier.get();
|
|
||||||
|
|
||||||
if (model.empty()) return;
|
if (model.empty()) return;
|
||||||
|
|
||||||
this.model = new IndexedModel(model);
|
this.vbo = new IndexedModel(model);
|
||||||
|
|
||||||
vao = new GlVertexArray();
|
vao = new GlVertexArray();
|
||||||
|
|
||||||
vao.bind();
|
vao.bind();
|
||||||
vao.enableArrays(this.model.getAttributeCount());
|
|
||||||
|
|
||||||
// bind the model's vbo to our vao
|
// bind the model's vbo to our vao
|
||||||
this.model.setupState();
|
this.vbo.setupState(vao);
|
||||||
|
|
||||||
GlVertexArray.unbind();
|
GlVertexArray.unbind();
|
||||||
|
}
|
||||||
|
|
||||||
this.model.clearState();
|
public void delete() {
|
||||||
|
if (vbo != null)
|
||||||
|
vbo.delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean isValid() {
|
||||||
|
return vbo != null && vbo.valid();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
package com.jozufozu.flywheel.backend.model;
|
package com.jozufozu.flywheel.backend.model;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.core.layout.BufferLayout;
|
|
||||||
import com.jozufozu.flywheel.api.vertex.VertexType;
|
import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||||
|
import com.jozufozu.flywheel.backend.gl.GlVertexArray;
|
||||||
|
import com.jozufozu.flywheel.core.layout.BufferLayout;
|
||||||
|
|
||||||
public interface BufferedModel {
|
public interface BufferedModel {
|
||||||
|
|
||||||
|
@ -10,11 +11,9 @@ public interface BufferedModel {
|
||||||
int getVertexCount();
|
int getVertexCount();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The VBO/VAO should be bound externally.
|
* The VAO must be bound externally.
|
||||||
*/
|
*/
|
||||||
void setupState();
|
void setupState(GlVertexArray vao);
|
||||||
|
|
||||||
void clearState();
|
|
||||||
|
|
||||||
void drawCall();
|
void drawCall();
|
||||||
|
|
||||||
|
@ -27,7 +26,7 @@ public interface BufferedModel {
|
||||||
|
|
||||||
void delete();
|
void delete();
|
||||||
|
|
||||||
default BufferLayout getFormat() {
|
default BufferLayout getLayout() {
|
||||||
return getType().getLayout();
|
return getType().getLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,6 +35,6 @@ public interface BufferedModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
default int getAttributeCount() {
|
default int getAttributeCount() {
|
||||||
return getFormat().getAttributeCount();
|
return getType().getLayout().getAttributeCount();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,14 @@ package com.jozufozu.flywheel.backend.model;
|
||||||
import org.lwjgl.opengl.GL20;
|
import org.lwjgl.opengl.GL20;
|
||||||
import org.lwjgl.opengl.GL31;
|
import org.lwjgl.opengl.GL31;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.Flywheel;
|
||||||
|
import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||||
import com.jozufozu.flywheel.backend.gl.GlPrimitive;
|
import com.jozufozu.flywheel.backend.gl.GlPrimitive;
|
||||||
|
import com.jozufozu.flywheel.backend.gl.GlVertexArray;
|
||||||
|
import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer;
|
||||||
|
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
|
||||||
|
import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer;
|
||||||
|
import com.jozufozu.flywheel.backend.gl.buffer.MappedGlBuffer;
|
||||||
import com.jozufozu.flywheel.core.model.Model;
|
import com.jozufozu.flywheel.core.model.Model;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -11,26 +18,43 @@ import com.jozufozu.flywheel.core.model.Model;
|
||||||
*
|
*
|
||||||
* <br><em>This should be favored over a normal BufferedModel.</em>
|
* <br><em>This should be favored over a normal BufferedModel.</em>
|
||||||
*/
|
*/
|
||||||
public class IndexedModel extends VBOModel {
|
public class IndexedModel implements BufferedModel {
|
||||||
|
|
||||||
|
protected final Model model;
|
||||||
|
protected final GlPrimitive primitiveMode;
|
||||||
protected ElementBuffer ebo;
|
protected ElementBuffer ebo;
|
||||||
|
protected GlBuffer vbo;
|
||||||
|
protected boolean deleted;
|
||||||
|
|
||||||
public IndexedModel(Model model) {
|
public IndexedModel(Model model) {
|
||||||
super(GlPrimitive.TRIANGLES, model);
|
this.model = model;
|
||||||
|
this.primitiveMode = GlPrimitive.TRIANGLES;
|
||||||
|
|
||||||
|
vbo = new MappedGlBuffer(GlBufferType.ARRAY_BUFFER);
|
||||||
|
|
||||||
|
vbo.bind();
|
||||||
|
// allocate the buffer on the gpu
|
||||||
|
vbo.ensureCapacity(model.size());
|
||||||
|
|
||||||
|
// mirror it in system memory, so we can write to it, and upload our model.
|
||||||
|
try (MappedBuffer buffer = vbo.getBuffer()) {
|
||||||
|
model.writeInto(buffer.unwrap());
|
||||||
|
} catch (Exception e) {
|
||||||
|
Flywheel.LOGGER.error(String.format("Error uploading model '%s':", model.name()), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
vbo.unbind();
|
||||||
|
|
||||||
this.ebo = model.createEBO();
|
this.ebo = model.createEBO();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
public void setupState() {
|
* The VBO/VAO should be bound externally.
|
||||||
super.setupState();
|
*/
|
||||||
ebo.bind();
|
public void setupState(GlVertexArray vao) {
|
||||||
}
|
vbo.bind();
|
||||||
|
vao.enableArrays(getAttributeCount());
|
||||||
@Override
|
vao.bindAttributes(0, getType().getLayout());
|
||||||
public void clearState() {
|
|
||||||
super.clearState();
|
|
||||||
ebo.unbind();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -39,6 +63,9 @@ public class IndexedModel extends VBOModel {
|
||||||
GL20.glDrawElements(primitiveMode.glEnum, ebo.elementCount, ebo.eboIndexType.getGlEnum(), 0);
|
GL20.glDrawElements(primitiveMode.glEnum, ebo.elementCount, ebo.eboIndexType.getGlEnum(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draws many instances of this model, assuming the appropriate state is already bound.
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void drawInstances(int instanceCount) {
|
public void drawInstances(int instanceCount) {
|
||||||
if (!valid()) return;
|
if (!valid()) return;
|
||||||
|
@ -47,4 +74,24 @@ public class IndexedModel extends VBOModel {
|
||||||
|
|
||||||
GL31.glDrawElementsInstanced(primitiveMode.glEnum, ebo.elementCount, ebo.eboIndexType.getGlEnum(), 0, instanceCount);
|
GL31.glDrawElementsInstanced(primitiveMode.glEnum, ebo.elementCount, ebo.eboIndexType.getGlEnum(), 0, instanceCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isDeleted() {
|
||||||
|
return deleted;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public VertexType getType() {
|
||||||
|
return model.getType();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getVertexCount() {
|
||||||
|
return model.vertexCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void delete() {
|
||||||
|
if (deleted) return;
|
||||||
|
|
||||||
|
deleted = true;
|
||||||
|
vbo.delete();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,15 +6,15 @@ import java.util.List;
|
||||||
import org.lwjgl.opengl.GL32;
|
import org.lwjgl.opengl.GL32;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.Flywheel;
|
import com.jozufozu.flywheel.Flywheel;
|
||||||
|
import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||||
|
import com.jozufozu.flywheel.api.vertex.VertexWriter;
|
||||||
import com.jozufozu.flywheel.backend.gl.GlPrimitive;
|
import com.jozufozu.flywheel.backend.gl.GlPrimitive;
|
||||||
|
import com.jozufozu.flywheel.backend.gl.GlVertexArray;
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer;
|
import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer;
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
|
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer;
|
import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer;
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.MappedGlBuffer;
|
import com.jozufozu.flywheel.backend.gl.buffer.MappedGlBuffer;
|
||||||
import com.jozufozu.flywheel.core.model.Model;
|
import com.jozufozu.flywheel.core.model.Model;
|
||||||
import com.jozufozu.flywheel.api.vertex.VertexType;
|
|
||||||
import com.jozufozu.flywheel.api.vertex.VertexWriter;
|
|
||||||
import com.jozufozu.flywheel.util.AttribUtil;
|
|
||||||
|
|
||||||
public class ModelPool implements ModelAllocator {
|
public class ModelPool implements ModelAllocator {
|
||||||
|
|
||||||
|
@ -121,7 +121,7 @@ public class ModelPool implements ModelAllocator {
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Flywheel.log.error("Error uploading pooled models:", e);
|
Flywheel.LOGGER.error("Error uploading pooled models:", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,7 +133,7 @@ public class ModelPool implements ModelAllocator {
|
||||||
}
|
}
|
||||||
pendingUpload.clear();
|
pendingUpload.clear();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Flywheel.log.error("Error uploading pooled models:", e);
|
Flywheel.LOGGER.error("Error uploading pooled models:", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,18 +178,10 @@ public class ModelPool implements ModelAllocator {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setupState() {
|
public void setupState(GlVertexArray vao) {
|
||||||
vbo.bind();
|
vbo.bind();
|
||||||
ebo.bind();
|
vao.enableArrays(getAttributeCount());
|
||||||
AttribUtil.enableArrays(getAttributeCount());
|
vao.bindAttributes(0, vertexType.getLayout());
|
||||||
ModelPool.this.vertexType.getLayout().vertexAttribPointers(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void clearState() {
|
|
||||||
AttribUtil.disableArrays(getAttributeCount());
|
|
||||||
ebo.unbind();
|
|
||||||
vbo.unbind();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,47 +0,0 @@
|
||||||
package com.jozufozu.flywheel.backend.model;
|
|
||||||
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
|
|
||||||
import com.jozufozu.flywheel.core.model.Model;
|
|
||||||
|
|
||||||
public class ModelRenderer {
|
|
||||||
|
|
||||||
protected Supplier<Model> modelSupplier;
|
|
||||||
protected BufferedModel model;
|
|
||||||
|
|
||||||
protected boolean initialized;
|
|
||||||
|
|
||||||
public ModelRenderer(Supplier<Model> modelSupplier) {
|
|
||||||
this.modelSupplier = modelSupplier;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Renders this model, checking first if there is anything to render.
|
|
||||||
*/
|
|
||||||
public void draw() {
|
|
||||||
if (!initialized) init();
|
|
||||||
if (!isValid()) return;
|
|
||||||
|
|
||||||
model.setupState();
|
|
||||||
model.drawCall();
|
|
||||||
model.clearState();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void delete() {
|
|
||||||
if (model != null)
|
|
||||||
model.delete();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void init() {
|
|
||||||
initialized = true;
|
|
||||||
Model model = modelSupplier.get();
|
|
||||||
|
|
||||||
if (model.empty()) return;
|
|
||||||
|
|
||||||
this.model = new IndexedModel(model);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean isValid() {
|
|
||||||
return model != null && model.valid();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -5,14 +5,14 @@ import static org.lwjgl.opengl.GL11.glDrawArrays;
|
||||||
import org.lwjgl.opengl.GL31;
|
import org.lwjgl.opengl.GL31;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.Flywheel;
|
import com.jozufozu.flywheel.Flywheel;
|
||||||
|
import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||||
import com.jozufozu.flywheel.backend.gl.GlPrimitive;
|
import com.jozufozu.flywheel.backend.gl.GlPrimitive;
|
||||||
|
import com.jozufozu.flywheel.backend.gl.GlVertexArray;
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer;
|
import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer;
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
|
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer;
|
import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer;
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.MappedGlBuffer;
|
import com.jozufozu.flywheel.backend.gl.buffer.MappedGlBuffer;
|
||||||
import com.jozufozu.flywheel.core.model.Model;
|
import com.jozufozu.flywheel.core.model.Model;
|
||||||
import com.jozufozu.flywheel.api.vertex.VertexType;
|
|
||||||
import com.jozufozu.flywheel.util.AttribUtil;
|
|
||||||
|
|
||||||
public class VBOModel implements BufferedModel {
|
public class VBOModel implements BufferedModel {
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ public class VBOModel implements BufferedModel {
|
||||||
try (MappedBuffer buffer = vbo.getBuffer()) {
|
try (MappedBuffer buffer = vbo.getBuffer()) {
|
||||||
model.writeInto(buffer.unwrap());
|
model.writeInto(buffer.unwrap());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Flywheel.log.error(String.format("Error uploading model '%s':", model.name()), e);
|
Flywheel.LOGGER.error(String.format("Error uploading model '%s':", model.name()), e);
|
||||||
}
|
}
|
||||||
|
|
||||||
vbo.unbind();
|
vbo.unbind();
|
||||||
|
@ -57,15 +57,10 @@ public class VBOModel implements BufferedModel {
|
||||||
/**
|
/**
|
||||||
* The VBO/VAO should be bound externally.
|
* The VBO/VAO should be bound externally.
|
||||||
*/
|
*/
|
||||||
public void setupState() {
|
public void setupState(GlVertexArray vao) {
|
||||||
vbo.bind();
|
vbo.bind();
|
||||||
AttribUtil.enableArrays(getAttributeCount());
|
vao.enableArrays(getAttributeCount());
|
||||||
getFormat().vertexAttribPointers(0);
|
vao.bindAttributes(0, getLayout());
|
||||||
}
|
|
||||||
|
|
||||||
public void clearState() {
|
|
||||||
AttribUtil.disableArrays(getAttributeCount());
|
|
||||||
vbo.unbind();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void drawCall() {
|
public void drawCall() {
|
||||||
|
|
|
@ -37,7 +37,7 @@ public class Contexts {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Names {
|
public static class Names {
|
||||||
public static final ResourceLocation CRUMBLING = new ResourceLocation(Flywheel.ID, "context/crumbling");
|
public static final ResourceLocation CRUMBLING = Flywheel.rl("context/crumbling");
|
||||||
public static final ResourceLocation WORLD = new ResourceLocation(Flywheel.ID, "context/world");
|
public static final ResourceLocation WORLD = Flywheel.rl("context/world");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ public class FullscreenQuad {
|
||||||
try (MappedBuffer buffer = vbo.getBuffer()) {
|
try (MappedBuffer buffer = vbo.getBuffer()) {
|
||||||
buffer.putFloatArray(vertices);
|
buffer.putFloatArray(vertices);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Flywheel.log.error("Could not create fullscreen quad.", e);
|
Flywheel.LOGGER.error("Could not create fullscreen quad.", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
vao = new GlVertexArray();
|
vao = new GlVertexArray();
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package com.jozufozu.flywheel.core;
|
package com.jozufozu.flywheel.core;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.Flywheel;
|
||||||
import com.jozufozu.flywheel.api.struct.StructType;
|
import com.jozufozu.flywheel.api.struct.StructType;
|
||||||
import com.jozufozu.flywheel.backend.Backend;
|
import com.jozufozu.flywheel.backend.Backend;
|
||||||
import com.jozufozu.flywheel.core.materials.model.ModelData;
|
import com.jozufozu.flywheel.core.materials.model.ModelData;
|
||||||
|
@ -22,7 +23,7 @@ public class Materials {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Names {
|
public static class Names {
|
||||||
public static final ResourceLocation MODEL = new ResourceLocation("create", "model");
|
public static final ResourceLocation MODEL = Flywheel.rl("model");
|
||||||
public static final ResourceLocation ORIENTED = new ResourceLocation("create", "oriented");
|
public static final ResourceLocation ORIENTED = Flywheel.rl("oriented");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,6 @@ import com.jozufozu.flywheel.Flywheel;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
|
||||||
public class Programs {
|
public class Programs {
|
||||||
public static final ResourceLocation TRANSFORMED = new ResourceLocation(Flywheel.ID, "model");
|
public static final ResourceLocation TRANSFORMED = Flywheel.rl("model");
|
||||||
public static final ResourceLocation ORIENTED = new ResourceLocation(Flywheel.ID, "oriented");
|
public static final ResourceLocation ORIENTED = Flywheel.rl("oriented");
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||||
* Classic Vertex Format struct with a clever name.
|
* Classic Vertex Format struct with a clever name.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* Used for vertices and instance. Describes the layout of a datatype in a buffer object.
|
* Used for vertices and instances. Describes the layout of a datatype in a buffer object.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @see com.jozufozu.flywheel.api.struct.StructType
|
* @see com.jozufozu.flywheel.api.struct.StructType
|
||||||
|
@ -34,6 +34,10 @@ public class BufferLayout {
|
||||||
this.stride = stride;
|
this.stride = stride;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<LayoutItem> getLayoutItems() {
|
||||||
|
return allAttributes;
|
||||||
|
}
|
||||||
|
|
||||||
public int getAttributeCount() {
|
public int getAttributeCount() {
|
||||||
return numAttributes;
|
return numAttributes;
|
||||||
}
|
}
|
||||||
|
@ -42,15 +46,6 @@ public class BufferLayout {
|
||||||
return stride;
|
return stride;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void vertexAttribPointers(int index) {
|
|
||||||
int offset = 0;
|
|
||||||
for (LayoutItem spec : this.allAttributes) {
|
|
||||||
spec.vertexAttribPointer(stride, index, offset);
|
|
||||||
index += spec.getAttributeCount();
|
|
||||||
offset += spec.getSize();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Builder builder() {
|
public static Builder builder() {
|
||||||
return new Builder();
|
return new Builder();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package com.jozufozu.flywheel.core.model;
|
package com.jozufozu.flywheel.core.model;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.core.Formats;
|
|
||||||
import com.jozufozu.flywheel.api.vertex.VertexList;
|
import com.jozufozu.flywheel.api.vertex.VertexList;
|
||||||
|
import com.jozufozu.flywheel.core.Formats;
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
|
@ -33,11 +33,6 @@ public class BlockModel implements Model {
|
||||||
name = referenceState.toString();
|
name = referenceState.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void configure(ModelTransformer.Context ctx) {
|
|
||||||
ctx.inputHasDiffuse = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String name() {
|
public String name() {
|
||||||
return name;
|
return name;
|
||||||
|
|
|
@ -2,11 +2,11 @@ package com.jozufozu.flywheel.core.model;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.api.vertex.VertexList;
|
||||||
|
import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||||
import com.jozufozu.flywheel.backend.model.ElementBuffer;
|
import com.jozufozu.flywheel.backend.model.ElementBuffer;
|
||||||
import com.jozufozu.flywheel.core.Formats;
|
import com.jozufozu.flywheel.core.Formats;
|
||||||
import com.jozufozu.flywheel.core.QuadConverter;
|
import com.jozufozu.flywheel.core.QuadConverter;
|
||||||
import com.jozufozu.flywheel.api.vertex.VertexList;
|
|
||||||
import com.jozufozu.flywheel.api.vertex.VertexType;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A model that can be rendered by flywheel.
|
* A model that can be rendered by flywheel.
|
||||||
|
@ -42,10 +42,6 @@ public interface Model {
|
||||||
*/
|
*/
|
||||||
int vertexCount();
|
int vertexCount();
|
||||||
|
|
||||||
default void configure(ModelTransformer.Context ctx) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
default VertexType getType() {
|
default VertexType getType() {
|
||||||
return Formats.POS_TEX_NORMAL;
|
return Formats.POS_TEX_NORMAL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,11 @@ import com.jozufozu.flywheel.util.RenderMath;
|
||||||
import com.jozufozu.flywheel.util.transform.Transform;
|
import com.jozufozu.flywheel.util.transform.Transform;
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||||
import com.mojang.math.*;
|
import com.mojang.math.Matrix3f;
|
||||||
|
import com.mojang.math.Matrix4f;
|
||||||
|
import com.mojang.math.Quaternion;
|
||||||
|
import com.mojang.math.Vector3f;
|
||||||
|
import com.mojang.math.Vector4f;
|
||||||
|
|
||||||
import net.minecraft.client.renderer.LightTexture;
|
import net.minecraft.client.renderer.LightTexture;
|
||||||
import net.minecraft.client.renderer.texture.OverlayTexture;
|
import net.minecraft.client.renderer.texture.OverlayTexture;
|
||||||
|
@ -74,34 +78,11 @@ public class ModelTransformer {
|
||||||
builder.color(params.r, params.g, params.b, params.a);
|
builder.color(params.r, params.g, params.b, params.a);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (context.inputHasDiffuse) {
|
if (context.outputColorDiffuse) {
|
||||||
int r = Byte.toUnsignedInt(reader.getR(i));
|
int d = RenderMath.unb(RenderMath.diffuseLight(nx, ny, nz));
|
||||||
int g = Byte.toUnsignedInt(reader.getG(i));
|
builder.color(d, d, d, 0xFF);
|
||||||
int b = Byte.toUnsignedInt(reader.getB(i));
|
|
||||||
int a = Byte.toUnsignedInt(reader.getA(i));
|
|
||||||
|
|
||||||
float undoStaticDiffuse = 1 / RenderMath.diffuseLight(normalX, normalY, normalZ);
|
|
||||||
float diffuse;
|
|
||||||
if (context.outputColorDiffuse) {
|
|
||||||
diffuse = RenderMath.diffuseLight(nx, ny, nz) * undoStaticDiffuse;
|
|
||||||
} else {
|
|
||||||
diffuse = undoStaticDiffuse;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (diffuse != 1) {
|
|
||||||
r = transformColor(r, diffuse);
|
|
||||||
g = transformColor(g, diffuse);
|
|
||||||
b = transformColor(b, diffuse);
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.color(r, g, b, a);
|
|
||||||
} else {
|
} else {
|
||||||
if (context.outputColorDiffuse) {
|
builder.color(reader.getR(i), reader.getG(i), reader.getB(i), reader.getA(i));
|
||||||
int d = RenderMath.unb(RenderMath.diffuseLight(nx, ny, nz));
|
|
||||||
builder.color(d, d, d, 0xFF);
|
|
||||||
} else {
|
|
||||||
builder.color(reader.getR(i), reader.getG(i), reader.getB(i), reader.getA(i));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,11 +132,6 @@ public class ModelTransformer {
|
||||||
*/
|
*/
|
||||||
public boolean fullNormalTransform = false;
|
public boolean fullNormalTransform = false;
|
||||||
|
|
||||||
/**
|
|
||||||
* Does the model we're transforming have diffuse light baked into its colors?
|
|
||||||
*/
|
|
||||||
public boolean inputHasDiffuse = false;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Do we need to bake diffuse lighting into the output colors?
|
* Do we need to bake diffuse lighting into the output colors?
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -5,11 +5,11 @@ import java.util.Collection;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.core.virtual.VirtualEmptyBlockGetter;
|
||||||
import com.jozufozu.flywheel.fabric.model.CullingBakedModel;
|
import com.jozufozu.flywheel.fabric.model.CullingBakedModel;
|
||||||
import com.jozufozu.flywheel.fabric.model.DefaultLayerFilteringBakedModel;
|
import com.jozufozu.flywheel.fabric.model.DefaultLayerFilteringBakedModel;
|
||||||
import com.jozufozu.flywheel.fabric.model.LayerFilteringBakedModel;
|
import com.jozufozu.flywheel.fabric.model.LayerFilteringBakedModel;
|
||||||
import com.jozufozu.flywheel.util.Lazy;
|
import com.jozufozu.flywheel.util.Lazy;
|
||||||
import com.jozufozu.flywheel.util.VirtualEmptyBlockGetter;
|
|
||||||
import com.jozufozu.flywheel.util.transform.TransformStack;
|
import com.jozufozu.flywheel.util.transform.TransformStack;
|
||||||
import com.mojang.blaze3d.vertex.BufferBuilder;
|
import com.mojang.blaze3d.vertex.BufferBuilder;
|
||||||
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
|
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
|
||||||
|
@ -44,14 +44,6 @@ public class ModelUtil {
|
||||||
public static BufferBuilder getBufferBuilder(BakedModel model, BlockState referenceState, PoseStack ms) {
|
public static BufferBuilder getBufferBuilder(BakedModel model, BlockState referenceState, PoseStack ms) {
|
||||||
ModelBlockRenderer blockRenderer = Minecraft.getInstance().getBlockRenderer().getModelRenderer();
|
ModelBlockRenderer blockRenderer = Minecraft.getInstance().getBlockRenderer().getModelRenderer();
|
||||||
BufferBuilder builder = new BufferBuilder(512);
|
BufferBuilder builder = new BufferBuilder(512);
|
||||||
|
|
||||||
// BakedQuadWrapper quadReader = new BakedQuadWrapper();
|
|
||||||
//
|
|
||||||
// IModelData modelData = model.getModelData(VirtualEmptyBlockGetter.INSTANCE, BlockPos.ZERO, referenceState, VirtualEmptyModelData.INSTANCE);
|
|
||||||
// List<BakedQuad> quads = Arrays.stream(CULL_FACES)
|
|
||||||
// .flatMap(dir -> model.getQuads(referenceState, dir, new Random(), modelData).stream())
|
|
||||||
// .collect(Collectors.toList());
|
|
||||||
|
|
||||||
builder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
|
builder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
|
||||||
model = DefaultLayerFilteringBakedModel.wrap(model);
|
model = DefaultLayerFilteringBakedModel.wrap(model);
|
||||||
blockRenderer.tesselateBlock(VirtualEmptyBlockGetter.INSTANCE, model, referenceState, BlockPos.ZERO, ms, builder,
|
blockRenderer.tesselateBlock(VirtualEmptyBlockGetter.INSTANCE, model, referenceState, BlockPos.ZERO, ms, builder,
|
||||||
|
|
|
@ -2,9 +2,9 @@ package com.jozufozu.flywheel.core.model;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.core.Formats;
|
|
||||||
import com.jozufozu.flywheel.api.vertex.VertexList;
|
import com.jozufozu.flywheel.api.vertex.VertexList;
|
||||||
import com.jozufozu.flywheel.api.vertex.VertexType;
|
import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||||
|
import com.jozufozu.flywheel.core.Formats;
|
||||||
|
|
||||||
import net.minecraft.client.renderer.RenderType;
|
import net.minecraft.client.renderer.RenderType;
|
||||||
import net.minecraft.world.level.BlockAndTintGetter;
|
import net.minecraft.world.level.BlockAndTintGetter;
|
||||||
|
@ -15,6 +15,9 @@ public class WorldModel implements Model {
|
||||||
private final VertexList reader;
|
private final VertexList reader;
|
||||||
private final String name;
|
private final String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* It is expected that <code>renderWorld.getShade(...)</code> returns a constant.
|
||||||
|
*/
|
||||||
public WorldModel(BlockAndTintGetter renderWorld, RenderType layer, Collection<StructureTemplate.StructureBlockInfo> blocks, String name) {
|
public WorldModel(BlockAndTintGetter renderWorld, RenderType layer, Collection<StructureTemplate.StructureBlockInfo> blocks, String name) {
|
||||||
reader = Formats.BLOCK.createReader(ModelUtil.getBufferBuilderFromTemplate(renderWorld, layer, blocks));
|
reader = Formats.BLOCK.createReader(ModelUtil.getBufferBuilderFromTemplate(renderWorld, layer, blocks));
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
|
|
@ -7,7 +7,7 @@ import net.minecraft.resources.ResourceLocation;
|
||||||
|
|
||||||
public class UnitExtensionInstance implements IExtensionInstance {
|
public class UnitExtensionInstance implements IExtensionInstance {
|
||||||
|
|
||||||
public static final ResourceLocation NAME = new ResourceLocation(Flywheel.ID, "unit");
|
public static final ResourceLocation NAME = Flywheel.rl("unit");
|
||||||
|
|
||||||
public UnitExtensionInstance(GlProgram program) {
|
public UnitExtensionInstance(GlProgram program) {
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ import net.minecraft.resources.ResourceLocation;
|
||||||
|
|
||||||
public class WorldFog implements IExtensionInstance {
|
public class WorldFog implements IExtensionInstance {
|
||||||
|
|
||||||
public static final ResourceLocation NAME = new ResourceLocation(Flywheel.ID, "fog");
|
public static final ResourceLocation NAME = Flywheel.rl("fog");
|
||||||
|
|
||||||
private final int uFogColor;
|
private final int uFogColor;
|
||||||
private final int uFogRange;
|
private final int uFogRange;
|
||||||
|
@ -28,6 +28,6 @@ public class WorldFog implements IExtensionInstance {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ResourceLocation name() {
|
public ResourceLocation name() {
|
||||||
return NAME;
|
return NAME;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ import net.minecraft.resources.ResourceLocation;
|
||||||
public class NormalDebugStateProvider implements IBooleanStateProvider {
|
public class NormalDebugStateProvider implements IBooleanStateProvider {
|
||||||
|
|
||||||
public static final NormalDebugStateProvider INSTANCE = new NormalDebugStateProvider();
|
public static final NormalDebugStateProvider INSTANCE = new NormalDebugStateProvider();
|
||||||
public static final ResourceLocation NAME = new ResourceLocation(Flywheel.ID, "normal_debug");
|
public static final ResourceLocation NAME = Flywheel.rl("normal_debug");
|
||||||
|
|
||||||
protected NormalDebugStateProvider() {
|
protected NormalDebugStateProvider() {
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,7 @@ public class BlockWriterUnsafe extends VertexWriterUnsafe<BlockVertex> {
|
||||||
MemoryUtil.memPutByte(ptr + 15, a);
|
MemoryUtil.memPutByte(ptr + 15, a);
|
||||||
MemoryUtil.memPutFloat(ptr + 16, u);
|
MemoryUtil.memPutFloat(ptr + 16, u);
|
||||||
MemoryUtil.memPutFloat(ptr + 20, v);
|
MemoryUtil.memPutFloat(ptr + 20, v);
|
||||||
MemoryUtil.memPutInt(ptr + 24, light);
|
MemoryUtil.memPutInt(ptr + 24, light << 8); // light is packed in the low byte of each short
|
||||||
MemoryUtil.memPutByte(ptr + 28, RenderMath.nb(nX));
|
MemoryUtil.memPutByte(ptr + 28, RenderMath.nb(nX));
|
||||||
MemoryUtil.memPutByte(ptr + 29, RenderMath.nb(nY));
|
MemoryUtil.memPutByte(ptr + 29, RenderMath.nb(nY));
|
||||||
MemoryUtil.memPutByte(ptr + 30, RenderMath.nb(nZ));
|
MemoryUtil.memPutByte(ptr + 30, RenderMath.nb(nZ));
|
||||||
|
|
|
@ -24,6 +24,7 @@ public abstract class VertexWriterUnsafe<V extends VertexType> implements Vertex
|
||||||
|
|
||||||
protected void advance() {
|
protected void advance() {
|
||||||
writeVertex++;
|
writeVertex++;
|
||||||
|
// account for seeking
|
||||||
if (writeVertex > totalVertices) totalVertices = writeVertex;
|
if (writeVertex > totalVertices) totalVertices = writeVertex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,250 @@
|
||||||
|
package com.jozufozu.flywheel.core.virtual;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.util.Mods;
|
||||||
|
|
||||||
|
import ca.spottedleaf.starlight.common.chunk.ExtendedChunk;
|
||||||
|
import ca.spottedleaf.starlight.common.light.StarLightEngine;
|
||||||
|
import it.unimi.dsi.fastutil.longs.LongSet;
|
||||||
|
import it.unimi.dsi.fastutil.shorts.ShortList;
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.core.Registry;
|
||||||
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
import net.minecraft.world.entity.Entity;
|
||||||
|
import net.minecraft.world.level.ChunkPos;
|
||||||
|
import net.minecraft.world.level.block.Block;
|
||||||
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||||
|
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||||
|
import net.minecraft.world.level.chunk.LevelChunkSection;
|
||||||
|
import net.minecraft.world.level.chunk.UpgradeData;
|
||||||
|
import net.minecraft.world.level.levelgen.Heightmap;
|
||||||
|
import net.minecraft.world.level.levelgen.feature.StructureFeature;
|
||||||
|
import net.minecraft.world.level.levelgen.structure.StructureStart;
|
||||||
|
import net.minecraft.world.level.material.Fluid;
|
||||||
|
import net.minecraft.world.level.material.FluidState;
|
||||||
|
import net.minecraft.world.ticks.BlackholeTickAccess;
|
||||||
|
import net.minecraft.world.ticks.TickContainerAccess;
|
||||||
|
|
||||||
|
public class VirtualChunk extends ChunkAccess {
|
||||||
|
|
||||||
|
final VirtualRenderWorld world;
|
||||||
|
boolean needsLight;
|
||||||
|
final int x;
|
||||||
|
final int z;
|
||||||
|
|
||||||
|
private final LevelChunkSection[] sections;
|
||||||
|
|
||||||
|
public VirtualChunk(VirtualRenderWorld world, int x, int z) {
|
||||||
|
super(new ChunkPos(x, z), UpgradeData.EMPTY, world, world.registryAccess()
|
||||||
|
.registry(Registry.BIOME_REGISTRY)
|
||||||
|
.orElseThrow(), 0L, null, null);
|
||||||
|
|
||||||
|
this.world = world;
|
||||||
|
this.needsLight = true;
|
||||||
|
this.x = x;
|
||||||
|
this.z = z;
|
||||||
|
|
||||||
|
int sectionCount = world.getSectionsCount();
|
||||||
|
this.sections = new LevelChunkSection[sectionCount];
|
||||||
|
|
||||||
|
for (int i = 0; i < sectionCount; i++) {
|
||||||
|
sections[i] = new VirtualChunkSection(this, i << 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
Mods.STARLIGHT.executeIfInstalled(() -> () -> {
|
||||||
|
((ExtendedChunk)this).setBlockNibbles(StarLightEngine.getFilledEmptyLight(this));
|
||||||
|
((ExtendedChunk)this).setSkyNibbles(StarLightEngine.getFilledEmptyLight(this));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Stream<BlockPos> getLights() {
|
||||||
|
return world.blocksAdded.entrySet()
|
||||||
|
.stream()
|
||||||
|
.filter(it -> {
|
||||||
|
BlockPos blockPos = it.getKey();
|
||||||
|
boolean chunkContains = blockPos.getX() >> 4 == x && blockPos.getZ() >> 4 == z;
|
||||||
|
return chunkContains && it.getValue()
|
||||||
|
.getLightEmission() != 0;
|
||||||
|
})
|
||||||
|
.map(Map.Entry::getKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LevelChunkSection[] getSections() {
|
||||||
|
return sections;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChunkStatus getStatus() {
|
||||||
|
return ChunkStatus.LIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public BlockState setBlockState(BlockPos p_177436_1_, BlockState p_177436_2_, boolean p_177436_3_) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setBlockEntity(BlockEntity p_177426_2_) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addEntity(Entity p_76612_1_) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<BlockPos> getBlockEntitiesPos() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<Map.Entry<Heightmap.Types, Heightmap>> getHeightmaps() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setHeightmap(Heightmap.Types p_201607_1_, long[] p_201607_2_) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Heightmap getOrCreateHeightmapUnprimed(Heightmap.Types p_217303_1_) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getHeight(Heightmap.Types p_201576_1_, int p_201576_2_, int p_201576_3_) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setUnsaved(boolean p_177427_1_) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isUnsaved() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeBlockEntity(BlockPos p_177425_1_) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ShortList[] getPostProcessing() {
|
||||||
|
return new ShortList[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public CompoundTag getBlockEntityNbt(BlockPos p_201579_1_) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public CompoundTag getBlockEntityNbtForSaving(BlockPos p_223134_1_) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UpgradeData getUpgradeData() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setInhabitedTime(long p_177415_1_) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getInhabitedTime() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isLightCorrect() {
|
||||||
|
return needsLight;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setLightCorrect(boolean needsLight) {
|
||||||
|
this.needsLight = needsLight;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public BlockEntity getBlockEntity(BlockPos pos) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockState getBlockState(BlockPos pos) {
|
||||||
|
return world.getBlockState(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FluidState getFluidState(BlockPos p_204610_1_) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addReferenceForFeature(StructureFeature<?> arg0, long arg1) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<StructureFeature<?>, LongSet> getAllReferences() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LongSet getReferencesForFeature(StructureFeature<?> arg0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StructureStart<?> getStartForFeature(StructureFeature<?> arg0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAllReferences(Map<StructureFeature<?>, LongSet> arg0) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setStartForFeature(StructureFeature<?> arg0, StructureStart<?> arg1) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAllStarts(Map<StructureFeature<?>, StructureStart<?>> p_201612_1_) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<StructureFeature<?>, StructureStart<?>> getAllStarts() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getHeight() {
|
||||||
|
return world.getHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMinBuildHeight() {
|
||||||
|
return world.getMinBuildHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TickContainerAccess<Fluid> getFluidTicks() {
|
||||||
|
return BlackholeTickAccess.emptyContainer();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TicksToSave getTicksForSerialization() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TickContainerAccess<Block> getBlockTicks() {
|
||||||
|
return BlackholeTickAccess.emptyContainer();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
package com.jozufozu.flywheel.core.virtual;
|
||||||
|
|
||||||
|
import net.minecraft.core.Registry;
|
||||||
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
import net.minecraft.world.level.chunk.LevelChunkSection;
|
||||||
|
|
||||||
|
public class VirtualChunkSection extends LevelChunkSection {
|
||||||
|
|
||||||
|
public VirtualChunk owner;
|
||||||
|
|
||||||
|
public final int xStart;
|
||||||
|
public final int yStart;
|
||||||
|
public final int zStart;
|
||||||
|
|
||||||
|
public VirtualChunkSection(VirtualChunk owner, int yBase) {
|
||||||
|
super(yBase, owner.world.registryAccess()
|
||||||
|
.registry(Registry.BIOME_REGISTRY)
|
||||||
|
.orElseThrow());
|
||||||
|
this.owner = owner;
|
||||||
|
this.xStart = owner.getPos()
|
||||||
|
.getMinBlockX();
|
||||||
|
this.yStart = yBase;
|
||||||
|
this.zStart = owner.getPos()
|
||||||
|
.getMinBlockZ();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockState getBlockState(int x, int y, int z) {
|
||||||
|
// ChunkSection#getBlockState expects local chunk coordinates, so we add to get
|
||||||
|
// back into world coords.
|
||||||
|
return owner.world.getBlockState(x + xStart, y + yStart, z + zStart);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockState setBlockState(int p_177484_1_, int p_177484_2_, int p_177484_3_, BlockState p_177484_4_,
|
||||||
|
boolean p_177484_5_) {
|
||||||
|
throw new IllegalStateException("Chunk sections should not be mutated in a fake world.");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
package com.jozufozu.flywheel.core.virtual;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.function.BooleanSupplier;
|
||||||
|
|
||||||
|
import net.minecraft.world.level.BlockGetter;
|
||||||
|
import net.minecraft.world.level.ChunkPos;
|
||||||
|
import net.minecraft.world.level.Level;
|
||||||
|
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||||
|
import net.minecraft.world.level.chunk.ChunkSource;
|
||||||
|
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||||
|
import net.minecraft.world.level.lighting.LevelLightEngine;
|
||||||
|
|
||||||
|
public class VirtualChunkSource extends ChunkSource {
|
||||||
|
private final VirtualRenderWorld world;
|
||||||
|
|
||||||
|
public final HashMap<Long, VirtualChunk> chunks = new HashMap<>();
|
||||||
|
|
||||||
|
public VirtualChunkSource(VirtualRenderWorld world) {
|
||||||
|
this.world = world;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockGetter getChunkForLighting(int x, int z) {
|
||||||
|
return getChunk(x, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Level getLevel() {
|
||||||
|
return world;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChunkAccess getChunk(int x, int z, ChunkStatus status, boolean p_212849_4_) {
|
||||||
|
return getChunk(x, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ChunkAccess getChunk(int x, int z) {
|
||||||
|
long pos = ChunkPos.asLong(x, z);
|
||||||
|
|
||||||
|
return chunks.computeIfAbsent(pos, $ -> new VirtualChunk(world, x, z));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String gatherStats() {
|
||||||
|
return "WrappedChunkProvider";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LevelLightEngine getLightEngine() {
|
||||||
|
return world.getLightEngine();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tick(BooleanSupplier pHasTimeLeft) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getLoadedChunksCount() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package com.jozufozu.flywheel.util;
|
package com.jozufozu.flywheel.core.virtual;
|
||||||
|
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
|
@ -120,7 +120,7 @@ public enum VirtualEmptyBlockGetter implements BlockAndTintGetter {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float getShade(Direction direction, boolean bool) {
|
public float getShade(Direction direction, boolean bool) {
|
||||||
return Minecraft.getInstance().level.getShade(direction, bool);
|
return 1f;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
|
@ -0,0 +1,41 @@
|
||||||
|
package com.jozufozu.flywheel.core.virtual;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import net.minecraft.world.level.entity.EntityAccess;
|
||||||
|
import net.minecraft.world.level.entity.EntityTypeTest;
|
||||||
|
import net.minecraft.world.level.entity.LevelEntityGetter;
|
||||||
|
import net.minecraft.world.phys.AABB;
|
||||||
|
|
||||||
|
public class VirtualLevelEntityGetter<T extends EntityAccess> implements LevelEntityGetter<T> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T get(int p_156931_) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T get(UUID pUuid) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<T> getAll() {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <U extends T> void get(EntityTypeTest<T, U> p_156935_, Consumer<U> p_156936_) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void get(AABB p_156937_, Consumer<T> p_156938_) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <U extends T> void get(EntityTypeTest<T, U> p_156932_, AABB p_156933_, Consumer<U> p_156934_) {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,335 @@
|
||||||
|
package com.jozufozu.flywheel.core.virtual;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.api.FlywheelWorld;
|
||||||
|
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.core.Direction;
|
||||||
|
import net.minecraft.core.RegistryAccess;
|
||||||
|
import net.minecraft.core.SectionPos;
|
||||||
|
import net.minecraft.sounds.SoundEvent;
|
||||||
|
import net.minecraft.sounds.SoundSource;
|
||||||
|
import net.minecraft.tags.TagContainer;
|
||||||
|
import net.minecraft.world.entity.Entity;
|
||||||
|
import net.minecraft.world.entity.player.Player;
|
||||||
|
import net.minecraft.world.item.crafting.RecipeManager;
|
||||||
|
import net.minecraft.world.level.Level;
|
||||||
|
import net.minecraft.world.level.biome.Biome;
|
||||||
|
import net.minecraft.world.level.block.Block;
|
||||||
|
import net.minecraft.world.level.block.Blocks;
|
||||||
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||||
|
import net.minecraft.world.level.chunk.ChunkSource;
|
||||||
|
import net.minecraft.world.level.chunk.LevelChunk;
|
||||||
|
import net.minecraft.world.level.entity.LevelEntityGetter;
|
||||||
|
import net.minecraft.world.level.gameevent.GameEvent;
|
||||||
|
import net.minecraft.world.level.lighting.LevelLightEngine;
|
||||||
|
import net.minecraft.world.level.material.Fluid;
|
||||||
|
import net.minecraft.world.level.saveddata.maps.MapItemSavedData;
|
||||||
|
import net.minecraft.world.level.storage.WritableLevelData;
|
||||||
|
import net.minecraft.world.scores.Scoreboard;
|
||||||
|
import net.minecraft.world.ticks.LevelTickAccess;
|
||||||
|
|
||||||
|
public class VirtualRenderWorld extends Level implements FlywheelWorld {
|
||||||
|
public final Map<BlockPos, BlockState> blocksAdded = new HashMap<>();
|
||||||
|
public final Map<BlockPos, BlockEntity> tesAdded = new HashMap<>();
|
||||||
|
public final Set<SectionPos> spannedSections = new HashSet<>();
|
||||||
|
private final BlockPos.MutableBlockPos scratch = new BlockPos.MutableBlockPos();
|
||||||
|
|
||||||
|
protected final Level level;
|
||||||
|
protected final LevelLightEngine lighter;
|
||||||
|
protected final VirtualChunkSource chunkSource;
|
||||||
|
protected final LevelEntityGetter<Entity> entityGetter = new VirtualLevelEntityGetter<>();
|
||||||
|
|
||||||
|
protected final int height;
|
||||||
|
protected final int minBuildHeight;
|
||||||
|
|
||||||
|
public VirtualRenderWorld(Level level) {
|
||||||
|
this(level, level.getHeight(), level.getMinBuildHeight());
|
||||||
|
}
|
||||||
|
|
||||||
|
public VirtualRenderWorld(Level level, int height, int minBuildHeight) {
|
||||||
|
super((WritableLevelData) level.getLevelData(), level.dimension(), level.dimensionType(), level::getProfiler,
|
||||||
|
true, false, 0);
|
||||||
|
this.level = level;
|
||||||
|
this.height = height;
|
||||||
|
this.minBuildHeight = minBuildHeight;
|
||||||
|
this.chunkSource = new VirtualChunkSource(this);
|
||||||
|
this.lighter = new LevelLightEngine(chunkSource, true, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run this after you're done using setBlock().
|
||||||
|
*/
|
||||||
|
public void runLightingEngine() {
|
||||||
|
for (Map.Entry<BlockPos, BlockState> entry : blocksAdded.entrySet()) {
|
||||||
|
BlockPos pos = entry.getKey();
|
||||||
|
BlockState state = entry.getValue();
|
||||||
|
int light = state.getLightEmission();
|
||||||
|
if (light > 0) {
|
||||||
|
lighter.onBlockEmissionIncrease(pos, light);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lighter.runUpdates(Integer.MAX_VALUE, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTileEntities(Collection<BlockEntity> tileEntities) {
|
||||||
|
tesAdded.clear();
|
||||||
|
tileEntities.forEach(te -> tesAdded.put(te.getBlockPos(), te));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear() {
|
||||||
|
blocksAdded.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
// MEANINGFUL OVERRIDES
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean setBlock(BlockPos pos, BlockState newState, int flags) {
|
||||||
|
blocksAdded.put(pos, newState);
|
||||||
|
|
||||||
|
SectionPos sectionPos = SectionPos.of(pos);
|
||||||
|
if (spannedSections.add(sectionPos)) {
|
||||||
|
lighter.updateSectionStatus(sectionPos, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((flags & Block.UPDATE_SUPPRESS_LIGHT) == 0) {
|
||||||
|
lighter.checkBlock(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getHeight() {
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMinBuildHeight() {
|
||||||
|
return minBuildHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChunkSource getChunkSource() {
|
||||||
|
return chunkSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LevelLightEngine getLightEngine() {
|
||||||
|
return lighter;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected LevelEntityGetter<Entity> getEntities() {
|
||||||
|
return entityGetter;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockState getBlockState(@Nullable BlockPos pos) {
|
||||||
|
BlockState state = blocksAdded.get(pos);
|
||||||
|
if (state != null)
|
||||||
|
return state;
|
||||||
|
return Blocks.AIR.defaultBlockState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean setBlockAndUpdate(BlockPos pos, BlockState state) {
|
||||||
|
return setBlock(pos, state, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public BlockEntity getBlockEntity(BlockPos pos) {
|
||||||
|
return tesAdded.get(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isStateAtPosition(BlockPos pos, Predicate<BlockState> condition) {
|
||||||
|
return condition.test(getBlockState(pos));
|
||||||
|
}
|
||||||
|
|
||||||
|
public BlockState getBlockState(int x, int y, int z) {
|
||||||
|
return getBlockState(scratch.set(x, y, z));
|
||||||
|
}
|
||||||
|
|
||||||
|
// RENDERING CONSTANTS
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMaxLocalRawBrightness(BlockPos pos) {
|
||||||
|
return 15;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getShade(Direction p_230487_1_, boolean p_230487_2_) {
|
||||||
|
return 1f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIN WRAPPERS AHEAD
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RegistryAccess registryAccess() {
|
||||||
|
return level.registryAccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LevelTickAccess<Block> getBlockTicks() {
|
||||||
|
return level.getBlockTicks();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LevelTickAccess<Fluid> getFluidTicks() {
|
||||||
|
return level.getFluidTicks();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RecipeManager getRecipeManager() {
|
||||||
|
return level.getRecipeManager();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TagContainer getTagManager() {
|
||||||
|
return level.getTagManager();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getFreeMapId() {
|
||||||
|
return level.getFreeMapId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Scoreboard getScoreboard() {
|
||||||
|
return level.getScoreboard();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Biome getUncachedNoiseBiome(int p_225604_1_, int p_225604_2_, int p_225604_3_) {
|
||||||
|
return level.getUncachedNoiseBiome(p_225604_1_, p_225604_2_, p_225604_3_);
|
||||||
|
}
|
||||||
|
|
||||||
|
// UNIMPORTANT CONSTANTS
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public Entity getEntity(int id) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public MapItemSavedData getMapData(String mapName) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isLoaded(BlockPos pos) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<? extends Player> players() {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String gatherChunkSourceStats() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOOP
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void levelEvent(@Nullable Player player, int type, BlockPos pos, int data) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void playSound(@Nullable Player player, double x, double y, double z, SoundEvent soundIn,
|
||||||
|
SoundSource category, float volume, float pitch) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void playSound(@Nullable Player p_217384_1_, Entity p_217384_2_, SoundEvent p_217384_3_,
|
||||||
|
SoundSource p_217384_4_, float p_217384_5_, float p_217384_6_) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setMapData(String pMapId, MapItemSavedData pData) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void destroyBlockProgress(int breakerId, BlockPos pos, int progress) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateNeighbourForOutputSignal(BlockPos p_175666_1_, Block p_175666_2_) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void gameEvent(@Nullable Entity pEntity, GameEvent pEvent, BlockPos pPos) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendBlockUpdated(BlockPos pos, BlockState oldState, BlockState newState, int flags) {}
|
||||||
|
|
||||||
|
// Override Starlight's ExtendedWorld interface methods:
|
||||||
|
|
||||||
|
public LevelChunk getChunkAtImmediately(final int chunkX, final int chunkZ) {
|
||||||
|
return chunkSource.getChunk(chunkX, chunkZ, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ChunkAccess getAnyChunkImmediately(final int chunkX, final int chunkZ) {
|
||||||
|
return chunkSource.getChunk(chunkX, chunkZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Intentionally copied from LevelHeightAccessor. Lithium overrides these methods so we need to, too.
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMaxBuildHeight() {
|
||||||
|
return this.getMinBuildHeight() + this.getHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSectionsCount() {
|
||||||
|
return this.getMaxSection() - this.getMinSection();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMinSection() {
|
||||||
|
return SectionPos.blockToSectionCoord(this.getMinBuildHeight());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMaxSection() {
|
||||||
|
return SectionPos.blockToSectionCoord(this.getMaxBuildHeight() - 1) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isOutsideBuildHeight(BlockPos pos) {
|
||||||
|
return this.isOutsideBuildHeight(pos.getY());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isOutsideBuildHeight(int y) {
|
||||||
|
return y < this.getMinBuildHeight() || y >= this.getMaxBuildHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSectionIndex(int y) {
|
||||||
|
return this.getSectionIndexFromSectionY(SectionPos.blockToSectionCoord(y));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSectionIndexFromSectionY(int sectionY) {
|
||||||
|
return sectionY - this.getMinSection();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSectionYFromSectionIndex(int sectionIndex) {
|
||||||
|
return sectionIndex + this.getMinSection();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
@ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault
|
||||||
|
package com.jozufozu.flywheel.core.virtual;
|
||||||
|
|
||||||
|
import javax.annotation.ParametersAreNonnullByDefault;
|
||||||
|
|
||||||
|
import net.minecraft.MethodsReturnNonnullByDefault;
|
|
@ -47,7 +47,7 @@ public class FabricModelUtil {
|
||||||
return BlendMode.DEFAULT;
|
return BlendMode.DEFAULT;
|
||||||
};
|
};
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Flywheel.log.error("Detected FREX but failed to load wrapper field.", e);
|
Flywheel.LOGGER.error("Detected FREX but failed to load wrapper field.", e);
|
||||||
return material -> BlendMode.DEFAULT;
|
return material -> BlendMode.DEFAULT;
|
||||||
}
|
}
|
||||||
} else if (INDIUM_LOADED) {
|
} else if (INDIUM_LOADED) {
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
package com.jozufozu.flywheel.util;
|
|
||||||
|
|
||||||
import org.lwjgl.opengl.GL20;
|
|
||||||
|
|
||||||
// TODO: move this functionality into GlVertexArray and track it
|
|
||||||
public class AttribUtil {
|
|
||||||
|
|
||||||
public static void enableArrays(int count) {
|
|
||||||
enableArrays(0, count);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void enableArrays(int fromInclusive, int toExclusive) {
|
|
||||||
for (int i = fromInclusive; i < toExclusive; i++) {
|
|
||||||
GL20.glEnableVertexAttribArray(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void disableArrays(int count) {
|
|
||||||
disableArrays(0, count);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void disableArrays(int fromInclusive, int toExclusive) {
|
|
||||||
for (int i = fromInclusive; i < toExclusive; i++) {
|
|
||||||
GL20.glDisableVertexAttribArray(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
47
src/main/java/com/jozufozu/flywheel/util/Mods.java
Normal file
47
src/main/java/com/jozufozu/flywheel/util/Mods.java
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
package com.jozufozu.flywheel.util;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import net.fabricmc.loader.api.FabricLoader;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For compatibility with and without another mod present, we have to define load conditions of the specific code
|
||||||
|
*/
|
||||||
|
public enum Mods {
|
||||||
|
STARLIGHT("starlight");
|
||||||
|
|
||||||
|
private final String id;
|
||||||
|
|
||||||
|
Mods(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return a boolean of whether the mod is loaded or not based on mod id
|
||||||
|
*/
|
||||||
|
public boolean isLoaded() {
|
||||||
|
return FabricLoader.getInstance().isModLoaded(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple hook to run code if a mod is installed
|
||||||
|
* @param toRun will be run only if the mod is loaded
|
||||||
|
* @return Optional.empty() if the mod is not loaded, otherwise an Optional of the return value of the given supplier
|
||||||
|
*/
|
||||||
|
public <T> Optional<T> runIfInstalled(Supplier<Supplier<T>> toRun) {
|
||||||
|
if (isLoaded())
|
||||||
|
return Optional.of(toRun.get().get());
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple hook to execute code if a mod is installed
|
||||||
|
* @param toExecute will be executed only if the mod is loaded
|
||||||
|
*/
|
||||||
|
public void executeIfInstalled(Supplier<Runnable> toExecute) {
|
||||||
|
if (isLoaded()) {
|
||||||
|
toExecute.get().run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,12 +12,6 @@ void fragment(BlockFrag r) {
|
||||||
|
|
||||||
vec4 color = vec4(tex.rgb * FLWLight(r.light).rgb * r.diffuse, tex.a) * r.color;
|
vec4 color = vec4(tex.rgb * FLWLight(r.light).rgb * r.diffuse, tex.a) * r.color;
|
||||||
|
|
||||||
// flw_WorldPos = ;
|
|
||||||
// flw_Normal = ;
|
|
||||||
// flw_Albedo = tex.rgb;
|
|
||||||
// flw_Alpha = tex.a;
|
|
||||||
// flw_LightMap = r.light;
|
|
||||||
// flw_Tint = r.color;
|
|
||||||
FLWFinalizeColor(color);
|
FLWFinalizeColor(color);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue