Skip to content

Commit

Permalink
Fixes #1515 for solid blocks and water
Browse files Browse the repository at this point in the history
  • Loading branch information
ConsueTerra committed Nov 12, 2023
1 parent 50f6444 commit 2d41b57
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 16 deletions.
1 change: 1 addition & 0 deletions chunky/src/java/se/llbit/chunky/block/minecraft/Air.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,6 @@ private Air() {
solid = false;
opaque = false;
invisible = true;
refractive = true;
}
}
7 changes: 4 additions & 3 deletions chunky/src/java/se/llbit/chunky/model/AnimatedQuadModel.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import se.llbit.chunky.plugin.PluginApi;
import se.llbit.chunky.renderer.scene.Scene;
import se.llbit.chunky.resources.AnimatedTexture;
import se.llbit.chunky.world.Material;
import se.llbit.math.Quad;
import se.llbit.math.Ray;
import se.llbit.math.Vector3;
Expand Down Expand Up @@ -42,7 +43,7 @@ public boolean intersect(Ray ray, Scene scene) {
Quad[] quads = getQuads();
AnimatedTexture[] textures = getTextures();
Tint[] tintedQuads = getTints();

Material mat = ray.getCurrentMaterial();
// The animation frame to use
int j = (int) (scene.getAnimationTime() * animationMode.framerate);
if (animationMode.positional) {
Expand All @@ -58,11 +59,11 @@ public boolean intersect(Ray ray, Scene scene) {
Quad quad = quads[i];
if (quad.intersect(ray)) {
float[] c = textures[i].getColor(ray.u, ray.v, j);
if (c[3] > Ray.EPSILON) {
if (c[3] > Ray.EPSILON || mat.refractive) {
tint = tintedQuads == null ? Tint.NONE : tintedQuads[i];
color = c;
ray.t = ray.tNext;
if (quad.doubleSided)
if (quad.doubleSided || mat.refractive)
ray.orientNormal(quad.n);
else
ray.setNormal(quad.n);
Expand Down
6 changes: 4 additions & 2 deletions chunky/src/java/se/llbit/chunky/model/QuadModel.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import se.llbit.chunky.plugin.PluginApi;
import se.llbit.chunky.renderer.scene.Scene;
import se.llbit.chunky.resources.Texture;
import se.llbit.chunky.world.Material;
import se.llbit.math.Quad;
import se.llbit.math.Ray;
import se.llbit.math.Vector3;
Expand Down Expand Up @@ -112,18 +113,19 @@ public boolean intersect(Ray ray, Scene scene) {
Quad[] quads = getQuads();
Texture[] textures = getTextures();
Tint[] tintedQuads = getTints();
Material mat = ray.getCurrentMaterial();

float[] color = null;
Tint tint = Tint.NONE;
for (int i = 0; i < quads.length; ++i) {
Quad quad = quads[i];
if (quad.intersect(ray)) {
float[] c = textures[i].getColor(ray.u, ray.v);
if (c[3] > Ray.EPSILON) {
if (c[3] > Ray.EPSILON || mat.refractive) {
tint = tintedQuads == null ? Tint.NONE : tintedQuads[i];
color = c;
ray.t = ray.tNext;
if (quad.doubleSided)
if (quad.doubleSided || mat.refractive)
ray.orientNormal(quad.n);
else
ray.setNormal(quad.n);
Expand Down
16 changes: 11 additions & 5 deletions chunky/src/java/se/llbit/chunky/renderer/scene/Scene.java
Original file line number Diff line number Diff line change
Expand Up @@ -360,8 +360,8 @@ public Scene() {
branchCount = PersistentSettings.getBranchCountDefault();

palette = new BlockPalette();
worldOctree = new Octree(octreeImplementation, 1);
waterOctree = new Octree(octreeImplementation, 1);
worldOctree = new Octree(octreeImplementation, 1, Octree.OctreeType.WORLD);
waterOctree = new Octree(octreeImplementation, 1, Octree.OctreeType.WATER);
emitterGrid = null;
}

Expand Down Expand Up @@ -744,7 +744,7 @@ private boolean worldIntersection(Ray ray) {
} else {
r = new Ray(start);
r.setCurrentMaterial(start.getPrevMaterial(), start.getPrevData());
if (waterOctree.enterBlock(this, r, palette) && r.distance < ray.t) {
if (waterOctree.enterBlock(this, r, palette) && r.distance < ray.t + Ray.EPSILON) {
ray.t = r.distance;
ray.setNormal(r.getNormal());
ray.color.set(r.color);
Expand Down Expand Up @@ -824,8 +824,8 @@ public synchronized void loadChunks(TaskTracker taskTracker, World world, Collec

// Create new octree to fit all chunks.
palette = new BlockPalette();
worldOctree = new Octree(octreeImplementation, requiredDepth);
waterOctree = new Octree(octreeImplementation, requiredDepth);
worldOctree = new Octree(octreeImplementation, requiredDepth, Octree.OctreeType.WORLD);
waterOctree = new Octree(octreeImplementation, requiredDepth, Octree.OctreeType.WATER);

grassTexture = biomeStructureFactory.create();
foliageTexture = biomeStructureFactory.create();
Expand Down Expand Up @@ -2227,6 +2227,12 @@ private synchronized boolean loadOctree(SceneIOProvider context, TaskTracker tas
// this dump is so old that it doesn't contain a water texture (Chunky 2.3.0, #691)
waterTexture = BiomeStructure.get(this.biomeStructureImplementation).create();
}
if (worldOctree.type == null) {
worldOctree.type = Octree.OctreeType.WORLD;
}
if (waterOctree.type == null) {
waterOctree.type = Octree.OctreeType.WATER;
}
palette = data.palette;
palette.applyMaterials();
Log.info("Octree loaded");
Expand Down
31 changes: 27 additions & 4 deletions chunky/src/java/se/llbit/math/Octree.java
Original file line number Diff line number Diff line change
Expand Up @@ -244,11 +244,26 @@ public int getData() {
}
}

/** The type of Octree, used to adjust intersection code based on contents*/
public enum OctreeType {
/**
* Contains all world geometry excluding water, water is removed from water logged blocks
* and full water blocks are replaced with air
*/
WORLD,
/**
* Contains all the water geometry only, other blocks are air
*/
WATER
}

/**
* Timestamp of last serialization.
*/
private long timestamp = 0;

public OctreeType type;

private OctreeImplementation implementation;

/**
Expand All @@ -257,9 +272,10 @@ public int getData() {
*
* @param octreeDepth The number of levels in the Octree.
*/
public Octree(String impl, int octreeDepth) {
public Octree(String impl, int octreeDepth, OctreeType type) {
Log.infof("Building new octree (%s)", impl);
implementation = getImplementationFactory(impl).create(octreeDepth);
this.type = type;
}

protected Octree(OctreeImplementation impl) {
Expand Down Expand Up @@ -484,6 +500,8 @@ public boolean enterBlock(Scene scene, Ray ray, BlockPalette palette) {
int depth = implementation.getDepth();

double distance = 0;
//tread air as a null block depending on octreetype and were we are in the trace
boolean includeAir = this.type == OctreeType.WORLD && !ray.getPrevMaterial().isWater();

// floating point division are slower than multiplication so we cache them
// We also try to limit the number of time the ray origin is updated
Expand Down Expand Up @@ -539,9 +557,14 @@ public boolean enterBlock(Scene scene, Ray ray, BlockPalette palette) {
ray.distance += distance;
distance = 0;
if (currentBlock.intersect(ray, scene)) {
if (prevBlock != currentBlock)
if (prevBlock != currentBlock) { //|| (currentBlock.refractive)) {
//for things like glass panes coerce the current mat to be air or water
// TODO testing
if (currentBlock.refractive) {
//ray.setCurrentMaterial(currentBlock.waterlogged ? Water.INSTANCE : Air.INSTANCE);
}
return true;

}
ray.o.scaleAdd(Ray.OFFSET, ray.d);
offsetX = -ray.o.x * invDx;
offsetY = -ray.o.y * invDy;
Expand All @@ -556,7 +579,7 @@ public boolean enterBlock(Scene scene, Ray ray, BlockPalette palette) {
offsetZ = -ray.o.z * invDz;
continue;
}
} else if (!currentBlock.isSameMaterial(prevBlock) && currentBlock != Air.INSTANCE) {
} else if (!currentBlock.isSameMaterial(prevBlock) && (currentBlock != Air.INSTANCE || includeAir)) {
// Origin and distance of ray need to be updated
ray.o.scaleAdd(distance, ray.d);
ray.distance += distance;
Expand Down
4 changes: 2 additions & 2 deletions chunky/src/java/se/llbit/math/Quad.java
Original file line number Diff line number Diff line change
Expand Up @@ -158,14 +158,14 @@ public void sample(Vector3 loc, Random rand) {
*/
public boolean intersect(Ray ray) {
double u, v;

Material mat = ray.getCurrentMaterial();
double ix = ray.o.x - QuickMath.floor(ray.o.x + ray.d.x * Ray.OFFSET);
double iy = ray.o.y - QuickMath.floor(ray.o.y + ray.d.y * Ray.OFFSET);
double iz = ray.o.z - QuickMath.floor(ray.o.z + ray.d.z * Ray.OFFSET);

// Test that the ray is heading toward the plane of this quad.
double denom = ray.d.dot(n);
if (denom < -Ray.EPSILON || (doubleSided && denom > Ray.EPSILON)) {
if (denom < -Ray.EPSILON || ((doubleSided || mat.refractive) && denom > Ray.EPSILON)) {

// Test for intersection with the plane at origin.
double t = -(ix * n.x + iy * n.y + iz * n.z + d) / denom;
Expand Down

0 comments on commit 2d41b57

Please sign in to comment.