diff --git a/06_Mandelbulb/Mandelbulb.lhs b/06_Mandelbulb/Mandelbulb.lhs
index 2131f0e..6428447 100644
--- a/06_Mandelbulb/Mandelbulb.lhs
+++ b/06_Mandelbulb/Mandelbulb.lhs
@@ -1,9 +1,33 @@
## Optimization
+All feel good from the architecture point of vue.
+More precisely, the separation between rendering and world behavior is clear.
+But this is extremely slow now.
+Because we compute the mandelbulb for each frame now.
+
+Before we had
+
+ Constant Function -> Constant List of Triangles -> Display
+
+Now we have
+
+ World -> Function -> List of Objects -> Atoms -> Display
+
+And the World state could change.
+Then it is no more straightforward for the compiler to understand
+when not to recompute the entire list of atoms.
+
+Then to optimize we will have to make things a little less separate.
+We must control the flow of atom generation.
+
+Mostly the program is the same as before, but instead of providing a
+function, we will provide the list of atoms directly.
+
+
> import YGL -- Most the OpenGL Boilerplate
> import Mandel -- The 3D Mandelbrot maths
-
+>
> -- Centralize all user input interaction
> inputActionMap :: InputMap World
> inputActionMap = inputMapFromList [
@@ -25,14 +49,15 @@
> ,(Press 'g' , resize (1/1.2))
> ]
+
-> -- I prefer to set my own name for these types
> data World = World {
> angle :: Point3D
> , scale :: Scalar
> , position :: Point3D
> , box :: Box3D
-> , told :: Time -- last frame time
+> , told :: Time
+> -- We replace shape by cache
> , cache :: [YObject]
> }
@@ -43,9 +68,10 @@
> camPos = position w,
> camDir = angle w,
> camZoom = scale w }
+> -- We update our objects instanciation
> objects = cache
-
+
> xdir :: Point3D
> xdir = makePoint3D (1,0,0)
@@ -67,17 +93,15 @@
> zoom :: Scalar -> World -> World
> zoom z world = world {
> scale = z * scale world }
->
-> resize :: Scalar -> World -> World
-> resize r world =
-> tmpWorld { cache = objectFunctionFromWorld tmpWorld }
-> where
-> tmpWorld = world { box = (box world) {
-> resolution = sqrt ((resolution (box world))**2 * r) }}
->
+
> main :: IO ()
> main = yMainLoop inputActionMap idleAction initialWorld
+
+
+Our initial world state is slightly changed:
+
+
> -- We initialize the world state
> -- then angle, position and zoom of the camera
> -- And the shape function
@@ -90,9 +114,13 @@
> , maxPoint = makePoint3D (2,2,2)
> , resolution = 0.02 }
> , told = 0
+> -- We declare cache directly this time
> , cache = objectFunctionFromWorld initialWorld
> }
->
+
+We use the `YGL.getObject3DFromShapeFunction` function directly.
+This way instead of providing `XYFunc`, we provide directly a list of Atoms.
+
> objectFunctionFromWorld :: World -> [YObject]
> objectFunctionFromWorld w = [Atoms atomList]
> where atomListPositive =
@@ -102,7 +130,22 @@
> negativeTriangle (ColoredTriangle (p1,p2,p3,c)) =
> ColoredTriangle (negz p1,negz p2,negz p3,c)
> where negz (P (x,y,z)) = P (x,y,-z)
->
+
+We know that resize is the only world change that necessitate to
+recompute the list of atoms (triangles).
+Then we update our world state accordingly.
+
+> resize :: Scalar -> World -> World
+> resize r world =
+> tmpWorld { cache = objectFunctionFromWorld tmpWorld }
+> where
+> tmpWorld = world { box = (box world) {
+> resolution = sqrt ((resolution (box world))**2 * r) }}
+
+All the rest is exactly the same.
+
+
+
> idleAction :: Time -> World -> World
> idleAction tnew world =
> world {