Skip to content

Commit

Permalink
Re-add frustum culling, add hack to make moving past lots of speakers…
Browse files Browse the repository at this point in the history
… feel less weird
  • Loading branch information
FoundationGames committed Aug 11, 2023
1 parent 81b03c3 commit a7e57d1
Show file tree
Hide file tree
Showing 7 changed files with 120 additions and 25 deletions.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ loader_version=0.14.21
#Fabric api
fabric_version=0.84.0+1.20.1

mod_version = 1.0.0-beta.9
mod_version = 1.0.0-beta.10
maven_group = io.github.foundationgames
archives_base_name = phonos

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package io.github.foundationgames.phonos.client.render;

import net.minecraft.client.render.Frustum;

public class CableBounds {
private double minX, minY, minZ, maxX, maxY, maxZ;

public void clear() {
minX = Float.POSITIVE_INFINITY;
minY = Float.POSITIVE_INFINITY;
minZ = Float.POSITIVE_INFINITY;
maxX = Float.NEGATIVE_INFINITY;
maxY = Float.NEGATIVE_INFINITY;;
maxZ = Float.NEGATIVE_INFINITY;;
}

public void fit(double x, double y, double z) {
minX = Math.min(minX, x);
minY = Math.min(minY, y);
minZ = Math.min(minZ, z);
maxX = Math.max(maxX, x);
maxY = Math.max(maxY, y);
maxZ = Math.max(maxZ, z);
}

public void fitTwo(double x0, double y0, double z0, double x1, double y1, double z1) {
minX = Math.min(x0, x1);
minY = Math.min(y0, y1);
minZ = Math.min(z0, z1);
maxX = Math.max(x0, x1);
maxY = Math.max(y0, y1);
maxZ = Math.max(z0, z1);
}

public boolean visible(Frustum frustum) {
return frustum.isVisible(minX, minY, minZ, maxX, maxY, maxZ);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,7 @@
import io.github.foundationgames.phonos.world.sound.CablePlugPoint;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.model.Model;
import net.minecraft.client.render.BufferBuilder;
import net.minecraft.client.render.Tessellator;
import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.render.WorldRenderer;
import net.minecraft.client.render.*;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
Expand Down Expand Up @@ -67,8 +64,9 @@ private static void lerpCableEnd(Vector4f[] out, Vector4f[] begin, Vector4f[] en
}
}

public static void renderConnection(@Nullable CableVBOContainer vboContainer, PhonosClientConfig config, World world, CableConnection conn,
MatrixStack matrices, VertexConsumer immediate, Model cableEndModel, int overlay, float tickDelta) {
public static void renderConnection(@Nullable CableVBOContainer vboContainer, PhonosClientConfig config, World world,
CableConnection conn, @Nullable CableBounds bounds, Frustum frustum, MatrixStack matrices,
VertexConsumer immediate, Model cableEndModel, int overlay, float tickDelta) {
int startLight, endLight;

// Connection plug points are always rendered immediate
Expand Down Expand Up @@ -97,12 +95,25 @@ public static void renderConnection(@Nullable CableVBOContainer vboContainer, Ph

if (conn.isStatic() && vboContainer != null) { // Vbo can be used for this connection
if (vboContainer.rebuild) {
if (bounds != null) {
bounds.fit(cableStPt.x, cableStPt.y, cableStPt.z);
bounds.fit(cableEnPt.x, cableEnPt.y, cableEnPt.z);
}

BufferBuilder buffer = Tessellator.getInstance().getBuffer();
matrices = new MatrixStack();

buildCableGeometry(conn, matrices, buffer, segments, length, detail, startLight, endLight, overlay);
}
} else { // Connection must be rendered immediate
if (bounds != null && config.cableCulling) {
bounds.fitTwo(cableStPt.x, cableStPt.y, cableStPt.z, cableEnPt.x, cableEnPt.y, cableEnPt.z);

if (!bounds.visible(frustum)) {
return;
}
}

if (config.cableLODs) {
float cx = (cableStPt.x + cableEnPt.x) * 0.5f;
float cy = (cableStPt.y + cableEnPt.y) * 0.5f;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ public class CableVBOContainer {
public @Nullable VertexBuffer buffer = null;
private List<CableConnection> cachedCons = new ArrayList<>();

private CableBounds bounds = new CableBounds();

public void refresh(ConnectionCollection conns) {
List<CableConnection> connections = new ArrayList<>();
conns.forEach((i, conn) -> {
Expand All @@ -41,7 +43,7 @@ public void refresh(ConnectionCollection conns) {
}
}

public void render(MatrixStack matrices, VertexConsumer immediate, RenderLayer layer, BasicModel cableEndModel,
public void render(MatrixStack matrices, VertexConsumer immediate, RenderLayer layer, BasicModel cableEndModel, Frustum frustum,
ConnectionCollection conns, PhonosClientConfig config, World world, int overlay, float tickDelta) {
boolean rebuild = this.buffer == null || this.rebuild;

Expand All @@ -53,11 +55,14 @@ public void render(MatrixStack matrices, VertexConsumer immediate, RenderLayer l
builder.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_COLOR_TEXTURE_OVERLAY_LIGHT_NORMAL);

this.buffer = vbo;

this.bounds.clear();
}

// Render each connection point in immediate mode, and render cables into the given vertex buffer
conns.forEach((i, conn) ->
CableRenderer.renderConnection(this, config, world, conn, matrices, immediate, cableEndModel, overlay, tickDelta));
CableRenderer.renderConnection(this, config, world, conn, rebuild ? bounds : null, frustum,
matrices, immediate, cableEndModel, overlay, tickDelta));

var vbo = this.buffer;

Expand All @@ -69,7 +74,9 @@ public void render(MatrixStack matrices, VertexConsumer immediate, RenderLayer l
this.rebuild = false;
}


if (config.cableCulling && !bounds.visible(frustum)) {
return;
}

// Set up the render state for this render phase (and texture)
layer.startDrawing();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@
import io.github.foundationgames.phonos.Phonos;
import io.github.foundationgames.phonos.PhonosClient;
import io.github.foundationgames.phonos.client.model.BasicModel;
import io.github.foundationgames.phonos.client.render.CableBounds;
import io.github.foundationgames.phonos.client.render.CableRenderer;
import io.github.foundationgames.phonos.client.render.CableVBOContainer;
import io.github.foundationgames.phonos.config.PhonosClientConfig;
import io.github.foundationgames.phonos.mixin.WorldRendererAccess;
import io.github.foundationgames.phonos.world.sound.block.OutputBlockEntity;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.block.entity.BlockEntityRenderer;
import net.minecraft.client.render.block.entity.BlockEntityRendererFactory;
Expand All @@ -18,6 +21,8 @@ public class CableOutputBlockEntityRenderer<E extends BlockEntity & OutputBlockE
public static final Identifier TEXTURE = Phonos.id("textures/entity/audio_cable.png");
private final BasicModel cableEndModel;

private final CableBounds boundCache = new CableBounds();

public CableOutputBlockEntityRenderer(BlockEntityRendererFactory.Context ctx) {
cableEndModel = new BasicModel(ctx.getLayerModelPart(PhonosClient.AUDIO_CABLE_END_LAYER));
}
Expand All @@ -27,6 +32,7 @@ public void render(E entity, float tickDelta, MatrixStack matrices, VertexConsum
var renderLayer = cableEndModel.getLayer(TEXTURE);
var immediate = vertexConsumers.getBuffer(renderLayer);
var config = PhonosClientConfig.get();
var frustum = ((WorldRendererAccess) MinecraftClient.getInstance().worldRenderer).phonos$getFrustum();

matrices.push();

Expand All @@ -37,10 +43,11 @@ public void render(E entity, float tickDelta, MatrixStack matrices, VertexConsum

if (vbos) {
CableVBOContainer vboContainer = entity.getOrCreateVBOContainer();
vboContainer.render(matrices, immediate, renderLayer, cableEndModel, entity.getOutputs(), config, entity.getWorld(), overlay, tickDelta);
vboContainer.render(matrices, immediate, renderLayer, cableEndModel, frustum, entity.getOutputs(), config, entity.getWorld(), overlay, tickDelta);
} else {
entity.getOutputs().forEach((i, conn) ->
CableRenderer.renderConnection(null, config, entity.getWorld(), conn, matrices, immediate, cableEndModel, overlay, tickDelta));
CableRenderer.renderConnection(null, config, entity.getWorld(), conn, boundCache, frustum,
matrices, immediate, cableEndModel, overlay, tickDelta));
}

matrices.pop();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.github.foundationgames.phonos.sound;

import com.google.common.util.concurrent.AtomicDouble;
import io.github.foundationgames.phonos.config.PhonosClientConfig;
import io.github.foundationgames.phonos.sound.emitter.SoundEmitterTree;
import net.minecraft.client.MinecraftClient;
Expand All @@ -8,16 +9,19 @@
import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvent;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.random.Random;
import org.joml.Vector3d;
import org.spongepowered.asm.mixin.injection.At;

import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;

public class MultiSourceSoundInstance extends AbstractSoundInstance implements TickableSoundInstance {
public final AtomicReference<SoundEmitterTree> emitters;
private double x;
private double y;
private double z;
private double camX, camZ;
private double x, y, z;
protected float volMultiplier = 1;

private boolean done;

Expand All @@ -37,7 +41,7 @@ public MultiSourceSoundInstance(SoundEmitterTree tree, SoundEvent sound, SoundCa

@Override
public float getVolume() {
return (float) (super.getVolume() * PhonosClientConfig.get().phonosMasterVolume);
return (float) (super.getVolume() * PhonosClientConfig.get().phonosMasterVolume * volMultiplier);
}

@Override
Expand All @@ -61,40 +65,70 @@ private void updatePosition() {

var pos = new Vector3d();

double[] emWeights = {0};
boolean[] foundSources = {false};
AtomicDouble emWeights = new AtomicDouble(0);
AtomicDouble minDist = new AtomicDouble(Double.POSITIVE_INFINITY);
AtomicBoolean foundSources = new AtomicBoolean(false);

var emPos = new Vector3d();

this.x = 0;
this.y = 999;
this.y = camPos.y + 999;
this.z = 0;

this.emitters.get().forEachSource(mc.world, em -> {
double weight;

foundSources[0] = true;
foundSources.set(true);
emPos.set(em.x(), em.y(), em.z());

double dist = emPos.distance(camPos.x, camPos.y, camPos.z);

if (dist < minDist.get()) {
minDist.set(dist);
}

if (dist <= 1.4135) {
weight = -0.05 * Math.pow(dist, 4) + 1;
} else {
weight = Math.pow(2, -(dist - 1.0923));
}

pos.add(emPos.mul(weight));
emWeights[0] += weight;
emWeights.addAndGet(weight);
});

if (foundSources[0]) {
pos.div(emWeights[0]);
if (foundSources.get()) {
pos.div(emWeights.get());

// Avoid headache by biasing the sound into the player head when moving fast
double camVel = Vector3d.length(camPos.x - this.camX, 0, camPos.z - this.camZ);

if (camVel > 0.3) {
float camWeight = MathHelper.clamp((float) ((-0.0333 / (camVel - 0.2666)) + 1), 0, 1);

pos.mul(1 - camWeight);
pos.add(camWeight * camPos.x, camWeight * camPos.y + 2, camWeight * camPos.z);
}

this.x = pos.x();
this.y = pos.y();
this.z = pos.z();
}

double errorDist = minDist.get() - pos.distance(camPos.x, camPos.y, camPos.z);

if (errorDist > 0) {
float range = this.volume * 16;
errorDist = Math.min(errorDist, range);

// Fake distance fade, I don't have a good reason for this function other than it works well enough
this.volMultiplier = (float) MathHelper.clamp(1 - (Math.pow(errorDist / range, 0.25)), 0, 1);
} else {
this.volMultiplier = 1;
}

this.camX = camPos.x;
this.camZ = camPos.z;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,6 @@ public boolean purge(Consumer<CableConnection> purgeAction) {
}

if (connections[i] != null && connections[i].shouldRemove(this.blockEntity.getWorld())) {
System.out.println("CAN EXIST: " + connections[i].end.canPlugExist(this.blockEntity.getWorld()));

purgeAction.accept(connections[i]);
connections[i] = null;
changed = true;
Expand Down

0 comments on commit a7e57d1

Please sign in to comment.