Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix refraction and material transitions. #1673

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
//tread air as a null block depending on octreetype and were we are in the trace
// Treat 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)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?

//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);
}
Comment on lines +563 to +565
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Either remove this or comment it alltogether.

Suggested change
if (currentBlock.refractive) {
//ray.setCurrentMaterial(currentBlock.waterlogged ? Water.INSTANCE : Air.INSTANCE);
}
// 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