Skip to content

Commit

Permalink
The long awaited commit towards a new chunk renderer
Browse files Browse the repository at this point in the history
  • Loading branch information
jellysquid3 committed Mar 25, 2020
1 parent 7664c58 commit 5a26131
Show file tree
Hide file tree
Showing 35 changed files with 1,511 additions and 886 deletions.
18 changes: 7 additions & 11 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,12 @@
org.gradle.jvmargs=-Xmx1G

# Fabric Properties
# check these on https://fabricmc.net/use
minecraft_version=1.15.1
yarn_mappings=1.15.1+build.3
loader_version=0.7.2+build.174
# check these on https://fabricmc.net/use
minecraft_version=1.15.2
yarn_mappings=1.15.2+build.14
loader_version=0.7.8+build.189

# Mod Properties
mod_version = 0.1.0
maven_group = me.jellysquid.mods
archives_base_name = sodium

# Dependencies
# currently not on the main fabric site, check on the maven: https://maven.fabricmc.net/net/fabricmc/fabric-api/fabric-api
fabric_version=0.4.24+build.279-1.15
mod_version = 0.1.0
maven_group = me.jellysquid.mods
archives_base_name = sodium
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-6.2.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
8 changes: 0 additions & 8 deletions settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,6 @@ pluginManagement {
name = 'Fabric'
url = 'https://maven.fabricmc.net/'
}
maven {
name = "Jitpack"
url 'https://jitpack.io/'
}
maven {
name = "Forge"
url = "https://files.minecraftforge.net/maven/"
}
gradlePluginPortal()
}
}
Original file line number Diff line number Diff line change
@@ -1,48 +1,44 @@
package me.jellysquid.mods.sodium.client.render.chunk;

import com.google.common.collect.Lists;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.ObjectArrayFIFOQueue;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import it.unimi.dsi.fastutil.objects.ObjectList;
import me.jellysquid.mods.sodium.client.SodiumClientMod;
import me.jellysquid.mods.sodium.client.gui.SodiumGameOptions;
import me.jellysquid.mods.sodium.common.util.DirectionUtil;
import net.minecraft.block.BlockState;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.Camera;
import net.minecraft.client.render.Frustum;
import net.minecraft.client.render.chunk.ChunkBuilder;
import net.minecraft.client.render.chunk.ChunkOcclusionDataBuilder;
import net.minecraft.client.util.math.Vector3f;
import net.minecraft.entity.Entity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.*;
import net.minecraft.world.World;
import net.minecraft.world.chunk.ChunkSection;
import net.minecraft.world.chunk.WorldChunk;

import java.util.*;
import java.util.Comparator;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;

public class ChunkGraph {
private static final Direction[] DIRECTIONS = Direction.values();
public class ChunkGraph<T extends ChunkRenderData> {
private final Long2ObjectOpenHashMap<ChunkGraphNode<T>> nodes = new Long2ObjectOpenHashMap<>();
private final ObjectList<ChunkGraphNode<T>> visibleNodes = new ObjectArrayList<>();

private final ObjectList<ChunkGraphNode> visibleNodes = new ObjectArrayList<>();

private final ChunkGraphNodeStorage nodes;
private final ChunkRenderManager<T> renderManager;
private final World world;
private final ObjectArrayFIFOQueue<ChunkGraphNode> iterationQueue = new ObjectArrayFIFOQueue<>();
private final ObjectArrayFIFOQueue<ChunkGraphNode<T>> iterationQueue = new ObjectArrayFIFOQueue<>();

private int minX, minZ, maxX, maxZ;
private int renderDistance;

private ChunkStatusTracker statusTracker;

public ChunkGraph(World world, ExtendedBuiltChunkStorage chunks, ChunkStatusTracker statusTracker, int renderDistance) {
public ChunkGraph(ChunkRenderManager<T> renderManager, World world, int renderDistance) {
this.renderManager = renderManager;
this.world = world;
this.renderDistance = renderDistance;
this.statusTracker = statusTracker;
this.nodes = new ChunkGraphNodeStorage(renderDistance, chunks.getData());
}

public void calculateVisible(Camera camera, Vec3d cameraPos, BlockPos blockPos, int frame, Frustum frustum, boolean spectator) {
Expand All @@ -56,7 +52,7 @@ public void calculateVisible(Camera camera, Vec3d cameraPos, BlockPos blockPos,
this.maxX = center.getX() + (this.renderDistance * 16);
this.maxZ = center.getZ() + (this.renderDistance * 16);

this.reset();
this.visibleNodes.clear();

boolean cull = this.init(blockPos, camera, cameraPos, frustum, frame, spectator);

Expand All @@ -65,10 +61,10 @@ public void calculateVisible(Camera camera, Vec3d cameraPos, BlockPos blockPos,
boolean fogCulling = cull && this.renderDistance > 4 && options.quality.enableFog && options.performance.useFogChunkCulling;
int maxChunkDistance = (this.renderDistance * 16) + 16;

ObjectArrayFIFOQueue<ChunkGraphNode> queue = this.iterationQueue;
ObjectArrayFIFOQueue<ChunkGraphNode<T>> queue = this.iterationQueue;

while (!queue.isEmpty()) {
ChunkGraphNode node = this.iterationQueue.dequeue();
ChunkGraphNode<T> node = this.iterationQueue.dequeue();

this.visibleNodes.add(node);

Expand All @@ -78,10 +74,14 @@ public void calculateVisible(Camera camera, Vec3d cameraPos, BlockPos blockPos,

Direction dir = node.direction;

for (Direction adjDir : DIRECTIONS) {
ChunkGraphNode adjNode = this.getAdjacentChunk(node, adjDir);
for (Direction adjDir : DirectionUtil.ALL_DIRECTIONS) {
ChunkGraphNode<T> adjNode = this.getAdjacentChunk(node, adjDir);

if (adjNode == null) {
continue;
}

if (adjNode == null || adjNode.getRebuildFrame() == frame) {
if (adjNode.getRebuildFrame() == frame) {
continue;
}

Expand All @@ -99,7 +99,7 @@ public void calculateVisible(Camera camera, Vec3d cameraPos, BlockPos blockPos,
}
}

if (!this.statusTracker.areChunksAvailable(adjNode.getIndex())) {
if (!adjNode.hasNeighbors()) {
continue;
}

Expand All @@ -114,11 +114,11 @@ public void calculateVisible(Camera camera, Vec3d cameraPos, BlockPos blockPos,

private boolean init(BlockPos blockPos, Camera camera, Vec3d cameraPos, Frustum frustum, int frame, boolean spectator) {
MinecraftClient client = MinecraftClient.getInstance();
ObjectArrayFIFOQueue<ChunkGraphNode> queue = this.iterationQueue;
ObjectArrayFIFOQueue<ChunkGraphNode<T>> queue = this.iterationQueue;

boolean cull = client.chunkCullingEnabled;

ChunkGraphNode node = this.nodes.get(blockPos);
ChunkGraphNode<T> node = this.getOrCreateNode(blockPos);

if (node != null) {
node.reset();
Expand Down Expand Up @@ -150,11 +150,11 @@ private boolean init(BlockPos blockPos, Camera camera, Vec3d cameraPos, Frustum
int x = MathHelper.floor(cameraPos.x / 16.0D) * 16;
int z = MathHelper.floor(cameraPos.z / 16.0D) * 16;

List<ChunkGraphNode> list = Lists.newArrayList();
List<ChunkGraphNode<T>> list = Lists.newArrayList();

for (int x2 = -this.renderDistance; x2 <= this.renderDistance; ++x2) {
for (int z2 = -this.renderDistance; z2 <= this.renderDistance; ++z2) {
ChunkGraphNode chunk = this.nodes.get(new BlockPos(x + (x2 << 4) + 8, y, z + (z2 << 4) + 8));
ChunkGraphNode<T> chunk = this.getOrCreateNode(new BlockPos(x + (x2 << 4) + 8, y, z + (z2 << 4) + 8));

if (chunk == null) {
continue;
Expand All @@ -171,51 +171,63 @@ private boolean init(BlockPos blockPos, Camera camera, Vec3d cameraPos, Frustum

list.sort(Comparator.comparingDouble(o -> blockPos.getSquaredDistance(o.chunk.getOrigin().add(8, 8, 8))));

for (ChunkGraphNode n : list) {
for (ChunkGraphNode<T> n : list) {
queue.enqueue(n);
}
}

return cull;
}

private ChunkGraphNode getAdjacentChunk(ChunkGraphNode node, Direction direction) {
BlockPos chunkPos = node.chunk.getNeighborPosition(direction);
private ChunkGraphNode<T> getOrCreateNode(BlockPos pos) {
return this.nodes.computeIfAbsent(ChunkSectionPos.asLong(pos.getX() >> 4, pos.getY() >> 4, pos.getZ() >> 4), this::createNode);
}

private ChunkGraphNode<T> createNode(long pos) {
return new ChunkGraphNode<>(this.renderManager.createChunkRender(ChunkSectionPos.getX(pos) << 4, ChunkSectionPos.getY(pos) << 4, ChunkSectionPos.getZ(pos) << 4));
}

private ChunkGraphNode<T> getAdjacentChunk(ChunkGraphNode<T> node, Direction direction) {
int x = node.chunk.getChunkX() + direction.getOffsetX();
int y = node.chunk.getChunkY() + direction.getOffsetY();
int z = node.chunk.getChunkZ() + direction.getOffsetZ();

if (chunkPos.getX() < this.minX || chunkPos.getX() > this.maxX) {
if (x < this.minX || x > this.maxX) {
return null;
}

if (chunkPos.getZ() < this.minZ || chunkPos.getZ() > this.maxZ) {
if (z < this.minZ || z > this.maxZ) {
return null;
}

if (chunkPos.getY() < 0 || chunkPos.getY() >= 256) {
if (y < 0 || y >= 256) {
return null;
}

return this.nodes.get(chunkPos);
return this.nodes.computeIfAbsent(ChunkSectionPos.asLong(x, y, z), this::createNode);
}

private Set<Direction> getOpenChunkFaces(BlockPos pos) {
ChunkOcclusionDataBuilder occlusionBuilder = new ChunkOcclusionDataBuilder();

WorldChunk chunk = this.world.getChunk(pos.getX() >> 4, pos.getZ() >> 4);

ChunkSection section = chunk.getSectionArray()[pos.getY() >> 4];

if (section != null && !section.isEmpty()) {
BlockPos.Mutable mpos = new BlockPos.Mutable();
if (section == null || section.isEmpty()) {
return EnumSet.allOf(Direction.class);
}

ChunkOcclusionDataBuilder occlusionBuilder = new ChunkOcclusionDataBuilder();

BlockPos.Mutable mpos = new BlockPos.Mutable();

for (int x = 0; x < 16; x++) {
for (int y = 0; y < 16; y++) {
for (int z = 0; z < 16; z++) {
BlockState state = section.getBlockState(x, y, z);
mpos.set(x, y, z);
for (int x = 0; x < 16; x++) {
for (int y = 0; y < 16; y++) {
for (int z = 0; z < 16; z++) {
BlockState state = section.getBlockState(x, y, z);
mpos.set(x, y, z);

if (state.isFullOpaque(this.world, mpos)) {
occlusionBuilder.markClosed(mpos);
}
if (state.isFullOpaque(this.world, mpos)) {
occlusionBuilder.markClosed(mpos);
}
}
}
Expand All @@ -225,14 +237,23 @@ private Set<Direction> getOpenChunkFaces(BlockPos pos) {
}

public void reset() {
for (ChunkGraphNode<?> node : this.nodes.values()) {
node.delete();
}

this.nodes.clear();
this.visibleNodes.clear();
}

public ObjectList<ChunkGraphNode> getVisibleChunks() {
public ObjectList<ChunkGraphNode<T>> getVisibleChunks() {
return this.visibleNodes;
}

public int getVisibleChunkCount() {
return this.visibleNodes.size();
}

public ChunkGraphNode<T> getChunkRender(int x, int y, int z) {
return this.nodes.get(ChunkSectionPos.asLong(x, y, z));
}
}
Original file line number Diff line number Diff line change
@@ -1,24 +1,22 @@
package me.jellysquid.mods.sodium.client.render.chunk;

import net.minecraft.client.render.chunk.ChunkBuilder;
import me.jellysquid.mods.sodium.client.render.chunk.compile.ChunkRender;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.Direction;

class ChunkGraphNode {
public final ChunkBuilder.BuiltChunk chunk;
class ChunkGraphNode<T extends ChunkRenderData> {
public final ChunkRender<T> chunk;

public Direction direction;

public int propagationLevel;
public int rebuildFrame;
public byte cullingState;

private final int index;

public ChunkGraphNode(ChunkBuilder.BuiltChunk chunk, int index) {
public ChunkGraphNode(ChunkRender<T> chunk) {
this.chunk = chunk;
this.rebuildFrame = -1;
this.index = index;
}

public void updateCullingState(byte parent, Direction from) {
Expand All @@ -40,7 +38,7 @@ public void setRebuildFrame(int frame) {
}

public Box getBoundingBox() {
return this.chunk.boundingBox;
return this.chunk.getBoundingBox();
}

public void setPropagationLevel(int level) {
Expand All @@ -55,15 +53,23 @@ public int getRebuildFrame() {
return this.rebuildFrame;
}

public int getIndex() {
return this.index;
}

public boolean isVisibleThrough(Direction from, Direction to) {
return this.chunk.getData().isVisibleThrough(from, to);
return this.chunk.isVisibleThrough(from, to);
}

public BlockPos getOrigin() {
return this.chunk.getOrigin();
}

public boolean hasNeighbors() {
return this.chunk.hasNeighbors();
}

public void setCullingState(byte i) {
this.cullingState = i;
}

public void delete() {
this.chunk.delete();
}
}
Loading

0 comments on commit 5a26131

Please sign in to comment.