Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions chunky/src/java/se/llbit/chunky/renderer/scene/Scene.java
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,9 @@ public synchronized void loadScene(RenderContext context, String sceneName, Task
// Load the configured skymap file.
sky.reloadSkymap(context);

// Load the configured custom texture
sun.loadCustomTextures(context);

loadedWorld = EmptyWorld.INSTANCE;
if (!worldPath.isEmpty()) {
File worldDirectory = new File(worldPath);
Expand Down
30 changes: 22 additions & 8 deletions chunky/src/java/se/llbit/chunky/renderer/scene/sky/Sun.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@
import org.apache.commons.math3.util.FastMath;

import se.llbit.chunky.renderer.Refreshable;
import se.llbit.chunky.renderer.SceneIOProvider;
import se.llbit.chunky.renderer.scene.Scene;
import se.llbit.chunky.resources.Texture;
import se.llbit.chunky.renderer.scene.sky.celestialbodies.CelestialBodyType;
import se.llbit.json.JsonObject;
import se.llbit.math.QuickMath;
import se.llbit.math.Ray;
Expand Down Expand Up @@ -116,11 +117,6 @@ public class Sun implements JsonSerializable {
private static Vector3 D = new Vector3();
private static Vector3 E = new Vector3();

/**
* Sun texture
*/
public static Texture texture = new Texture();

static {
A.x = mdx[0][0] * turb + mdx[0][1];
B.x = mdx[1][0] * turb + mdx[1][1];
Expand Down Expand Up @@ -150,6 +146,8 @@ public class Sun implements JsonSerializable {

private final Refreshable scene;

private CelestialBodyType type = CelestialBodyType.DEFAULT;

/**
* Sun radius
*/
Expand Down Expand Up @@ -236,6 +234,7 @@ public void set(Sun other) {
radius = other.radius;
enableTextureModification = other.enableTextureModification;
luminosityPdf = other.luminosityPdf;
type = other.type;
importanceSampleRadius = other.importanceSampleRadius;
importanceSampleChance = other.importanceSampleChance;
initSun();
Expand Down Expand Up @@ -328,7 +327,7 @@ public boolean intersect(Ray ray) {
if (a >= 0 && a < width2) {
double b = Math.PI / 2 - FastMath.acos(ray.d.dot(sv)) + width;
if (b >= 0 && b < width2) {
texture.getColor(a / width2, b / width2, ray.color);
type.getTexture().getColor(a / width2, b / width2, ray.color);
ray.color.x *= apparentTextureBrightness.x * 10;
ray.color.y *= apparentTextureBrightness.y * 10;
ray.color.z *= apparentTextureBrightness.z * 10;
Expand All @@ -354,7 +353,7 @@ public boolean intersectDiffuse(Ray ray) {
if (a >= 0 && a < width2) {
double b = Math.PI / 2 - FastMath.acos(ray.d.dot(sv)) + width;
if (b >= 0 && b < width2) {
texture.getColor(a / width2, b / width2, ray.color);
type.getTexture().getColor(a / width2, b / width2, ray.color);
ray.color.x *= color.x * 10;
ray.color.y *= color.y * 10;
ray.color.z *= color.z * 10;
Expand Down Expand Up @@ -516,6 +515,7 @@ public void getRandomSunDirection(Ray reflected, Random random) {
importanceSamplingObj.add("radius", importanceSampleRadius);
sun.add("importanceSampling", importanceSamplingObj);
sun.add("drawTexture", drawTexture);
type.appendToConfig(sun);
return sun;
}

Expand Down Expand Up @@ -550,9 +550,15 @@ public void importFromJson(JsonObject json) {

drawTexture = json.get("drawTexture").boolValue(drawTexture);

type = CelestialBodyType.newFromJson(json);

initSun();
}

public void loadCustomTextures(SceneIOProvider ioContext) {
type.loadCustomTextures(ioContext);
}

/**
* @return sun color
*/
Expand All @@ -579,6 +585,14 @@ public boolean drawTexture() {
return drawTexture;
}

public CelestialBodyType getType() {
return type;
}

public void setType(CelestialBodyType type) {
this.type = type;
}

public double getImportanceSampleChance() { return importanceSampleChance; }

public void setImportanceSampleChance(double d) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package se.llbit.chunky.renderer.scene.sky.celestialbodies;

import se.llbit.chunky.renderer.SceneIOProvider;
import se.llbit.chunky.resources.Texture;
import se.llbit.json.JsonObject;
import se.llbit.log.Log;
import se.llbit.util.Registerable;

import java.util.HashMap;
import java.util.Map;
import java.util.function.Supplier;

public abstract class CelestialBodyType implements Registerable {
private static final String CONFIG_TYPE_KEY = "celestialBodyType";

public final static CelestialBodyType DEFAULT = new Sun();

public static final Map<String, Supplier<CelestialBodyType>> TYPES = new HashMap<>(3);
static {
TYPES.put(Sun.ID, Sun::new);
TYPES.put(Moon.ID, Moon::new);
TYPES.put(Custom.ID, Custom::new);
}

public static CelestialBodyType newFromJson(JsonObject obj) {
String typeStr = obj.get(CONFIG_TYPE_KEY).asString(Sun.ID);
Supplier<CelestialBodyType> create = TYPES.get(typeStr);
if(create == null) {
Log.warnf("Unknown celestial body type \"%s\"", typeStr);
return DEFAULT;
}
CelestialBodyType type = create.get();
type.importFromJson(obj);
return type;
}

protected void importFromJson(JsonObject obj) {}

public void appendToConfig(JsonObject obj) {
obj.add(CONFIG_TYPE_KEY, getId());
}

/**
* will be called when a scene is loaded to load associated custom textures
*/
public void loadCustomTextures(SceneIOProvider ioContext) {
}

public abstract Texture getTexture();

@Override
public String getDescription() {
return getName();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package se.llbit.chunky.renderer.scene.sky.celestialbodies;

import se.llbit.chunky.renderer.SceneIOProvider;
import se.llbit.chunky.resources.Texture;
import se.llbit.json.JsonObject;
import se.llbit.log.Log;
import se.llbit.resources.ImageLoader;

import java.io.File;
import java.io.IOException;

public class Custom extends CelestialBodyType {
public static final String ID = "CUSTOM";

@Override
public String getId() {
return ID;
}

@Override
public String getName() {
return "Custom";
}

@Override
public String getDescription() {
return "Custom celestial body texture";
}

private final Texture texture = new Texture();
private String fileName;

public Custom() {
texture.setTexture(Sun.texture);
}

@Override
protected void importFromJson(JsonObject obj) {
fileName = obj.get("customTextureFile").asString(null);
}

@Override
public void appendToConfig(JsonObject obj) {
super.appendToConfig(obj);
obj.add("customTextureFile", fileName);
}

public void loadCustomTextures(SceneIOProvider ioContext) {
if (fileName != null) {
try {
setFile(ioContext.resolveLinkedFile(fileName));
} catch (IOException ex) {
Log.error("Failed to find custom skymap file: " + fileName);
}
}
}

@Override
public Texture getTexture() {
return texture;
}

public String getFileName() {
return fileName;
}

public void setFile(File file) {
try {
texture.setTexture(ImageLoader.read(file));
} catch (IOException ex) {
Log.error("Failed to load custom skymap: " + file, ex);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package se.llbit.chunky.renderer.scene.sky.celestialbodies;

import se.llbit.chunky.resources.BitmapImage;
import se.llbit.chunky.resources.Texture;
import se.llbit.json.JsonObject;
import se.llbit.log.Log;

public class Moon extends CelestialBodyType {
public static final String ID = "MOON";

@Override
public String getId() {
return ID;
}

@Override
public String getName() {
return "Moon";
}

public enum Phase {
NEW_MOON(0, 1),
WAXING_CRESCENT(1, 1),
FIRST_QUARTER(2, 1),
WAXING_GIBBOUS(3, 1),
FULL_MOON(0, 0),
WANING_GIBBOUS(1, 0),
LAST_QUARTER(2, 0),
WANING_CRESCENT(3, 0);

final byte textureAtlasPosX, textureAtlasPosY;

Phase(int x, int y) {
textureAtlasPosX = (byte) x;
textureAtlasPosY = (byte) y;
}
}

public static final Texture textureAtlas = new Texture();
private final Texture texture = new Texture();
private Phase phase;

public Moon() {
setPhase(Phase.FULL_MOON);
}

@Override
protected void importFromJson(JsonObject obj) {
setPhase(Phase.valueOf(obj.get("moonPhase").asString(Phase.FULL_MOON.toString())));
}

@Override
public void appendToConfig(JsonObject obj) {
super.appendToConfig(obj);
obj.add("moonPhase", phase.name());
}

@Override
public Texture getTexture() {
return texture;
}

public Phase getPhase() {
return phase;
}

public void setPhase(Phase phase) {
this.phase = phase;

if (textureAtlas.getWidth() == textureAtlas.getHeight()) {
// only has 1 phase (phases atlas not found, fallback to default moon texture)
Log.info("Moon texture did not contain multiple phases");
texture.setTexture(textureAtlas);
return;
}

int textureSize = textureAtlas.getHeight() / 2;
BitmapImage phaseTexture = new BitmapImage(textureSize, textureSize);
phaseTexture.blit(
textureAtlas.getBitmap(),
0, 0,
phase.textureAtlasPosX * textureSize,
phase.textureAtlasPosY * textureSize,
(phase.textureAtlasPosX + 1) * textureSize,
(phase.textureAtlasPosY + 1) * textureSize
);
texture.setTexture(phaseTexture.rotated270());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package se.llbit.chunky.renderer.scene.sky.celestialbodies;

import se.llbit.chunky.resources.Texture;

public class Sun extends CelestialBodyType {
public static final String ID = "SUN";

@Override
public String getId() {
return ID;
}

@Override
public String getName() {
return "Sun";
}

public static final Texture texture = new Texture();

@Override
public Texture getTexture() {
return texture;
}
}
13 changes: 10 additions & 3 deletions chunky/src/java/se/llbit/chunky/resources/TexturePackLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
package se.llbit.chunky.resources;

import se.llbit.chunky.renderer.scene.PlayerModel;
import se.llbit.chunky.renderer.scene.sky.Sun;
import se.llbit.chunky.renderer.scene.sky.celestialbodies.Moon;
import se.llbit.chunky.renderer.scene.sky.celestialbodies.Sun;
import se.llbit.chunky.resources.texturepack.*;

import java.lang.reflect.Field;
Expand Down Expand Up @@ -100,9 +101,15 @@ public class TexturePackLoader {
Texture.largeTrappedChestBottomLeft, Texture.largeTrappedChestBottomRight,
Texture.largeTrappedChestBackLeft, Texture.largeTrappedChestBackRight)));
ALL_TEXTURES.put("sun", new AlternateTextures(
new SimpleTexture("assets/minecraft/textures/environment/sun", Sun.texture),// MC 1.6
new SimpleTexture("environment/sun", Sun.texture),// MC 1.5
new SimpleTexture("assets/minecraft/textures/environment/sun", Sun.texture), // MC 1.6
new SimpleTexture("environment/sun", Sun.texture), // MC 1.5
new SimpleTexture("terrain/sun", Sun.texture)));
ALL_TEXTURES.put("moon", new AlternateTextures(
new SimpleTexture("assets/minecraft/textures/environment/moon_phases", Moon.textureAtlas), // MC 1.6
new SimpleTexture("environment/moon_phases", Moon.textureAtlas), // MC 1.5
new SimpleTexture("terrain/moon_phases", Moon.textureAtlas), // fallback to non-phase texture
new SimpleTexture("environment/moon", Moon.textureAtlas), // MC 1.5
new SimpleTexture("terrain/moon", Moon.textureAtlas))); // fallback to non-phase texture
ALL_TEXTURES.put("clouds", new AlternateTextures(
new CloudsTexture("assets/minecraft/textures/environment/clouds"),
// MC 1.6
Expand Down