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/13 16:24] – [Adding buds] 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, Needles) 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 48: Line 49:
 </code> </code>
  
 +This module does not do much more than being a place holder for next years shoots. It contains the knowledge of the order as well as the proposed length of the new shoot.
 +To improve the visibility the bud is displayed by a turquoise sphere.
 +  
 ==== Apical ==== ==== Apical ====
  
 +To enable further apical growth, we will place a bud of the same order as the shoot on each shoot that does not have a apical successor.
 +
 +We can estimate this by testing if the RTREND (reverse Trend) is 0. In that case we replace the F not only by a new MyShoot but additionally by a new MyBud with the same order and proposed length of 70% of the original f. :
 +<code>
 +f:F,(f[RTREND]==0) ==> MyShoot(f.length,f.diameter).($[transform]=f[transform])MyBud(f[BO],f.length*0.7);
 +</code>
 +
 +
 +Lets pick for now a very simple growth rule: every bud of order 0 or 1 is replaced by a shoot of the proposed length with a diameter estimated based on the length(5%) and a new bud of the same order and a new 70% of the proposed length of the old bud:
 +<code>
 +MyBud(o,l),(o<2) ==> MyShoot(l,l/25) MyBud(o,l*0.7);
 +</code>
 + 
 +
 +These changes leads to the following RGG code:
 +
 +<code java step2.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);}}
 +public void update()[
 + {
 + jumpAllAxis();
 + }
 + f:F,(f[RTREND]==0) ==> MyShoot(f.length,f.diameter).($[transform]=f[transform])MyBud(f[BO],f.length*0.7);
 + f:F ==> MyShoot(f.length,f.diameter).($[transform]=f[transform]);
 +]
 +
 +
 +public void grow()[
 + MyBud(o,l),(o<2) ==> MyShoot(l,l/20) MyBud(o,l*0.7);
 +
 +]
 +
 +</code>
 +
 +This model applied on our small example tree should result in the following output:
 +
 +| {{:tutorials:qsm:initial_tiny_tree.png?direct&200|}} | {{:tutorials:qsm:with_a_buds_tiny_tree.png?direct&200|}} | {{:tutorials:qsm:with_a_buds_step1_tiny_tree.png?direct&200|}} | {{:tutorials:qsm:with_a_buds_step2.png?direct&200|}} |
 +| Imported tree | updated tree | 1. growth step | 2. growth step | 
 ==== Lateral ==== ==== Lateral ====
  
-===== Adding needles =====+For the lateral buds we again use a simplified assumption: Each of the shoot has two lateral buds placed in opposite position at 2/3th of the shoot. These buds have a branch order one higher than the parent shoot and a proposed length of 50% of the parent shoot. 
 + 
 +//Since GroIMP works with local transformation and the buds are added at the end of the new shoot we move backwards not forwards. // 
 + 
 +<code> 
 +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) 
 +  ] 
 + ] 
 + MyBud(f[BO],f.length*0.7); 
 +</code> 
 + 
 + 
 +If we use the same code not only for the reconstructed shoots but for the new created once as well, and increase the limit on which order buds can grow to 3 (so we actually see lateral branches emerge), we end with the following code: 
 + 
 +<code java lateralBuds.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);}} 
 +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) 
 +    ] 
 +   ] 
 +   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) 
 +   ] 
 +  ] 
 +  MyBud(o,l*0.7); 
 +
 +</code>     
 + 
 + 
 +| {{:tutorials:qsm:initial_latb_tiny_tree.png?direct&200|}} | {{:tutorials:qsm:with_a_buds_latb_tiny_tree.png?direct&200|}} | {{:tutorials:qsm:with_a_buds_step1_latb_tiny_tree.png?direct&200|}} | {{:tutorials:qsm:with_a_buds_step2_latb_tiny_tree.png?direct&200|}} | 
 +| Imported tree | updated tree | 1. growth step | 2. growth step |  
 + 
 +===== 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:==> 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.1760365497.txt.gz · Last modified: 2025/10/13 16:24 by Tim