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

Add a 3D world texture implementation. #1639

Merged
merged 7 commits into from
Dec 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions chunky/src/java/se/llbit/chunky/renderer/scene/Scene.java
Original file line number Diff line number Diff line change
Expand Up @@ -1385,14 +1385,18 @@ public synchronized void loadChunks(TaskTracker taskTracker, World world, Collec
}
task.updateEta(target, done);
done += 1;

grassTexture.compact();
foliageTexture.compact();
waterTexture.compact();
}

worldOctree.endFinalization();
waterOctree.endFinalization();

grassTexture.compact();
foliageTexture.compact();
waterTexture.compact();
grassTexture.endFinalization();
foliageTexture.endFinalization();
waterTexture.endFinalization();
}

entities.loadDataFromOctree(worldOctree, palette, origin);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package se.llbit.chunky.renderer.scene.biome;

import it.unimi.dsi.fastutil.objects.Object2ReferenceOpenHashMap;
import se.llbit.chunky.renderer.scene.biome.worldtexture.WorldTexture2dBiomeStructure;
import se.llbit.chunky.renderer.scene.biome.worldtexture.WorldTexture3dBiomeStructure;
import se.llbit.chunky.world.Chunk;
import se.llbit.chunky.world.WorldTexture;
import se.llbit.log.Log;
import se.llbit.math.structures.Position2IntStructure;
import se.llbit.math.structures.Position2ReferenceStructure;
Expand All @@ -24,13 +25,11 @@ static void registerDefaults() {
//TODO: create a plugin api interface for registering implementations, and move this to that
BiomeStructure.register(new Trivial3dBiomeStructure());
BiomeStructure.register(new Trivial2dBiomeStructure());
BiomeStructure.register(new WorldTexture2dBiomeStructure());
BiomeStructure.register(new WorldTexture2dBiomeStructure.Factory());
BiomeStructure.register(new WorldTexture3dBiomeStructure.Factory());
}

/**
* This is basically a reimplementation of {@link WorldTexture#load} but instead loading into an arbitrary
* BiomeStructure implementation
*
* @param impl The implementation to load the legacy implementation into
* @param in The serialised legacy data in an input stream
* @return The newly constructed {@link BiomeStructure} of the specified implementation
Expand Down Expand Up @@ -84,10 +83,14 @@ static Factory get(@NotNull String key) throws NullPointerException {
void store(DataOutputStream out) throws IOException;

/**
* This method is called to tell the implementation to shrink its size. (Node-tree optimisation, etc.)
* Called when throughout insertion of new biomes, and on completion
* This method is called to tell the implementation to shrink its size. Called when throughout insertion of new biomes.
*/
default void compact() {}

/**
* This method is called to tell the implementation to finalize. Called on completion of loading.
*/
void compact();
default void endFinalization() {}

/**
* @return The registry key this biome format uses. Must be unique
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,5 @@ public void store(DataOutputStream out) throws IOException {
public String biomeFormat() {
return ID;
}

@Override
public void compact() {
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,5 @@ public void store(DataOutputStream out) throws IOException {
public String biomeFormat() {
return ID;
}

@Override
public void compact() {

}
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/* Copyright (c) 2012-2013 Jesper Öqvist <[email protected]>
/*
* Copyright (c) 2023 Chunky contributors
*
* This file is part of Chunky.
*
Expand All @@ -14,23 +15,24 @@
* You should have received a copy of the GNU General Public License
* along with Chunky. If not, see <http://www.gnu.org/licenses/>.
*/
package se.llbit.chunky.world;

package se.llbit.chunky.renderer.scene.biome.worldtexture;

import se.llbit.chunky.world.Chunk;
import se.llbit.math.ColorUtil;
import se.llbit.util.interner.Interner;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Arrays;

/**
* Chunk texture
*
* @author Jesper Öqvist <[email protected]>
* A 2D chunk texture. This stores a pixel for each block in a chunk, with 8 bits per channel.
*/
public class ChunkTexture {

public class ChunkTexture {
protected final byte[] data = new byte[Chunk.X_MAX * Chunk.Z_MAX * 3];
protected transient boolean writeable = true;

/**
* Create new texture
Expand All @@ -46,68 +48,85 @@ public ChunkTexture(ChunkTexture ct) {
}

/**
* Set color value at (x, z).
*
* @param frgb RGB color components to set
*/
public void set(int x, int z, float[] frgb) {
int index = (x + z * Chunk.X_MAX) * 3;
data[index] = ColorUtil.RGBComponentFromLinear(frgb[0]);
data[index + 1] = ColorUtil.RGBComponentFromLinear(frgb[1]);
data[index + 2] = ColorUtil.RGBComponentFromLinear(frgb[2]);
}

/**
* @return RGB color components at (x, z)
* Load a chunk texture from an input stream.
*/
public float[] get(int x, int z) {
float[] result = new float[3];
int index = (x + z * Chunk.X_MAX) * 3;
result[0] = ColorUtil.RGBComponentToLinear(data[index]);
result[1] = ColorUtil.RGBComponentToLinear(data[index + 1]);
result[2] = ColorUtil.RGBComponentToLinear(data[index + 2]);
return result;
public static ChunkTexture load(DataInputStream in) throws IOException {
ChunkTexture tex = new ChunkTexture();
for (int i = 0; i < Chunk.X_MAX * Chunk.Z_MAX; i++) {
tex.data[i*3 + 0] = ColorUtil.RGBComponentFromLinear(in.readFloat());
tex.data[i*3 + 1] = ColorUtil.RGBComponentFromLinear(in.readFloat());
tex.data[i*3 + 2] = ColorUtil.RGBComponentFromLinear(in.readFloat());
}
return tex;
}

/**
* Write this chunk texture to an output stream.
*
* @throws IOException
*/
public void store(DataOutputStream out) throws IOException {
for (int i = 0; i < Chunk.X_MAX * Chunk.Z_MAX; ++i) {
for (int i = 0; i < Chunk.X_MAX * Chunk.Z_MAX; i++) {
out.writeFloat(ColorUtil.RGBComponentToLinear(data[i*3]));
out.writeFloat(ColorUtil.RGBComponentToLinear(data[i*3 + 1]));
out.writeFloat(ColorUtil.RGBComponentToLinear(data[i*3 + 2]));
}
}

/**
* Load a chunk texture from an input stream.
*
* @return The loaded texture
* @throws IOException
* Make this chunk texture read-only.
*/
public static ChunkTexture load(DataInputStream in) throws IOException {
ChunkTexture texture = new ChunkTexture();
for (int i = 0; i < Chunk.X_MAX * Chunk.Z_MAX; ++i) {
texture.data[i*3] = ColorUtil.RGBComponentFromLinear(in.readFloat());
texture.data[i*3 + 1] = ColorUtil.RGBComponentFromLinear(in.readFloat());
texture.data[i*3 + 2] = ColorUtil.RGBComponentFromLinear(in.readFloat());
public void makeReadOnly() {
writeable = false;
}

/**
* Intern this chunk texture.
*/
public ChunkTexture intern(Interner<ChunkTexture> interner) {
this.makeReadOnly();
return interner.intern(this);
}

/**
* Set the color value at (x, z).
* @param frgb RGB color components to set
* @return The chunk texture with the color value set
*/
public ChunkTexture set(int x, int z, float[] frgb) {
if (writeable) {
int index = (x + z * Chunk.X_MAX) * 3;
data[index + 0] = ColorUtil.RGBComponentFromLinear(frgb[0]);
data[index + 1] = ColorUtil.RGBComponentFromLinear(frgb[1]);
data[index + 2] = ColorUtil.RGBComponentFromLinear(frgb[2]);
return this;
} else {
ChunkTexture tex = new ChunkTexture(this);
return tex.set(x, z, frgb);
}
return texture;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ChunkTexture that = (ChunkTexture) o;
return Arrays.equals(data, that.data);
/**
* Get the color value at (x, z).
* @return RGB color components at (x, z)
*/
public float[] get(int x, int z) {
float[] result = new float[3];
int index = (x + z * Chunk.X_MAX) * 3;
result[0] = ColorUtil.RGBComponentToLinear(data[index + 0]);
result[1] = ColorUtil.RGBComponentToLinear(data[index + 1]);
result[2] = ColorUtil.RGBComponentToLinear(data[index + 2]);
return result;
}

@Override
public int hashCode() {
return Arrays.hashCode(data);
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof ChunkTexture)) return false;
ChunkTexture that = (ChunkTexture) o;
return Arrays.equals(data, that.data);
}
}
Loading
Loading