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 | |