Modélisation multi-échelle procédurale de scènes animées
Frank Perbet - 2004/04/25

next up previous contents
Next: Bibliographie Up: main Previous: 8. Conclusion

Sous-sections


A. Exemple du cube de Sirpienski

Afin d'avoir une idée précise de ce à quoi peut ressembler un modèle réalisé avec Dynamic Graph, voici le code du cube de Sirpienski. Pour plus de renseignement sur cet outil, je vous renvoie à la documentation en ligne sur http://www-evasion.imag.fr/$\sim$Frank.Perbet/these.

A.1 Le générateur d'amplifieurs

Voici le générateur d'amplifieurs que le créateur doit écrire. Une fois la phase de création ou de modification terminé, ce bout de code est compilé et chargé à la volée durant l'éxécution de Dynamic Graph.

class ty_square:
  public ty_drawableNodeBase
{
public:
  // square size
  ty_float size;
  // branching order
  ty_uint branchingOrder;
  // color
  vec3 color;
  
public:

  // constructor without ancestor
  ty_square::ty_square(
    ty_pt_nodeBase pt_father,
    ty_localID li,
    const ty_uint& _branchingOrder,
    const ty_float& _size,
    const vec3& _color,
    ty_repere initialRepere):
      ty_drawableNodeBase(pt_father,li,createDefaultNodeContainer(),
          initialRepere,ty_sphericalBB(_size)),
      branchingOrder(_branchingOrder),
      color(_color),
      size(_size)
  {
    // Nothing
  }

  // constructor with ancestor
  ty_square::ty_square(
    ty_pt_nodeBase pt_father,
    ty_localID li,
    ty_nodeBase& _ancestor,
    const ty_uint& _branchingOrder,
    const ty_float& _size,
    const vec3& _color,
    ty_repere initialRepere):
      ty_drawableNodeBase(pt_father,li,createDefaultNodeContainer(),_ancestor,
          initialRepere,ty_sphericalBB(_size)),
      branchingOrder(_branchingOrder),
      color(_color),
      size(_size)
  {
    // Nothing
  }


  // visitor: generation 
  virtual void upDown(parserFunction::ty_generation& v)
  {
    setMaturity(v.getNodeInfo());

    if(branchingOrder>0)
    {
      ty_float reductionCoef = 1.0;
      ty_float coef = reductionCoef+(1.0-reductionCoef)*(1.0-maturity());
      size*=coef;
    }

    if(precision()>0)
    {
      // create child node
      childGeneration(v);
    }
    else
    {
      draw();
    }
  }
  
protected:
  
  // creation of child node
  void childGeneration(parserFunction::ty_generation& v)
  {
    ty_ncRedirection& childContainer =
        static_cast<ty_ncRedirection&>(container());

    static boost::array<vec3,8> dec = {{
      vec3(1.0,1.0,1.0),
      vec3(1.0,1.0,-1.0),
      vec3(1.0,-1.0,1.0),
      vec3(1.0,-1.0,-1.0),
      vec3(-1.0,1.0,1.0),
      vec3(-1.0,1.0,-1.0),
      vec3(-1.0,-1.0,1.0),
      vec3(-1.0,-1.0,-1.0) }};

    ty_tmpChildList tmpList = childContainer.startGeneration();
    for(int i=0;i<8;i++)
    {
      vec3 newPosition = dec[i]*(size/4.0);
      ty_float newSize = size/2.0;
      vec3 newColor = color;

      ty_pt_nodeBaseBase it = childAncestor(i);
      if(it.isValid())
      {
        ty_nodeBase& a = static_cast<ty_nodeBase&>(it.ref());
        ty_nodeBase* newChild;
        NEW(ty_square,newChild)
            (this,i,a,branchingOrder+1,newSize,
            newColor,globalRepere*ty_repere(newPosition));
        childContainer.addChild(tmpList,newChild);
      }
      else
      {
        ty_nodeBase* newChild;
        NEW(ty_square,newChild)
          (this,i,branchingOrder+1,newSize,
          newColor,globalRepere*ty_repere(newPosition));
        childContainer.addChild(tmpList,newChild);
      }
    }
    childContainer.endGeneration(tmpList);
  }

  
  // opengl draw function
  void drawCore()
  {
    glPushMatrix();
    glMultMatrix(globalRepere);
    glColor(color);
    draw_cube(1,0xFF,get_rapport(),size);
    glPopMatrix();
  }


  /// opengl draw function
  void drawDebug(ty_glViewer& v)
  {
    pixel vpSize = v.mainViewportSize();

    ty_float pos=-30;
    v.strBuf()<<"size = "<<size<<std::endl;
    v.drawText(10,vpSize[1]-(pos+=30));
    v.strBuf()<<"branchingOrder = "<<branchingOrder;
    v.drawText(10,vpSize[1]-(pos+=30));
    v.strBuf()<<"precision = "<<ty_maturity::precision();
    v.drawText(10,vpSize[1]-(pos+=30));
    v.strBuf()<<"maturity = "<<ty_maturity::maturity();
    v.drawText(10,vpSize[1]-(pos+=30));
  }


}; // end of ty_square

A.2 Fonctions d'échange

Les fonctions d'échanges sont les fonctions que Dynamic Graph va explicitement chercher dans la librairie avec la fonction dlsym (dans le fichier d'entête standard dlfcn.h). Parmis ces fonctions, ont remarquera celle qui se charge de la création du premier amplifieur, racine de l'arbre d'évaluation.

extern "C"
{
  typedef boostEXT::te_array<GLfloat,4> glvec4;
  typedef boostEXT::te_array<GLfloat,3> glvec3;


  // called one time when loading the model
  void init()
  {
    dpGV::initSlider(7,1,"Rapport",333,1000);
    dpGV::initSlider(7,2,"GL_SPOT_CUTOFF",200,1000);
    dpGV::initSlider(7,3,"GL_SPOT_EXPONENT",145,1000);
    dpGV::initSlider(7,4,"GL_AMBIENT",380,1000);
    dpGV::initSlider(7,5,"GL_DIFFUSE",500,1000);
    
    glPushMatrix();
    glLoadIdentity(); // on est dans le repere de la camera

    glvec4 light_ambiant = glvec4(
       4*dpGV::sliderF(7,4),
       4*dpGV::sliderF(7,4),
       4*dpGV::sliderF(7,4),1);
    glvec4 light_diffuse = glvec4(
      4*dpGV::sliderF(7,5),
      4*dpGV::sliderF(7,5),
      4*dpGV::sliderF(7,5),1);

    glLightfv(GL_LIGHT1, GL_POSITION, glvec4(0,0,0,1).c_array());
    glLight(GL_LIGHT1, GL_SPOT_DIRECTION, glvec4(0,0,-1,1).c_array());
    glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambiant.c_array());
    glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse.c_array());

    glLightf(GL_LIGHT1, GL_SPOT_CUTOFF, 180*dpGV::sliderF(7,2));
    glLightf(GL_LIGHT1, GL_SPOT_EXPONENT, 128*dpGV::sliderF(7,3));
    
    glPopMatrix();
  } // init


  // called one time when unloading the model
  void kill()
  {
    // Nothing
  } // kill


  // called one time before each tree generation
  void initFrame()
  {
    glEnable(GL_LIGHT1);
  } // initFrame

  
  // call one time after each tree generation
  void killFrame()
  {
    // nothing
  } // killFrame

  
  // create the root node (the axiom)
  void getStartInfo(ty_tree& tree)
  {
    // color
    vec3 color =
      vec3(dpGV::sliderF(3,1),dpGV::sliderF(3,2),dpGV::sliderF(3,3));
    
    // size and position of the first square
    ty_float size = 1;
    vec3 position = vec3(0,0,0);
    
    // initial repere:
    ty_repere ri = tree.initialRepere;

    // construct the axion
    if(tree.isAncestorAxiomAlive())
    {
      ty_nodeBase& ancestor = static_cast<ty_nodeBase&>(tree.ancestorAxiom());
      NEW(ty_square,tree.ptAxiom())
        (ty_pt_nodeBase(),0,ancestor,0,size,color,ri*position);
    }
    else
    {
      NEW(ty_square,tree.ptAxiom())
        (ty_pt_nodeBase(),0,0,size,color,ri*position);
    }
  }
}



Frank Perbet
2004/04/25