Skip to content

Commit

Permalink
De-duplicate constants, improve Javadoc, fix scaling
Browse files Browse the repository at this point in the history
- De-duplicate shared constants relating to texture sizes
- Improve some Javadoc formatting & use @link and @see more
- Fix scaling issues for some textures
  • Loading branch information
NeRdTheNed committed Sep 26, 2021
1 parent ec2973a commit 85893d8
Show file tree
Hide file tree
Showing 11 changed files with 109 additions and 113 deletions.
2 changes: 2 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ javadoc {
options.memberLevel = JavadocMemberLevel.PRIVATE
// Add custom "todo" tag
options.tags = ["todo:a:To Do:"]
// Ensures that the encoding of javadoc source files is set to UTF-8
options.encoding = "UTF-8"
}

tasks.withType(JavaCompile) {
Expand Down
29 changes: 16 additions & 13 deletions src/main/java/mcTextureGen/generators/AbstractLavaGenerator.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@

/**
* Although this class is called AbstractLavaGenerator, it's pretty much just a lava texture generator,
* minus an implementation of setABGR(). Classes that extend this class must therefore implement setABGR().
* minus an implementation of {@link AbstractLiquidGenerator#setABGR(byte[], float, int)}.
* Classes that extend this class must therefore implement {@link AbstractLiquidGenerator#setABGR(byte[], float, int)}.
* This is mainly due to the fact that this is one of the only differences between Classic 0.0.19a lava textures
* and Classic 0.0.22a lava textures (the other difference being how pixels are clamped).
* This is a non-deterministic generator.
*
* @todo clean up, refactor
* @see AbstractLiquidGenerator#clampCurrentPixelIntensity(float)
* @see AbstractLiquidGenerator#setABGR(byte[], float, int)
*/
public abstract class AbstractLavaGenerator extends AbstractLiquidGenerator {

Expand All @@ -27,38 +30,38 @@ protected AbstractLavaGenerator(String generatorName) {
* @todo better Javadoc
*/
public final void generateLiquidTexture(final float[] liquidImagePrevious, final float[] liquidImageCurrent, final float[] liquidIntensity, final float[] liquidIntensityIntensity) {
for (int currentLavaX = 0; currentLavaX < LIQUID_IMAGE_SIZE; ++currentLavaX) {
for (int currentLavaY = 0; currentLavaY < LIQUID_IMAGE_SIZE; ++currentLavaY) {
for (int currentLavaX = 0; currentLavaX < STANDARD_IMAGE_SIZE; ++currentLavaX) {
for (int currentLavaY = 0; currentLavaY < STANDARD_IMAGE_SIZE; ++currentLavaY) {
float localPreviousIntensity = 0.0F;
// Side note: 1.2F is the value originally used, despite it being "incorrect" to use a float here
// (would usually be a double, as 1.2F gets promoted to double at compile time, due to Math.sin returning a double).
// This was likely due to programmer oversight when writing this code.
// TL;DR: I meant to type 1.2F, Notch probably didn't.
final int ySin = (int) (Math.sin((currentLavaY * Math.PI * 2.0D) / LIQUID_IMAGE_SIZE) * 1.2F);
final int xCos = (int) (Math.sin((currentLavaX * Math.PI * 2.0D) / LIQUID_IMAGE_SIZE) * 1.2F);
final int ySin = (int) (Math.sin((currentLavaY * Math.PI * 2.0D) / STANDARD_IMAGE_SIZE) * 1.2F);
final int xCos = (int) (Math.sin((currentLavaX * Math.PI * 2.0D) / STANDARD_IMAGE_SIZE) * 1.2F);

// Iterates through (x - 1, y - 1) to (x + 1, y + 1).
// For each x and y value, it accumulates the previous pixel value at (x + ySin, y + xCos) into localPixelIntensity.
for (int localLavaX = currentLavaX - 1; localLavaX <= (currentLavaX + 1); ++localLavaX) {
for (int localLavaY = currentLavaY - 1; localLavaY <= (currentLavaY + 1); ++localLavaY) {
// Restrict the adjusted coordinates to be in range of the maximum valid coordinate (liquidImageSize).
// If a coordinate is out of range, it wraps to be in range.
final int localLavaXWrapped = (localLavaX + ySin) & LIQUID_IMAGE_MASK;
final int localLavaYWrapped = (localLavaY + xCos) & LIQUID_IMAGE_MASK;
localPreviousIntensity += liquidImagePrevious[localLavaXWrapped + (localLavaYWrapped * LIQUID_IMAGE_SIZE)];
final int localLavaXWrapped = (localLavaX + ySin) & STANDARD_IMAGE_SIZE_BITMASK;
final int localLavaYWrapped = (localLavaY + xCos) & STANDARD_IMAGE_SIZE_BITMASK;
localPreviousIntensity += liquidImagePrevious[localLavaXWrapped + (localLavaYWrapped * STANDARD_IMAGE_SIZE)];
}
}

final int currentLavaOffset = currentLavaX + (currentLavaY * LIQUID_IMAGE_SIZE);
final int currentLavaOffset = currentLavaX + (currentLavaY * STANDARD_IMAGE_SIZE);
// A manually unrolled loop iterating from (y, x) to (y + 1, x + 1). Wraps coordinates in the same way as above.
// For each x and y value, it accumulates the additional pixel intensity into localLiquidIntensity.
// I don't want to change floating point semantics, so I'm not re-rolling this for now.
// This was originally inlined as part of the next line of code. I un-inlined it for readability.
// I'm pretty sure this shouldn't change anything, but I should probably figure out how floats work in Java to verify that.
final float localLiquidIntensity = liquidIntensity[(currentLavaX & LIQUID_IMAGE_MASK) + ((currentLavaY & LIQUID_IMAGE_MASK) * LIQUID_IMAGE_SIZE)]
+ liquidIntensity[(currentLavaX & LIQUID_IMAGE_MASK) + (((currentLavaY + 1) & LIQUID_IMAGE_MASK) * LIQUID_IMAGE_SIZE)]
+ liquidIntensity[((currentLavaX + 1) & LIQUID_IMAGE_MASK) + ((currentLavaY & LIQUID_IMAGE_MASK) * LIQUID_IMAGE_SIZE)]
+ liquidIntensity[((currentLavaX + 1) & LIQUID_IMAGE_MASK) + (((currentLavaY + 1) & LIQUID_IMAGE_MASK) * LIQUID_IMAGE_SIZE)];
final float localLiquidIntensity = liquidIntensity[(currentLavaX & STANDARD_IMAGE_SIZE_BITMASK) + ((currentLavaY & STANDARD_IMAGE_SIZE_BITMASK) * STANDARD_IMAGE_SIZE)]
+ liquidIntensity[(currentLavaX & STANDARD_IMAGE_SIZE_BITMASK) + (((currentLavaY + 1) & STANDARD_IMAGE_SIZE_BITMASK) * STANDARD_IMAGE_SIZE)]
+ liquidIntensity[((currentLavaX + 1) & STANDARD_IMAGE_SIZE_BITMASK) + ((currentLavaY & STANDARD_IMAGE_SIZE_BITMASK) * STANDARD_IMAGE_SIZE)]
+ liquidIntensity[((currentLavaX + 1) & STANDARD_IMAGE_SIZE_BITMASK) + (((currentLavaY + 1) & STANDARD_IMAGE_SIZE_BITMASK) * STANDARD_IMAGE_SIZE)];
// localLiquidIntensity is divided by 4.0F, because it samples from 4 points.
// localPreviousIntensity is divided by 10.0F, because the whims of other programmers are inscrutable.
// You'd expect it to be 9.0F based on the previous bit of logic. Maybe someone made an off-by-one error? Or rounded up from 9.9? TODO investigate
Expand Down
21 changes: 6 additions & 15 deletions src/main/java/mcTextureGen/generators/AbstractLiquidGenerator.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,6 @@
*/
public abstract class AbstractLiquidGenerator extends AbstractTextureGenerator {

/** The size of a liquid image in bits. */
private static final int LIQUID_IMAGE_BITS = 4;

/** A bit mask of the amount of bits in a liquid image. */
static final int LIQUID_IMAGE_MASK = ~(-1 << LIQUID_IMAGE_BITS);

/** The size of a liquid image in pixels. */
static final int LIQUID_IMAGE_SIZE = LIQUID_IMAGE_MASK + 1;

/** The name of this liquid texture generator. */
private final String generatorName;

Expand Down Expand Up @@ -97,21 +88,21 @@ public final TextureGroup[] getTextureGroups() {
*/
private final TextureGroup liquidTextures() {
rand = getRandom();
float[] liquidImagePrevious = new float[LIQUID_IMAGE_SIZE * LIQUID_IMAGE_SIZE];
float[] liquidImageCurrent = new float[LIQUID_IMAGE_SIZE * LIQUID_IMAGE_SIZE];
final float[] liquidIntensity = new float[LIQUID_IMAGE_SIZE * LIQUID_IMAGE_SIZE];
final float[] liquidIntensityIntensity = new float[LIQUID_IMAGE_SIZE * LIQUID_IMAGE_SIZE];
float[] liquidImagePrevious = new float[STANDARD_IMAGE_SIZE * STANDARD_IMAGE_SIZE];
float[] liquidImageCurrent = new float[STANDARD_IMAGE_SIZE * STANDARD_IMAGE_SIZE];
final float[] liquidIntensity = new float[STANDARD_IMAGE_SIZE * STANDARD_IMAGE_SIZE];
final float[] liquidIntensityIntensity = new float[STANDARD_IMAGE_SIZE * STANDARD_IMAGE_SIZE];
final BufferedImage[] liquidImages = new BufferedImage[nonDeterministicFrames];

for (int currentFrame = 0; currentFrame < nonDeterministicFrames; currentFrame++) {
generateLiquidTexture(liquidImagePrevious, liquidImageCurrent, liquidIntensity, liquidIntensityIntensity);
final float[] liquidImageCurrentTemp = liquidImageCurrent;
liquidImageCurrent = liquidImagePrevious;
liquidImagePrevious = liquidImageCurrentTemp;
final BufferedImage currentLiquidImage = new BufferedImage(LIQUID_IMAGE_SIZE, LIQUID_IMAGE_SIZE, BufferedImage.TYPE_4BYTE_ABGR);
final BufferedImage currentLiquidImage = new BufferedImage(STANDARD_IMAGE_SIZE, STANDARD_IMAGE_SIZE, BufferedImage.TYPE_4BYTE_ABGR);
final byte[] imageByteData = ((DataBufferByte) currentLiquidImage.getRaster().getDataBuffer()).getData();

for (int currentPixel = 0; currentPixel < (LIQUID_IMAGE_SIZE * LIQUID_IMAGE_SIZE); ++currentPixel) {
for (int currentPixel = 0; currentPixel < (STANDARD_IMAGE_SIZE * STANDARD_IMAGE_SIZE); ++currentPixel) {
final float currentPixelIntensity = clampCurrentPixelIntensity(liquidImagePrevious[currentPixel]);
final int imageOffset = currentPixel * 4;
setABGR(imageByteData, currentPixelIntensity, imageOffset);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,17 @@ public abstract class AbstractTextureGenerator {
/** True if platform dependent texture generators should generate platform dependent textures. */
protected static boolean shouldGeneratePlatformDependentTextures = false;

// Image size constants

/** A convenience variable to generate larger textures. Must be a power of two, or one. */
static final int STANDARD_IMAGE_SIZE_MULTIPLIER = 1;

/** The size of a standard image in pixels. */
static final int STANDARD_IMAGE_SIZE = 16 * STANDARD_IMAGE_SIZE_MULTIPLIER;

/** A bit mask of the size of a standard image. */
static final int STANDARD_IMAGE_SIZE_BITMASK = STANDARD_IMAGE_SIZE - 1;

/*
* Constants to determine the size of the sin and cos lookup tables.
* Adapted from https://jvm-gaming.org/t/fast-math-sin-cos-lookup-tables/36660.
Expand Down Expand Up @@ -92,7 +103,7 @@ public static void setNonDeterministicFrames(int nonDeterministicFrames) {
}

/**
* Sets the seed used by getRandom().
* Sets the seed used by {@link #getRandom()}.
*
* @param randomSeed the new random seed
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,28 +20,28 @@ public Classic19aWaterGenerator() {
*/
public void generateLiquidTexture(final float[] liquidImagePrevious, final float[] liquidImageCurrent, final float[] liquidIntensity, final float[] liquidIntensityIntensity) {
// Generate the image pixel values
for (int currentWaterX = 0; currentWaterX < LIQUID_IMAGE_SIZE; ++currentWaterX) {
for (int currentWaterY = 0; currentWaterY < LIQUID_IMAGE_SIZE; ++currentWaterY) {
for (int currentWaterX = 0; currentWaterX < STANDARD_IMAGE_SIZE; ++currentWaterX) {
for (int currentWaterY = 0; currentWaterY < STANDARD_IMAGE_SIZE; ++currentWaterY) {
float localPixelIntensity = 0.0F;

// Iterates through (x - 1, y) to (x + 1, y), and accumulates the previous pixel value at each location into localPixelIntensity.
// Only iterating over the x values causes the water to generate horizontal "stripes", as the y value does not change.
for (int localWaterX = currentWaterX - 1; localWaterX <= (currentWaterX + 1); ++localWaterX) {
// Restrict the adjusted x coordinate to be in range of the maximum valid coordinate (liquidImageSize).
// Restrict the adjusted x coordinate to be in range of the maximum valid coordinate (STANDARD_IMAGE_SIZE).
// If the x coordinate is out of range, it wraps to be in range.
localPixelIntensity += liquidImagePrevious[(localWaterX & LIQUID_IMAGE_MASK) + (currentWaterY * LIQUID_IMAGE_SIZE)];
localPixelIntensity += liquidImagePrevious[(localWaterX & STANDARD_IMAGE_SIZE_BITMASK) + (currentWaterY * STANDARD_IMAGE_SIZE)];
}

final int currentWaterOffset = currentWaterX + (currentWaterY * LIQUID_IMAGE_SIZE);
final int currentWaterOffset = currentWaterX + (currentWaterY * STANDARD_IMAGE_SIZE);
// localPixelIntensity is divided by 3.3F, because it samples from 3 x points.
liquidImageCurrent[currentWaterOffset] = (localPixelIntensity / 3.3F) + (liquidIntensity[currentWaterOffset] * 0.8F);
}
}

// Update liquidIntensity and liquidIntensityIntensity
for (int currentWaterX = 0; currentWaterX < LIQUID_IMAGE_SIZE; ++currentWaterX) {
for (int currentWaterY = 0; currentWaterY < LIQUID_IMAGE_SIZE; ++currentWaterY) {
final int currentWaterOffset = currentWaterX + (currentWaterY * LIQUID_IMAGE_SIZE);
for (int currentWaterX = 0; currentWaterX < STANDARD_IMAGE_SIZE; ++currentWaterX) {
for (int currentWaterY = 0; currentWaterY < STANDARD_IMAGE_SIZE; ++currentWaterY) {
final int currentWaterOffset = currentWaterX + (currentWaterY * STANDARD_IMAGE_SIZE);
liquidIntensity[currentWaterOffset] += liquidIntensityIntensity[currentWaterOffset] * 0.05F;

if (liquidIntensity[currentWaterOffset] < 0.0F) {
Expand Down
21 changes: 10 additions & 11 deletions src/main/java/mcTextureGen/generators/FireGenerator.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,11 @@
*/
public final class FireGenerator extends AbstractTextureGenerator {

/** A convenience variable to generate larger fire textures with. */
private static final int FIRE_MULTI = 1;

/** How wide the fire texture is. */
private static final int FIRE_TEXTURE_WIDTH = 16 * FIRE_MULTI;
private static final int FIRE_TEXTURE_WIDTH = 16 * STANDARD_IMAGE_SIZE_MULTIPLIER;

/** How high the fire texture is. */
private static final int FIRE_TEXTURE_HEIGHT = 20 * FIRE_MULTI;
private static final int FIRE_TEXTURE_HEIGHT = 20 * STANDARD_IMAGE_SIZE_MULTIPLIER;

/** How many pixels left to sample from when generating the texture. */
private static final int SAMPLE_X_LEFT = 1;
Expand All @@ -43,7 +40,7 @@ public final class FireGenerator extends AbstractTextureGenerator {
*/

/** The staring value for the "sample counter". */
private static final int SAMPLE_COUNTER_START = 18 * FIRE_MULTI;
private static final int SAMPLE_COUNTER_START = 18 * STANDARD_IMAGE_SIZE_MULTIPLIER;

/** How many times the "sample counter" would increment. */
private static final int SAMPLE_COUNTER_ITERATIONS = (SAMPLE_X_LEFT + SAMPLE_SELF + SAMPLE_X_RIGHT) * (SAMPLE_Y_DOWN + SAMPLE_SELF + SAMPLE_Y_UP);
Expand All @@ -53,16 +50,18 @@ public final class FireGenerator extends AbstractTextureGenerator {

/**
* WTFLOAT is a very strange constant. I felt the name was appropriate, given how hard it was to pin down.
* Earlier versions of Minecraft define this as 1.06F. Later versions defined it as 1.0600001F.
* Earlier versions of Minecraft define this as 1.06F. Later versions defined it as 1.0600001F.
* This is the current method I've settled on to determine the scaled value of WTFLOAT.
* If fireMulti is 1, it results in 1.06F.
* If {@link AbstractTextureGenerator#STANDARD_IMAGE_SIZE_MULTIPLIER} is
* {@value mcTextureGen.generators.AbstractTextureGenerator#STANDARD_IMAGE_SIZE_MULTIPLIER},
* it results in {@value} (the same as earlier versions of Minecraft).
*/
private static final float WTFLOAT = 1.0F + (SAMPLE_SELF * 0.01F) + (((SAMPLE_COUNTER_ITERATIONS - SAMPLE_SELF) * 0.01F) / FIRE_MULTI);
private static final float WTFLOAT = 1.0F + (SAMPLE_SELF * 0.01F) + (((SAMPLE_COUNTER_ITERATIONS - SAMPLE_SELF) * 0.01F) / STANDARD_IMAGE_SIZE_MULTIPLIER);

/**
* Used during fire texture generation to compensate for sampling multiple pixels.
* @todo It's rumored that some versions of pocket edition have this as 25.2?
* If that's true, removing " + (SAMPLE_SELF * 0.01F)" from WTFLOAT might simulate this.
* If that's true, removing " + (SAMPLE_SELF * 0.01F)" from {@link #WTFLOAT} might simulate this.
*/
private static final float DIV_PIXEL_INTENSITY = SAMPLE_COUNTER_END * WTFLOAT;

Expand Down Expand Up @@ -100,7 +99,7 @@ private static TextureGroup fireTextures() {
}

// Randomize bottom row of pixels
fireImageCurrent[fireX + ((FIRE_TEXTURE_HEIGHT - 1) * FIRE_TEXTURE_WIDTH)] = (float)((rand.nextDouble() * rand.nextDouble() * rand.nextDouble() * (3 + FIRE_MULTI)) + (rand.nextDouble() * 0.1F) + 0.2F);
fireImageCurrent[fireX + ((FIRE_TEXTURE_HEIGHT - 1) * FIRE_TEXTURE_WIDTH)] = (float)((rand.nextDouble() * rand.nextDouble() * rand.nextDouble() * (3 + STANDARD_IMAGE_SIZE_MULTIPLIER)) + (rand.nextDouble() * 0.1F) + 0.2F);
}

final float[] fireImageCurrentTemp = fireImageCurrent;
Expand Down
Loading

0 comments on commit 85893d8

Please sign in to comment.