Updated readability of the code.
[sixth-3d.git] / src / main / java / eu / svjatoslav / sixth / e3d / math / TransformsStack.java
diff --git a/src/main/java/eu/svjatoslav/sixth/e3d/math/TransformsStack.java b/src/main/java/eu/svjatoslav/sixth/e3d/math/TransformsStack.java
new file mode 100644 (file)
index 0000000..41e1a95
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Sixth 3D engine. Author: Svjatoslav Agejenko.
+ * This project is released under Creative Commons Zero (CC0) license.
+ */
+package eu.svjatoslav.sixth.e3d.math;
+
+import eu.svjatoslav.sixth.e3d.geometry.Point3D;
+
+/**
+ * <pre>
+ * It is used to store and apply transforms to points.
+ * Transforms are applied in the reverse order they were added to the pipeline.
+ *
+ * Transforms are stacked and then every point is affected by every transform in this stack.
+ * This is needed to support feature where objects in the world are attached to and are relative to each other.
+ *
+ * <b>Example:</b>
+ * There is a ship it the sea. Ship moves along the sea and every object on the ship moves with it.
+ * Inside the ship there is a car. Car moves along the ship and every object on the car moves with it.
+ *
+ * So to calculate an absolute location in the world of particular object within a car,
+ * we must take into account object location relative to the car,
+ * car location relative to the ship,
+ * and ship location relative to the world.
+ * </pre>
+ */
+public class TransformsStack {
+
+
+    /**
+     * Transforms that are currently in the pipeline.
+     * Array is used for efficiency to avoid memory allocation during the rendering
+     * because depth of the pipeline needs to change very often.
+     */
+    private final Transform[] transforms = new Transform[100];
+
+    /**
+     * The number of transforms in the pipeline.
+     */
+    private int transformsCount = 0;
+
+    /**
+     * Adds a transform to the pipeline.
+     *
+     * @param transform The transform to add.
+     */
+    public void addTransform(final Transform transform) {
+        transforms[transformsCount] = transform;
+        transformsCount++;
+    }
+
+    /**
+     * Clears the pipeline.
+     */
+    public void clear() {
+        transformsCount = 0;
+    }
+
+    /**
+     * Drops the last transform from the pipeline.
+     */
+    public void dropTransform() {
+        transformsCount--;
+    }
+
+    /**
+     * Transforms a point.
+     *
+     * @param coordinate Coordinate to be transformed into result. Original input coordinate is not modified.
+     * @param result     Resulting transformed point. For efficiency reasons, result is stored into preexisting object
+     *                   that is passed here as an argument to avoid memory allocation.
+     */
+    public void transform(final Point3D coordinate, final Point3D result) {
+
+        result.clone(coordinate);
+
+        // Apply transforms in reverse order.
+        for (int i = transformsCount - 1; i >= 0; i--)
+            transforms[i].transform(result);
+    }
+}