Home | nevrax.com |
|
mot.hGo 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 |