package codechicken.lib.vec; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import java.util.ArrayList; import java.util.Iterator; public class TransformationList extends Transformation { private ArrayList<Transformation> transformations = new ArrayList<Transformation>(); private Matrix4 mat; public TransformationList(Transformation... transforms) { for (Transformation t : transforms) { if (t instanceof TransformationList) { transformations.addAll(((TransformationList) t).transformations); } else { transformations.add(t); } } compact(); } public Matrix4 compile() { if (mat == null) { mat = new Matrix4(); for (int i = transformations.size() - 1; i >= 0; i--) { transformations.get(i).apply(mat); } } return mat; } /** * Returns a global space matrix as opposed to an object space matrix (reverse application order) * * @return */ public Matrix4 reverseCompile() { Matrix4 mat = new Matrix4(); for (Transformation t : transformations) { t.apply(mat); } return mat; } @Override public void apply(Vector3 vec) { if (mat != null) { mat.apply(vec); } else { for (int i = 0; i < transformations.size(); i++) { transformations.get(i).apply(vec); } } } @Override public void applyN(Vector3 normal) { if (mat != null) { mat.applyN(normal); } else { for (int i = 0; i < transformations.size(); i++) { transformations.get(i).applyN(normal); } } } @Override public void apply(Matrix4 mat) { mat.multiply(compile()); } @Override public TransformationList with(Transformation t) { if (t.isRedundant()) { return this; } mat = null;//matrix invalid if (t instanceof TransformationList) { transformations.addAll(((TransformationList) t).transformations); } else { transformations.add(t); } compact(); return this; } public TransformationList prepend(Transformation t) { if (t.isRedundant()) { return this; } mat = null;//matrix invalid if (t instanceof TransformationList) { transformations.addAll(0, ((TransformationList) t).transformations); } else { transformations.add(0, t); } compact(); return this; } private void compact() { ArrayList<Transformation> newList = new ArrayList<Transformation>(transformations.size()); Iterator<Transformation> iterator = transformations.iterator(); Transformation prev = null; while (iterator.hasNext()) { Transformation t = iterator.next(); if (t.isRedundant()) { continue; } if (prev != null) { Transformation m = prev.merge(t); if (m == null) { newList.add(prev); } else if (m.isRedundant()) { t = null; } else { t = m; } } prev = t; } if (prev != null) { newList.add(prev); } if (newList.size() < transformations.size()) { transformations = newList; mat = null; } if (transformations.size() > 3 && mat == null) { compile(); } } @Override public boolean isRedundant() { return transformations.size() == 0; } @Override @SideOnly(Side.CLIENT) public void glApply() { for (int i = transformations.size() - 1; i >= 0; i--) { transformations.get(i).glApply(); } } @Override public Transformation inverse() { TransformationList rev = new TransformationList(); for (int i = transformations.size() - 1; i >= 0; i--) { rev.with(transformations.get(i).inverse()); } return rev; } @Override public String toString() { String s = ""; for (Transformation t : transformations) { s += "\n" + t.toString(); } return s.trim(); } }