| 1 | // tWorld.h  |
| 2 | //  |
| 3 | // This class represents entire worlds of tObjects. Instances, materials, models, paths, lights, skeletons, and cameras  |
| 4 | // may all be present in a tWorld. It is able to load multiple tChunk-based binary tac files. It can also save them.  |
| 5 | //  |
| 6 | // Every saved tac file contains a version chunk with both major and minor version numbers. Increment the minor number  |
| 7 | // if there is a change to a tObject that does not break binary compatibility. For example, you can add a new chunk ID  |
| 8 | // as long as loading it is optional. The major version number must be incremented if file compatibility is broken.  |
| 9 | // This can happen if chunks are rearranged or chunk contents are altered. This allows an exporters to change, perhaps  |
| 10 | // a new chunk was added, without the tac file parsing tool needing an upgrade immediately (forward compatibility). The  |
| 11 | // minor version should be reset to 0 when the major number is incremented. Any tools, by looking at the major number,  |
| 12 | // can maintain backwards compatibility.  |
| 13 | //  |
| 14 | // Version History  |
| 15 | // 1.0 Initial release.  |
| 16 | //  |
| 17 | // Copyright (c) 2006, 2017 Tristan Grimmer.  |
| 18 | // Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby  |
| 19 | // granted, provided that the above copyright notice and this permission notice appear in all copies.  |
| 20 | //  |
| 21 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL  |
| 22 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,  |
| 23 | // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN  |
| 24 | // AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR  |
| 25 | // PERFORMANCE OF THIS SOFTWARE.  |
| 26 |   |
| 27 | #pragma once  |
| 28 | #include <Foundation/tPlatform.h>  |
| 29 | #include <Foundation/tList.h>  |
| 30 | #include "Scene/tCamera.h"  |
| 31 | #include "Scene/tLight.h"  |
| 32 | #include "Scene/tPath.h"  |
| 33 | #include "Scene/tMaterial.h"  |
| 34 | #include "Scene/tSkeleton.h"  |
| 35 | #include "Scene/tPolyModel.h"  |
| 36 | #include "Scene/tLodGroup.h"  |
| 37 | #include "Scene/tInstance.h"  |
| 38 | #include "Scene/tSelection.h"  |
| 39 | namespace tScene  |
| 40 | {  |
| 41 |   |
| 42 |   |
| 43 | const uint32 SceneMajorVersion = 1;  |
| 44 | const uint32 SceneMinorVersion = 0;  |
| 45 |   |
| 46 |   |
| 47 | class tWorld  |
| 48 | {  |
| 49 | public:  |
| 50 | // When loading a tac file, what object types do we process. Filters can be combined.  |
| 51 | enum tLoadFilter  |
| 52 | {  |
| 53 | tLoadFilter_None = 0x00000000,  |
| 54 | tLoadFilter_Cameras = 0x00000001,  |
| 55 | tLoadFilter_Lights = 0x00000002,  |
| 56 | tLoadFilter_Paths = 0x00000004,  |
| 57 | tLoadFilter_Materials = 0x00000008,  |
| 58 | tLoadFilter_Skeletons = 0x00000010,  |
| 59 | tLoadFilter_Models = 0x00000020,  |
| 60 | tLoadFilter_LodGroups = 0x00000040,  |
| 61 | tLoadFilter_Instances = 0x00000080,  |
| 62 | tLoadFilter_Selections = 0x00000100,  |
| 63 | tLoadFilter_All = 0xFFFFFFFF  |
| 64 | };  |
| 65 |   |
| 66 | tWorld() { }  |
| 67 |   |
| 68 | // Loads scene from a tac chunk file. Any externally referenced files get turned into absolute paths. For example,  |
| 69 | // a tMaterial may refer to a dds file relative to it's location on disk. After the tWorld is created, the path to  |
| 70 | // the dds will be absolute. This allows the tWorld Load call to be called multiple times and load several files  |
| 71 | // into a single world.  |
| 72 | tWorld(const tString& tacFile, uint32 filter = tLoadFilter_All) { Load(tacFile, filter); }  |
| 73 |   |
| 74 | // This constructor can load from multiple tac files and merges them all into one world.  |
| 75 | tWorld(const tItList<tString>& tacFiles, uint32 filter = tLoadFilter_All) { Load(tacFiles, filter); }  |
| 76 | virtual ~tWorld() { Clear(); }  |
| 77 |   |
| 78 | void Clear(); // Clears the scene. Frees any lists or internal objects.  |
| 79 | void Scale(float); // Scales the scene and all its objects.  |
| 80 |   |
| 81 | // @todo Allow save to take filters.  |
| 82 | void Save(const tString& tacFile) const;  |
| 83 |   |
| 84 | // Load may be called more than once to load more objects into the same world.  |
| 85 | void Load(const tString& tacFile, uint32 filter = tLoadFilter_All);  |
| 86 | void Load(const tItList<tString>& tacFiles, uint32 filter = tLoadFilter_All) { for (tItList<tString>::Iter file = tacFiles.First(); file.IsValid(); ++file) Load(*file, filter); }  |
| 87 |   |
| 88 | void AddOffsetToAllIDs(uint32 offset);  |
| 89 |   |
| 90 | // This merges the srcWorld into the current world. In doing so, the srcWorld is left empty and invalid.  |
| 91 | void MergeScene(tWorld& srcWorld);  |
| 92 |   |
| 93 | // This function merges various tObject types into the current world. Since some tObject types can refer to other  |
| 94 | // tObject types, it is important that you supply the objects you want to merge _and_ any objects that may be  |
| 95 | // referenced. You need to go 'all the way down the tree' until you are referencing nothing. Here's a chart that  |
| 96 | // shows what tObjects may reference others:  |
| 97 | //  |
| 98 | // cameras reference nothing  |
| 99 | // lights reference nothing  |
| 100 | // paths reference nothing  |
| 101 | // materials reference nothing (external files only)  |
| 102 | // skeletons reference nothing  |
| 103 | // polyModels reference materials, skeletons  |
| 104 | // lodGroups reference polyModels  |
| 105 | // instances reference lodGroups, polyModels, cameras, lights, paths  |
| 106 | // selectionSets reference instances  |
| 107 | //  |
| 108 | // The passed-in object lists are emptied and merged into the scene. Returns true if all the necessary objects were  |
| 109 | // supplied and the merge was successful.  |
| 110 | bool MergeItems  |
| 111 | (  |
| 112 | tItList<tCamera>*, tItList<tLight>*, tItList<tPath>*,  |
| 113 | tItList<tMaterial>*, tItList<tSkeleton>*, tItList<tPolyModel>*,  |
| 114 | tItList<tLodGroup>*, tItList<tInstance>*, tItList<tSelection>*  |
| 115 | );  |
| 116 |   |
| 117 | // CombinePolyModelInstances combines a list of tPolyModel instances, their meshes and their materials into a  |
| 118 | // single new instance called instName. The polymodel instances you want to combine must already be in the scene.  |
| 119 | // The polymodel instances you provide may no longer in the scene after this call if there are no other instances  |
| 120 | // that refer to it. The new instance will have it's own new polymodel. Returns success.  |
| 121 | bool CombinePolyModelInstances(tItList<tInstance>& polymodelInstances, tString newInstName);  |
| 122 |   |
| 123 | // Returns the number of cameras in the world. If name is supplied, returns the number with that particular name.  |
| 124 | int GetNumCameras(const tString& name = tString()) const;  |
| 125 |   |
| 126 | // Inserts the supplied camera into the scene.  |
| 127 | void InsertCamera(tCamera*);  |
| 128 |   |
| 129 | // Returns first camera with supplied name. Returns nullptr if not found.  |
| 130 | tCamera* FindCamera(const tString& name) const;  |
| 131 |   |
| 132 | // Returns the camera having the id supplied. Returns nullptr if not found.  |
| 133 | tCamera* FindCamera(uint32 id) const;  |
| 134 |   |
| 135 | // The rest of these functions are similar to the 4 above except for different tObject types.  |
| 136 | int GetNumLights(const tString& name = tString()) const;  |
| 137 | void InsertLight(tLight*);  |
| 138 | tLight* FindLight(const tString& name) const;  |
| 139 | tLight* FindLight(uint32 id) const;  |
| 140 |   |
| 141 | int GetNumPaths(const tString& name = tString()) const;  |
| 142 | void InsertPath(tPath*);  |
| 143 | tPath* FindPath(const tString& name) const;  |
| 144 | tPath* FindPath(uint32 id) const;  |
| 145 |   |
| 146 | int GetMaterials(const tMesh& mesh, tItList<tMaterial>&); // Returns the materials used by a particular mesh.  |
| 147 | int GetNumMaterials(const tString& name = tString()) const;  |
| 148 | void InsertMaterial(tMaterial*);  |
| 149 | tMaterial* FindMaterial(const tString& name) const;  |
| 150 | tMaterial* FindMaterial(uint32 id) const;  |
| 151 |   |
| 152 | int GetNumSkeletons(const tString& name = tString()) const;  |
| 153 | void InsertSkeleton(tSkeleton*);  |
| 154 | tSkeleton* FindSkeleton(const tString& name) const;  |
| 155 | tSkeleton* FindSkeleton(uint32 id) const;  |
| 156 |   |
| 157 | int GetNumModels(const tString& name = tString()) const;  |
| 158 | void InsertPolyModel(tPolyModel*);  |
| 159 | tPolyModel* FindPolyModel(const tString& name) const;  |
| 160 | tPolyModel* FindPolyModel(uint32 id) const;  |
| 161 |   |
| 162 | int GetNumLodGroups(const tString& name = tString()) const;  |
| 163 | void InsertLodGroup(tLodGroup*);  |
| 164 | tLodGroup* FindLodGroup(const tString& name) const;  |
| 165 | tLodGroup* FindLodGroup(uint32 id) const;  |
| 166 |   |
| 167 | int GetNumInstances(const tString& name = tString()) const;  |
| 168 | void InsertInstance(tInstance*);  |
| 169 | tInstance* FindInstance(const tString& name) const;  |
| 170 | tInstance* FindInstance(uint32 id) const;  |
| 171 | bool IsInstanceInSelection(const tInstance*, const tSelection*) const;  |
| 172 |   |
| 173 | int GetNumSelections(const tString& name = tString()) const;  |
| 174 | void InsertSelection(tSelection*);  |
| 175 | tSelection* FindSelection(const tString& name) const;  |
| 176 | tSelection* FindSelection(uint32 id) const;  |
| 177 |   |
| 178 | // Returns a list of pointers to all selection sets that contain partialName somewhere in their name. You must  |
| 179 | // empty the list yourself afterwards (you own it), but you don't own the things the pointers on the list point to  |
| 180 | // (the selection sets).  |
| 181 | void FindSelectionsContaining(tItList<tSelection*>&, const tString& partialName) const;  |
| 182 |   |
| 183 | // This call generates additional tLodGroups based on a model naming convention. All models must be present in the  |
| 184 | // scene before calling this. The model naming convention is: "ModelName_LOD_n" where n is the percent of screen  |
| 185 | // space above which the model will be used. The "ModelName" becomes the name of the group, and all models that  |
| 186 | // follow the pattern get their IsLodGroupMember member set. Returns the number of additional tLodGroups that were  |
| 187 | // added to the scene.  |
| 188 | //  |
| 189 | // This functionality should arguably be in the exporter code itself, but since it's a lot of work to make Lod plugins  |
| 190 | // for some modeling packages we've decided a naming convention is reasonable. Multiple modeling SW may need this  |
| 191 | // functionality so it makes sense to put it in a shared location like the tWorld (here). It is ok if there are  |
| 192 | // already LodGroups in the scene. Any new ones simply get assigned new IDs starting at a value one higher than the  |
| 193 | // highest of any current LodGroups.  |
| 194 | int GenerateLodGroupsFromModelNamingConvention();  |
| 195 |   |
| 196 | private:  |
| 197 | // These are helper functions to save and load different types of tObjects.  |
| 198 | void SaveMaterials(tChunkWriter&) const;  |
| 199 | void SaveObjects(tChunkWriter&) const;  |
| 200 | void SaveGroups(tChunkWriter&) const;  |
| 201 | void SaveInstances(tChunkWriter&) const;  |
| 202 | void SaveSelections(tChunkWriter&) const;  |
| 203 |   |
| 204 | void LoadMaterials(const tChunk&, tItList<tMaterial>&);  |
| 205 | void LoadObjects  |
| 206 | (  |
| 207 | const tChunk&,  |
| 208 | tItList<tPolyModel>&, tItList<tSkeleton>&, tItList<tCamera>&, tItList<tLight>&, tItList<tPath>&,  |
| 209 | uint32 loadFilter  |
| 210 | );  |
| 211 | void LoadGroups(const tChunk&, tItList<tLodGroup>&);  |
| 212 | void LoadInstances(const tChunk&, tItList<tInstance>&);  |
| 213 | void LoadSelections(const tChunk&, tItList<tSelection>&);  |
| 214 |   |
| 215 | void CorrectCameraIDs(tItList<tCamera>&, tItList<tInstance>&);  |
| 216 | void CorrectLightIDs(tItList<tLight>&, tItList<tInstance>&);  |
| 217 | void CorrectPathIDs(tItList<tPath>&, tItList<tInstance>&);  |
| 218 | void CorrectMaterialIDs(tItList<tMaterial>&, tItList<tPolyModel>&);  |
| 219 | void CorrectSkeletonIDs(tItList<tSkeleton>&, tItList<tPolyModel>&);  |
| 220 | void CorrectPolyModelIDs(tItList<tPolyModel>&, tItList<tLodGroup>&, tItList<tInstance>&);  |
| 221 | void CorrectLodGroupIDs(tItList<tLodGroup>&);  |
| 222 | void CorrectInstanceIDs(tItList<tInstance>&, tItList<tSelection>&);  |
| 223 | void CorrectSelectionIDs(tItList<tSelection>&);  |
| 224 | void MergeToExistingSelections(tItList<tSelection>&);  |
| 225 |   |
| 226 | public:  |
| 227 | tString Name;  |
| 228 | tString LastLoadedFilename;  |
| 229 |   |
| 230 | // These don't reference anything else in the world, only external file references.  |
| 231 | tItList<tCamera> Cameras;  |
| 232 | tItList<tLight> Lights;  |
| 233 | tItList<tPath> Paths;  |
| 234 | tItList<tMaterial> Materials;  |
| 235 | tItList<tSkeleton> Skeletons;  |
| 236 |   |
| 237 | // These may reference materials and skeletons.  |
| 238 | tItList<tPolyModel> PolyModels;  |
| 239 |   |
| 240 | // These may reference poly-models.  |
| 241 | tItList<tLodGroup> LodGroups;  |
| 242 |   |
| 243 | // Instances may reference anything above.  |
| 244 | tItList<tInstance> Instances;  |
| 245 |   |
| 246 | // Selection sets may reference instances.  |
| 247 | tItList<tSelection> Selections;  |
| 248 |   |
| 249 | // These are always the version numbers of the last file loaded.  |
| 250 | uint32 MajorVersion = SceneMajorVersion;  |
| 251 | uint32 MinorVersion = SceneMinorVersion;  |
| 252 |   |
| 253 | // Used to assign new IDs sequentially.  |
| 254 | uint32 NextCameraID = 0;  |
| 255 | uint32 NextLightID = 0;  |
| 256 | uint32 NextPathID = 0;  |
| 257 | uint32 NextMaterialID = 0;  |
| 258 | uint32 NextSkeletonID = 0;  |
| 259 | uint32 NextPolyModelID = 0;  |
| 260 | uint32 NextLodGroupID = 0;  |
| 261 | uint32 NextInstanceID = 0;  |
| 262 | uint32 NextSelectionID = 0;  |
| 263 | };  |
| 264 |   |
| 265 |   |
| 266 | }  |
| 267 | |