Last active
February 9, 2016 01:49
-
-
Save tterrag1098/d013780e7d9c3d0f8a06 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package team.chisel.client.render; | |
import java.awt.geom.Rectangle2D; | |
import java.util.Arrays; | |
import java.util.List; | |
import javax.annotation.Nullable; | |
import lombok.Getter; | |
import lombok.RequiredArgsConstructor; | |
import lombok.Setter; | |
import lombok.ToString; | |
import lombok.Value; | |
import net.minecraft.client.Minecraft; | |
import net.minecraft.client.renderer.block.model.BakedQuad; | |
import net.minecraft.client.renderer.texture.TextureAtlasSprite; | |
import net.minecraft.client.renderer.texture.TextureMap; | |
import net.minecraft.client.renderer.vertex.VertexFormat; | |
import net.minecraft.client.renderer.vertex.VertexFormatElement; | |
import net.minecraft.client.renderer.vertex.VertexFormatElement.EnumUsage; | |
import net.minecraft.util.EnumFacing; | |
import net.minecraftforge.client.model.pipeline.IVertexConsumer; | |
import org.apache.commons.lang3.tuple.Pair; | |
import org.lwjgl.util.vector.Vector; | |
import org.lwjgl.util.vector.Vector2f; | |
import org.lwjgl.util.vector.Vector3f; | |
import com.google.common.base.Optional; | |
import com.google.common.collect.ListMultimap; | |
import com.google.common.collect.Lists; | |
import com.google.common.collect.MultimapBuilder; | |
@ToString(of = { "verts", "uvs" }) | |
public class Quad { | |
@Value | |
public static class Vertex { | |
Vector3f pos; | |
Vector2f uvs; | |
} | |
@RequiredArgsConstructor | |
public static class UVs { | |
private static final TextureAtlasSprite BASE = Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite(TextureMap.LOCATION_MISSING_TEXTURE.toString()); | |
private static final float BASE_WIDTH = BASE.getMaxU() - BASE.getMinU(), BASE_HEIGHT = BASE.getMaxV() - BASE.getMinV(); | |
@Getter | |
private final TextureAtlasSprite sprite; | |
@Getter | |
final float minU, minV, maxU, maxV; | |
private UVs(Vector2f... data) { | |
this(BASE, data); | |
} | |
private UVs(TextureAtlasSprite sprite, Vector2f... data) { | |
this.sprite = sprite; | |
float minU = Float.MAX_VALUE; | |
float minV = Float.MAX_VALUE; | |
float maxU = 0, maxV = 0; | |
for (Vector2f v : data) { | |
minU = Math.min(minU, v.x); | |
minV = Math.min(minV, v.y); | |
maxU = Math.max(maxU, v.x); | |
maxV = Math.max(maxV, v.y); | |
} | |
this.minU = minU; | |
this.minV = minV; | |
this.maxU = maxU; | |
this.maxV = maxV; | |
} | |
public UVs transform(TextureAtlasSprite other) { | |
float scaleU = BASE_WIDTH / (other.getMaxU() - other.getMinU()); | |
float scaleV = BASE_HEIGHT / (other.getMaxV() - other.getMinV()); | |
float startU = (minU - BASE.getMinU()) * scaleU; | |
float startV = (minV - BASE.getMinV()) * scaleV; | |
float endU = (BASE.getMaxU() - maxU) * scaleU; | |
float endV = (BASE.getMaxV() - maxV) * scaleV; | |
return new UVs(other, startU + other.getMinU(), startV + other.getMinV(), other.getMaxU() - endU, other.getMaxV() - endV); | |
} | |
public UVs normalize() { | |
return new UVs(sprite, normalize(sprite.getMinU(), sprite.getMaxU(), this.minU), normalize(sprite.getMinV(), sprite.getMaxV(), this.minV), normalize(sprite.getMinU(), sprite.getMaxU(), this.maxU), | |
normalize(sprite.getMinV(), sprite.getMaxV(), this.maxV)); | |
} | |
private float normalize(float min, float max, float x) { | |
return (x - min) / (max - min); | |
} | |
} | |
private final Vector3f[] verts; | |
@Getter | |
private final UVs uvs; | |
private final Builder builder; | |
private Quad(Vector3f[] verts, Vector2f[] uvs, Builder builder) { | |
this.verts = verts; | |
this.uvs = new UVs(uvs); | |
this.builder = builder; | |
} | |
public void compute() { | |
} | |
public Quad[] subdivide(int count) { | |
List<Quad> rects = Lists.newArrayList(); | |
Pair<Quad, Optional<Quad>> firstDivide = divide(this, false); | |
rects.add(firstDivide.getLeft()); | |
if (firstDivide.getRight().isPresent()) { | |
Quad split = firstDivide.getRight().get(); | |
rects.add(split); | |
Pair<Quad, Optional<Quad>> secondDivide = divide(split, true); | |
rects.add(secondDivide.getLeft()); | |
if (secondDivide.getRight().isPresent()) { | |
rects.add(secondDivide.getRight().get()); | |
} | |
} | |
return rects.toArray(new Quad[rects.size()]); | |
} | |
@Nullable | |
private Pair<Quad, Optional<Quad>> divide(Quad quad, boolean vertical) { | |
float min, max; | |
UVs uvs = quad.getUvs().normalize(); | |
if (vertical) { | |
min = uvs.minV; | |
max = uvs.maxV; | |
} else { | |
min = uvs.minU; | |
max = uvs.maxU; | |
} | |
if (min < 0.5 && max > 0.5) { | |
UVs first = new UVs(uvs.getSprite(), uvs.minU, uvs.minV, vertical ? uvs.maxU : 0.5f, vertical ? 0.5f : uvs.maxV); | |
UVs second = new UVs(uvs.getSprite(), vertical ? uvs.minU : 0.5f, vertical ? 0.5f : uvs.minV, uvs.maxU, uvs.maxV); | |
} else { | |
return Pair.of(quad, Optional.absent()); | |
} | |
} | |
public static Quad from(BakedQuad baked, VertexFormat fmt) { | |
Builder b = new Builder(fmt); | |
baked.pipe(b); | |
return b.build(); | |
} | |
@RequiredArgsConstructor | |
public static class Builder implements IVertexConsumer { | |
@Getter | |
private final VertexFormat vertexFormat; | |
@Setter | |
private int quadTint; | |
@Setter | |
private EnumFacing quadOrientation; | |
@Override | |
public void setQuadColored() {} | |
private ListMultimap<VertexFormatElement.EnumUsage, float[]> data = MultimapBuilder.enumKeys(EnumUsage.class).arrayListValues().build(); | |
@Override | |
public void put(int element, float... data) { | |
if (element == 2) { | |
System.out.println(Arrays.toString(data)); | |
} | |
float[] copy = new float[data.length]; | |
System.arraycopy(data, 0, copy, 0, data.length); | |
this.data.put(vertexFormat.getElement(element).getUsage(), copy); | |
} | |
public Quad build() { | |
Vector3f[] verts = fromData(data.get(EnumUsage.POSITION), 3); | |
Vector2f[] uvs = fromData(data.get(EnumUsage.UV), 2); | |
return new Quad(verts, uvs, this); | |
} | |
@SuppressWarnings("unchecked") | |
private <T extends Vector> T[] fromData(List<float[]> data, int size) { | |
Vector[] ret = size == 2 ? new Vector2f[data.size()] : new Vector3f[data.size()]; | |
for (int i = 0; i < data.size(); i++) { | |
ret[i] = size == 2 ? new Vector2f(data.get(i)[0], data.get(i)[1]) : new Vector3f(data.get(i)[0], data.get(i)[1], data.get(i)[2]); | |
} | |
return (T[]) ret; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment