User Tools

Site Tools


tutorials:qsm:to-growable

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
tutorials:qsm:to-growable [2025/10/14 11:48] – [Lateral] Timtutorials:qsm:to-growable [2025/10/23 15:52] (current) – [Turning a QSM into a growable model] Tim
Line 1: Line 1:
 ====== Turning a QSM into a growable model ====== ====== Turning a QSM into a growable model ======
  
-In the following tutorial we will take a small QSM file, transform the existing cylinders into modules and add additional organs(Buds, Leaves) in order to simulate simple growth based on a measured dataset  +In the following tutorial we will take a small QSM file, transform the existing cylinders into modules and add additional organs(Buds, Leaves) in order to simulate simple forgoing growth. This tutorial requires knowledge about the programming language RGG (see: [[tutorials:rgg-code-structure|RGG Code structure introduction]]) as well as basic XL-queries (see: [[tutorials:xl-queries-and-operators|XL queries and operators]]).
  
 +For this tutorial we will use this very small QSM: {{ :tutorials:qsm:tiny_tree2.qsm |tiny_tree2.qsm}}. 
 +This dataset was originally measured with the fastrak stylus and is later translated into a QSM
 ===== Shoots ===== ===== Shoots =====
  
Line 118: Line 119:
  
 <code java lateralBuds.rgg> <code java lateralBuds.rgg>
 +import static de.grogra.qsm.utils.Library.*;
 +import static de.grogra.qsm.utils.Descriptors.*;
  
-    import static de.grogra.qsm.utils.Library.*; +module MyShoot(super.length, super.diameter) extends F{{setShader(EGA_6);}} 
-    import static de.grogra.qsm.utils.Descriptors.*; +module MyBud(int order, float length) extends Sphere(0.002){{setShader(EGA_3);}} 
-    module MyShoot(super.length, super.diameter) extends F{{setShader(EGA_6);}} +public void update()[ 
-    module MyBud(int order, float length) extends Sphere(0.002){{setShader(EGA_3);}} + { 
-    public void update()[ +  jumpAllAxis(); 
-     + } 
-     jumpAllAxis(); + f:F,(f[RTREND]==0) ==> MyShoot(f.length,f.diameter).($[transform]=f[transform]) 
-     +   
-     f:F,(f[RTREND]==0) ==> MyShoot(f.length,f.diameter).($[transform]=f[transform]) +    M(-0.3*f.length)   
-     +    
-     M(-0.3*f.length)   +     RL(65)MyBud(f[BO]+1,f.length*0.5)
-     +
- RL(65)MyBud(f[BO]+1,f.length*0.5) +
-+
-+
- RL(-65)MyBud(f[BO]+1,f.length*0.5) +
-+
-    ] +
-    MyBud(f[BO],f.length*0.7); +
-    f:F ==> MyShoot(f.length,f.diameter).($[transform]=f[transform]);+
     ]     ]
 +    [
 +     RL(-65)MyBud(f[BO]+1,f.length*0.5)
 +    ]
 +   ]
 +   MyBud(f[BO],f.length*0.7);
 +   
 + f:F ==> MyShoot(f.length,f.diameter).($[transform]=f[transform]);
 +]
            
            
-    public void grow()[ +public void grow()[ 
-     MyBud(o,l),(o<3) ==> MyShoot(l,l/20)  + MyBud(o,l),(o<3) ==> MyShoot(l,l/20)  
-     +  
-     M(-0.3*l)   +   M(-0.3*l)   
-     +   
- RL(65)MyBud(o+1,l*0.5) +    RL(65)MyBud(o+1,l*0.5) 
- +   
- +   
- RL(-65)MyBud(o+1,l*0.5) +    RL(-65)MyBud(o+1,l*0.5) 
- +   
-     +  
-     MyBud(o,l*0.7); +  MyBud(o,l*0.7); 
-      +]
-    ]+
 </code>     </code>    
  
Line 162: Line 163:
 | Imported tree | updated tree | 1. growth step | 2. growth step |  | Imported tree | updated tree | 1. growth step | 2. growth step | 
  
-===== Adding needles =====+===== Adding Leaves =====
  
 +As final organ for this tutorial we want to add leaves to our little tree. The leaves are represented by simple parallelograms,with an additional M to shifted them a bit to make them not appear to grow on the inside of the shoot:
 +<code java>
 + module Leaf ==> M(0.001) Parallelogram(0.012,0.01).(setShader(GREEN));
 +</code> 
 +We assume that our Leaves have a fixed size, based on the proportions of the original tree.
  
 +Lets place two of them each at 1/4 and 3/4 length on our shoot, with one pair oriented to the left and right and one pair up and down:
 +
 +<code java with_leaves.rgg>
 +import static de.grogra.qsm.utils.Library.*;
 +import static de.grogra.qsm.utils.Descriptors.*;
 +module MyShoot(super.length, super.diameter) extends F{{setShader(EGA_6);}}
 +module MyBud(int order, float length) extends Sphere(0.002){{setShader(EGA_3);}}
 +module Leaf ==> M(0.001) Parallelogram(0.012,0.01).(setShader(GREEN));
 +public void update()[
 + {
 +  jumpAllAxis();
 + }
 + f:F,(f[RTREND]==0) ==> MyShoot(f.length,f.diameter).($[transform]=f[transform])
 +  [
 +   M(-0.3*f.length)  
 +   [
 +    RL(65)MyBud(f[BO]+1,f.length*0.5)
 +   ]
 +   [
 +    RL(-65)MyBud(f[BO]+1,f.length*0.5)
 +   ]
 +  ]
 +  [
 +  M(-0.25*f.length)
 +  [
 +   RL(80)Leaf()
 +  ]
 +  [
 +   RL(-80)Leaf()
 +  ]
 + ]
 + [
 +  M(-0.75*f.length)RH(90)
 +  [
 +   RL(80)Leaf()
 +  ]
 +  [
 +   RL(-80)Leaf()
 +  ]
 + ]
 + MyBud(f[BO],f.length*0.7);
 +
 + f:F ==> MyShoot(f.length,f.diameter).($[transform]=f[transform]);
 +]
 +
 +
 +public void grow()[
 + MyBud(o,l),(o<3) ==> MyShoot(l,l/20) 
 +  [
 +   M(-0.3*l)  
 +   [
 +    RL(65)MyBud(o+1,l*0.5)
 +   ]
 +   [
 +    RL(-65)MyBud(o+1,l*0.5)
 +   ]
 +  ]
 +  [
 +   M(-0.25*l)
 +   [
 +    RL(80)Leaf()
 +   ]
 +   [
 +    RL(-80)Leaf()
 +   ]
 +  ]
 +  [
 +   M(-0.75*l)RH(90)
 +   [
 +    RL(80)Leaf()
 +   ]
 +   [
 +    RL(-80)Leaf()
 +   ]
 +  ]
 +  MyBud(o,l*0.7);
 +]
 +</code>
 +
 +| {{:tutorials:qsm:initial_leaf_tiny_tree.png?direct&200|}} | {{:tutorials:qsm:with_a_buds_leaf_tiny_tree.png?direct&200|}} | {{:tutorials:qsm:with_a_buds_step1_leaf_tiny_tree.png?direct&200|}} | {{:tutorials:qsm:with_a_buds_step2_leaf_tiny_tree.png?direct&200|}} |
 +| Imported tree | updated tree | 1. growth step | 2. growth step | 
 +
 +
 +===== Outlook =====
 +
 +Possible next steps would be:
 +  * To add an age to the leaves (so they die after a year or two)
 +  * To add secondary growth to the shoots (so they stretch a bit over the years)
 +  * To add image shades to the different organs
 +  * To set up a light model and implements a simple photo synthesis model.
 + 
tutorials/qsm/to-growable.1760435296.txt.gz · Last modified: 2025/10/14 11:48 by Tim