package io.github.moulberry.notenoughupdates.cosmetics; import net.minecraft.block.Block; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.WorldRenderer; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.util.BlockPos; import net.minecraft.util.MathHelper; import org.lwjgl.input.Keyboard; import org.lwjgl.opengl.GL11; import org.lwjgl.util.vector.Vector2f; import org.lwjgl.util.vector.Vector3f; import java.nio.FloatBuffer; import java.util.ArrayList; import java.util.HashMap; import java.util.List; public class CapeNode { private static final NEUCape.Direction[] cardinals = new NEUCape.Direction[]{NEUCape.Direction.UP, NEUCape.Direction.RIGHT, NEUCape.Direction.DOWN, NEUCape.Direction.LEFT}; public Vector3f position; public Vector3f lastPosition = new Vector3f(); public Vector3f renderPosition = new Vector3f(); public final Vector3f[] oldRenderPosition = new Vector3f[5]; public final Vector3f velocity = new Vector3f(); public Vector3f normal = null; public Vector3f sideNormal = null; public boolean fixed = false; public static final int DRAW_MASK_FRONT = 0b1; public static final int DRAW_MASK_BACK = 0b10; public static final int DRAW_MASK_SIDES = 0b100; public HashMap neighbors = new HashMap<>(); public float texU = 0; public float texV = 0; public float horzDistMult = 2f; public float vertDistMult = 0.5f; public float horzSideTexU = 0; public float horzSideTexVTop = 0; public float vertSideTexU = 0; public float vertSideTexVTop = 0; public final float gravity = 0.1f; public final float resistance = 0.5f; public static final int FLOAT_NUM = 20; public CapeNode(float x, float y, float z) { this.position = new Vector3f(x, y, z); } private List getConstaints() { List constaints = new ArrayList<>(); for(NEUCape.Direction cardinal : cardinals) { for(int i=1; i<=2; i++) { NEUCape.Offset offset = new NEUCape.Offset(cardinal, i); CapeNode other = neighbors.get(offset); if(other != null) { int iOffset = offset.getXOffset() + NEUCape.HORZ_NODES * offset.getYOffset(); constaints.add(new Vector2f(iOffset, i*NEUCape.targetDist*(cardinal.yOff==0?horzDistMult:vertDistMult))); } } } return constaints; } public void loadIntoBuffer(FloatBuffer buffer) { loadVec3IntoBuffer(buffer, position); List containts = getConstaints(); buffer.put(containts.size()); for(int i=0; i<8; i++) { if(i < containts.size()) { loadVec2IntoBuffer(buffer, containts.get(i)); } else { loadVec2IntoBuffer(buffer, new Vector2f()); } } } public void readFromBuffer(FloatBuffer buffer) { readVec3FromBuffer(buffer, position); buffer.position(buffer.position()+17); } private void readVec3FromBuffer(FloatBuffer buffer, Vector3f vec) { vec.x = buffer.get(); vec.y = buffer.get(); vec.z = buffer.get(); } private void loadVec2IntoBuffer(FloatBuffer buffer, Vector2f vec) { buffer.put(vec.x); buffer.put(vec.y); } private void loadVec3IntoBuffer(FloatBuffer buffer, Vector3f vec) { buffer.put(vec.x); buffer.put(vec.y); buffer.put(vec.z); } public void update() { if(!fixed) { velocity.y -= gravity * (resistance)/(1-resistance); float actualResistance = resistance; /*BlockPos pos = new BlockPos( MathHelper.floor_double(position.x), MathHelper.floor_double(position.y), MathHelper.floor_double(position.z)); Block block = Minecraft.getMinecraft().theWorld.getBlockState(pos).getBlock(); if(block.getMaterial().isLiquid()) { actualResistance = 0.8f; }*/ velocity.scale(1-actualResistance); Vector3f.add(position, velocity, position); } } public final CapeNode getNeighbor(NEUCape.Offset offset) { return neighbors.get(offset); } public final void setNeighbor(NEUCape.Offset offset, CapeNode node) { neighbors.put(offset, node); } public void applyForce(float dX, float dY, float dZ) { velocity.x += dX; velocity.y += dY; velocity.z += dZ; } public void move(float dX, float dY, float dZ) { position.x += dX; position.y += dY; position.z += dZ; lastPosition.x = position.x; lastPosition.y = position.y; lastPosition.z = position.z; } public void resetNormal() { normal = null; sideNormal = null; } public void resolveAll(float horzDistMult, boolean opt) { resolveBend(horzDistMult, opt); //resolveShear(); resolveStruct(horzDistMult, opt); } public void resolve(CapeNode other, float targetDist, float strength, boolean opt) { double dX = position.x - other.position.x; double dY = position.y - other.position.y; double dZ = position.z - other.position.z; double distSq = dX*dX + dY*dY + dZ*dZ; double factor = (distSq - targetDist*targetDist)/(40*distSq)*strength; factor = Math.max(-0.5f, factor); dX *= factor; dY *= factor; dZ *= factor; if(fixed || other.fixed) { dX *= 2; dY *= 2; dZ *= 2; } if(!fixed) { position.x -= dX; position.y -= dY; position.z -= dZ; } if(!other.fixed) { other.position.x += dX; other.position.y += dY; other.position.z += dZ; } } public void resolveStruct(float horzDistMult, boolean opt) { for(NEUCape.Direction cardinal : cardinals) { NEUCape.Offset offset = new NEUCape.Offset(cardinal, 1); CapeNode other = neighbors.get(offset); if(other != null) { resolve(other, NEUCape.targetDist*(cardinal.yOff==0?horzDistMult:1), 2f*7.5f, opt); } } } public void resolveShear(float horzDistMult, boolean opt) { for(NEUCape.Direction d : new NEUCape.Direction[]{NEUCape.Direction.DOWNLEFT, NEUCape.Direction.UPLEFT, NEUCape.Direction.DOWNRIGHT, NEUCape.Direction.DOWNLEFT}) { NEUCape.Offset o = new NEUCape.Offset(d, 1); CapeNode neighbor = getNeighbor(o); if(neighbor != null) { resolve(neighbor, 1f*NEUCape.targetDist*(d.yOff==0?horzDistMult:1f), 0.5f*7.5f, opt); } } } public void resolveBend(float horzDistMult, boolean opt) { for(NEUCape.Direction cardinal : cardinals) { NEUCape.Offset offset = new NEUCape.Offset(cardinal, 2); CapeNode other = neighbors.get(offset); if(other != null) { resolve(other, 2f*NEUCape.targetDist*(cardinal.yOff==0?horzDistMult:1), 1f*7.5f, opt); } } } public Vector3f normal() { if(normal != null) return normal; normal = new Vector3f(); for(int i=0; i