# Home    # nevrax.com   
Nevrax
Nevrax.org
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
Docs
 
Documentation  
Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  

mot.h

Go to the documentation of this file.
00001 
00007 /* Copyright, 2000 Nevrax Ltd.
00008  *
00009  * This file is part of NEVRAX NEL.
00010  * NEVRAX NEL is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2, or (at your option)
00013  * any later version.
00014 
00015  * NEVRAX NEL is distributed in the hope that it will be useful, but
00016  * WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00018  * General Public License for more details.
00019 
00020  * You should have received a copy of the GNU General Public License
00021  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00022  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00023  * MA 02111-1307, USA.
00024  */
00025 
00026 #ifndef NL_MOT_H
00027 #define NL_MOT_H
00028 
00029 
00030 #include "nel/misc/types_nl.h"
00031 #include "nel/misc/smart_ptr.h"
00032 #include "nel/misc/bit_set.h"
00033 #include "nel/misc/class_id.h"
00034 #include <vector>
00035 #include <set>
00036 #include <map>
00037 
00038 
00039 
00040 namespace       NLMISC
00041 {
00042         class   IStream;
00043 }
00044 
00045 
00046 namespace       NL3D
00047 {
00048 
00049 /*
00050         // THIS IS NOT TRADUCED BECAUSE NOT FIXED YET.
00051 
00052         IDEES / TODO:
00053 
00054         - Pour la recherche de texture/mesh sur le disque, il faudrait implémenter un objet CPath, qui représente
00055           un simili PATH, avec des méthodes add() / del() / get(i), et une méthode open(TFile) ou TFile est un objet fichier
00056           avec une fonction "bool open(string )".
00057         - Imaginons que l'on veuille implémenter un système de cache avancé: un fichier peut se trouver en mémoire, sur disque,
00058           ou sur le réseau. On pourrait faire cela en utilisant simplement CPath, et en utilisant un CMetaFile, classe qui
00059           ouvrir un type de stream suivant le nom de la string ouverte (CMemoryStream, CFile, CMessage ...).
00060 
00061         - On pourrait implémenter un Observer de clip qui clip par matériau aussi, en faisant une sorte de 
00062           batch culling: On stocke par matériau un "plan directeur" et un delta d'erreur accepté (à préciser...)
00063 
00064 */
00065 
00066 
00067 
00068 /*
00069         // THIS IS NOT TRADUCED BECAUSE NOT FIXED YET.
00070 
00071   Le moteur est basé sur un modèle Model / Observer / Traversal. (MOT).
00072 
00073   Graph de classe Model / Observer / Traversal  (Model, Obs, Trav)
00074 
00075   CMOT contient N traversals de type différents. Typiquement, les 4 traversals de base sont:
00076 
00077 CHandleTrav:    la hierarchie d'objet. Le graph est un arbre. Le Traverser donne toutes les WorldMatrix des objets,
00078         necessaire aux autres traversals.
00079 CCullTrav:      le graph de visibilité. Ce traversal affecte directement CRenderTrav, en ajoutant les objets visibles.
00080 CLightTrav:     le graph de dépendance Light/Objet. Ce graph est aussi un arbre. Il indique quels objets sont illuminés par 
00081         quelle source lumineuse. Le traversal déduit par noeud une liste des lights qui l'ilumine.
00082 CRenderTrav: la liste triée en Z des objets à rendre.
00083 
00084 
00085   On a un SceneGraph en organisant les observers. ie, on a des graph d' observer (on a un graph par Traversal). Les models
00086   n'ont pas forcément un observer dans chaque graph. Typiquement, ni un cluster ni une light ne se render.
00087 
00088   
00089   Exemple de models
00090 
00091 CLight:         light. Pass: NODE & CULL & LIGHT.
00092 CInstance:      instance d'un mesh quelconque. Pass: NODE & CULL & LIGHT & RENDER
00093 CCluster:       Un cluster représente un partitionnement du monde. NODE & CULL
00094 CPortal:        un portal est un lien entre 2 clusters.  NODE & CULL
00095 
00096 
00097 
00098 Le client n'utilise QUE ITrav et IModel.
00099 Il ne peut accéder à ses Observeurs. Un observeur ici est juste un objet "algorithm" qui travaille sur des modeles, pour un 
00100 traversal. AUCUN setup ne doit donc lui être appliqué. A la question "oui mais j'ai envie de donner des hints pour le calcul 
00101 de la radiosité", la réponse est: Il faut dériver du Model à étendre, pour lui rajouter ces fameux hints, puis implémenter
00102 l'observeur qui va prendre en compte ces hints. Un nouveau model est crée, et c'est donc celui là que le client devra utiliser 
00103 pour setter ses hints pour le traversal de radiosité. De cette facon, on garde l'encapsulation Model/Traversal.
00104 
00105 
00106 Le deriver peut créer des Traversals, de nouveaux models (soit totalement nouveaux, soit par héritage)
00107 et implémente les IObs, et doit les registerer dans CMOT.
00108 
00109 
00110 Fonctionnement du Système d'instance (Shapes). Ce modèle ne s'occupe pas des instances, mais il faut donner une ligne de
00111 conduite pour une utilisation correcte. En fait, les règles Model/Observer ne doivent pas être transgressées: le model est
00112 la structure, l'observeur est l'algorithm pour le traversal donné. Cela veut dire que la fonction render() doit être
00113 implémentée dans l'observeur, et non dans le shape. En procédant de cette façon, on est sur que l'observeur pourra accéder 
00114 à toutes les infos dont il a besoin (comme la WorldMatrix de l'observeur Handle par exemple). Cela veut dire aussi qu'il 
00115 faudra que l'interface du shape soit bien définie vis à vis de l'observeur. Faire un nouveau shape demandera donc parfois
00116 de créer un nouveau model (un CInstance particulier, qui n'a pas forcément de nouvelles méthodes), ainsi qu'un nouvel 
00117 observeur qui suportera ce shape.
00118 
00119 
00120 NOTE: le fait de bien séparer Models/Observers n'interdit pas le stockage de données particulières à l'observeur dans Model.
00121 Ceci est particulièrement vrai pour Shape, qui gardera les liste de vertices pré-computées pour render() etc...
00122 
00123 
00124 PROBLEME: interaction entre les traversals (clip / cull). ClipObs et RenderObs doit demander le résultat de HandleObs. 
00125 ClipObs doit linker les RenderObs dans le RenderTrav. => pitet obligé, en partie, de fournir une interface de base IObs, 
00126 par Traversal (CBaseRenderObs, CBaseCullObs, ...) pour ainsi fournir une même interface pour les autrres observeurs (eg: 
00127 l'observeur de Cull récupère la WorlMatrix de l'observeur de base Handle). Ceci est à spécifier par Traversal.
00128 
00129 
00130 
00131 Le core du moteur (ie nous :) ) a le droit de changer modèles, Traversals et observeurs, à la condition de garder
00132 une compatibilité ascendante, pour que les modèles/observeurs/traversals écrit par les Deriver marchent encore, bien qu'il 
00133 soit alors nécessaire de recompiler.
00134 
00135 */
00136 
00137 
00138 
00139 class   IModel;
00140 class   IObs;
00141 class   ITrav;
00142 
00143 
00144 // ***************************************************************************
00159 class   CMOT
00160 {
00161 public:
00162         // Ctor.
00163         CMOT();
00164         // Dtor.
00165         ~CMOT();
00166 
00168 
00169 
00176         static  void    registerModel(const NLMISC::CClassId &idModel, const NLMISC::CClassId &idModelBase, IModel* (*creator)());
00184         static  void    registerObs(const NLMISC::CClassId &idTrav, const NLMISC::CClassId &idModel, IObs* (*creator)());
00186 
00187 
00188 public:
00190 
00191 
00198         void    addTrav(ITrav *v);
00204         ITrav   *getTrav(const NLMISC::CClassId &idTrav) const;
00206 
00207         
00208 public:
00210 
00211 
00228         IModel  *createModel(const NLMISC::CClassId &idModel);
00229 
00236         void    deleteModel(IModel *model);
00237 
00241         void    validateModels();
00242 
00244 
00245 
00249         void    release();
00250 
00251 
00252 // ******************
00253 private:
00254         struct  CModelEntry
00255         {
00256                 NLMISC::CClassId        ModelId, BaseModelId;
00257                 IModel* (*Creator)();
00258                 bool    operator<(const CModelEntry& o) const {return ModelId<o.ModelId;}
00259                 bool    operator==(const CModelEntry& o) const {return ModelId==o.ModelId;}
00260                 bool    operator!=(const CModelEntry& o) const {return !(*this==o);}
00261         };
00262 
00263         struct  CObsEntry
00264         {
00265                 NLMISC::CClassId        TravId, ModelId;
00266                 IObs* (*Creator)();
00267                 bool    operator<(const CObsEntry& o) const 
00268                 {
00269                         if(TravId!=o.TravId)
00270                                 return TravId<o.TravId;
00271                         else
00272                                 return ModelId<o.ModelId;
00273                 }
00274                 bool    operator==(const CObsEntry& o) const 
00275                 {
00276                         return ModelId==o.ModelId && TravId==o.TravId;
00277                 }
00278                 bool    operator!=(const CObsEntry& o) const {return !(*this==o);}
00279         };
00280 
00281         struct  CTravEntry
00282         {
00283                 NLMISC::CClassId        TravId;
00284                 ITrav   *Trav;
00285         };
00286 
00287 private:
00288         std::vector<CTravEntry>                 Traversals;
00289         std::set<IModel*>                               Models;
00290         static std::set<CModelEntry>    RegModels;
00291         static std::set<CObsEntry>              RegObservers;
00292 
00293 private:
00294         // Create an observer, obeying the hierachy/observer system explained in createModel().
00295         IObs    *createObs(const ITrav *trav, const NLMISC::CClassId &idModel) const;
00296 
00297 protected:
00298         // For hertied class, to access observer result of a model.
00299         IObs    *getModelObs(IModel *m, const NLMISC::CClassId &idTrav) const;
00300 };
00301 
00302 
00303 // ***************************************************************************
00328 class   IModel : public NLMISC::CRefCount
00329 {
00330 protected:
00339         IModel();
00340 
00347         virtual ~IModel();
00348 
00349 public:
00350         
00352 
00353 
00357         enum    TDirty
00358         {
00359                 Dirty=0,                // First bit, to say that the Model is dirty.
00360                 Last
00361         };
00363         NLMISC::CBitSet         TouchObs;
00365         void    foul(uint flag) { TouchObs.set(Dirty); TouchObs.set(flag); }
00366 
00368         void    validate();
00369 
00371 
00372 
00373 protected:
00374         // Observers created and linked by CMOT::createModel()
00375         friend  class   CMOT;
00376         friend  class   IObs;
00377         friend  class   ITrav;
00378         typedef std::map<NLMISC::CClassId, IObs*>               CObsMap;
00379         CObsMap Observers;
00380 
00381         // Cache the last observer acceded through getObs().
00382         mutable NLMISC::CClassId        LastClassId;
00383         mutable IObs                            *LastObs;
00385         IObs    *getObs(const NLMISC::CClassId &idTrav) const;
00386 
00387 
00388 protected:
00389 
00390 
00392 
00393 
00405         virtual void    update()
00406         {
00407         }
00408 
00421         virtual void    cleanTouch()
00422         {
00423                 TouchObs.clearAll();
00424         }
00426 
00427 };
00428 
00429 
00430 // ***************************************************************************
00453 class   IObs : public NLMISC::CRefCount
00454 {
00455 public:
00456         IModel  *Model;         // The model for this observer.
00457         ITrav   *Trav;          // The traversal for this observer.
00458 
00459 public:
00460         IObs();
00462         virtual                 ~IObs();
00466         virtual void    init() {}
00467 
00468 
00489 
00490         virtual bool    isTreeNode() {return true;}
00492         virtual void    addChild(IObs *son);
00494         virtual void    delChild(IObs *son);
00499         virtual void    addParent(IObs *father);
00501         virtual void    delParent(IObs *father);
00502 
00504         virtual sint    getNumChildren() const;
00506         virtual IObs    *getFirstChild() const;
00508         virtual IObs    *getNextChild() const;
00509 
00511         virtual sint    getNumParents() const;
00513         virtual IObs    *getFirstParent() const;
00515         virtual IObs    *getNextParent() const;
00517 
00518 
00520 
00521 
00528         virtual void    traverse(IObs *caller)=0;
00530 
00531 
00533 
00534 
00541         virtual void    update()
00542         {
00543         }
00545 
00546 
00548 
00549 
00550         void    traverseSons()
00551         {
00552                 for(IObs *c= getFirstChild(); c!=NULL; c= getNextChild())
00553                 {
00554                         c->traverse(this);
00555                 }
00556         }
00558         IObs                    *getObs(const NLMISC::CClassId &idTrav) const;
00560 
00561 
00562 protected:
00563         std::set<IObs*> Sons;
00564         std::set<IObs*> Fathers;
00565 
00566         mutable std::set<IObs*>::const_iterator SonIt;
00567         mutable std::set<IObs*>::const_iterator FatherIt;
00568 
00569 };
00570 
00571 
00572 
00573 // ***************************************************************************
00595 class   ITrav : public NLMISC::CRefCount
00596 {
00597 public:
00598 
00600 
00601 
00602         ITrav() {Root=NULL;}
00604         virtual ~ITrav() {Root= NULL;}
00606 
00608 
00609 
00613         virtual IObs    *createDefaultObs() const =0;
00615         virtual NLMISC::CClassId        getClassId() const =0;
00617 
00618 
00620 
00621 
00629         void    setRoot(IModel  *root);
00631         IModel  *getRoot() const;
00638         void    link(IModel *m1, IModel *m2) const;
00644         void    unlink(IModel *m1, IModel *m2) const;
00646         void    moveChildren(IModel *parentFrom, IModel *parentTo) const;
00648         void    copyChildren(IModel *parentFrom, IModel *parentTo) const;
00649 
00650 
00652         sint    getNumChildren(IModel *m) const;
00654         IModel  *getFirstChild(IModel *m) const;
00656         IModel  *getNextChild(IModel *m) const;
00657 
00659         sint    getNumParents(IModel *m) const;
00661         IModel  *getFirstParent(IModel *m) const;
00663         IModel  *getNextParent(IModel *m) const;
00664 
00666 
00667 
00668 protected:
00669         // The root observer.
00670         NLMISC::CRefPtr<IObs>   Root;
00671 
00672 };
00673 
00674 
00675 
00676 
00677 }
00678 
00679 
00680 #endif // NL_MOT_H
00681 
00682 /* End of mot.h */
00683