- initial commit of Genesis3D 1.6
[genesis3d.git] / GBSPLib / GBSPPREP.CPP
1 /****************************************************************************************/\r
2 /*  GBSPPrep.cpp                                                                        */\r
3 /*                                                                                      */\r
4 /*  Author: John Pollard                                                                */\r
5 /*  Description: Saves non GFX data to GFX data (GFX data is data on disk)              */\r
6 /*                                                                                      */\r
7 /*  The contents of this file are subject to the Genesis3D Public License               */\r
8 /*  Version 1.01 (the "License"); you may not use this file except in                   */\r
9 /*  compliance with the License. You may obtain a copy of the License at                */\r
10 /*  http://www.genesis3d.com                                                            */\r
11 /*                                                                                      */\r
12 /*  Software distributed under the License is distributed on an "AS IS"                 */\r
13 /*  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See                */\r
14 /*  the License for the specific language governing rights and limitations              */\r
15 /*  under the License.                                                                  */\r
16 /*                                                                                      */\r
17 /*  The Original Code is Genesis3D, released March 25, 1999.                            */\r
18 /*Genesis3D Version 1.1 released November 15, 1999                            */\r
19 /*  Copyright (C) 1999 WildTangent, Inc. All Rights Reserved           */\r
20 /*                                                                                      */\r
21 /****************************************************************************************/\r
22 #include <Windows.h>\r
23 #include <Stdio.h>\r
24 \r
25 \r
26 #include "GBSPPrep.h"\r
27 #include "GBSPFile.h"\r
28 #include "Poly.h"               // For Planes, and NumPlanes\r
29 #include "BSP.h"\r
30 #include "Map.h"                // For texture\r
31 #include "Texture.h"\r
32 #include "Portals.h"\r
33 #include "Leaf.h"\r
34 \r
35 #include "VFile.h"\r
36 #include "Ram.h"\r
37 \r
38 geBoolean       SaveGFXModelData(geVFile *f);\r
39 geBoolean       SaveGFXNodes(geVFile *f);\r
40 geBoolean       SaveGFXPortals(geVFile *f);\r
41 geBoolean       SaveGFXBNodes(geVFile *f);\r
42 geBoolean       SaveGFXLeafs(geVFile *f);\r
43 geBoolean       SaveGFXClusters(geVFile *f);            // CHANGE: CLUSTER\r
44 geBoolean       SaveGFXAreasAndPortals(geVFile *f);\r
45 geBoolean       SaveGFXFaces(geVFile *f);\r
46 geBoolean       SaveGFXLeafSides(geVFile *f);\r
47 geBoolean       SaveGFXVerts(geVFile *f);\r
48 geBoolean       SaveGFXVertIndexList(geVFile *f);\r
49 geBoolean       SaveGFXPlanes(geVFile *f);\r
50 geBoolean       SaveGFXTextures(geVFile *f);\r
51 geBoolean       SaveGFXEntData(geVFile *f);\r
52 geBoolean       SaveGFXMotionData(geVFile *VFile);\r
53 \r
54 char    VisFile[300];\r
55 \r
56 int32 NumSolidLeafs;\r
57 \r
58 geBoolean ConvertGBSPToFile(char *FileName)\r
59 {\r
60         geVFile         *f;\r
61         GBSP_Chunk      Chunk;\r
62 \r
63         strcpy(VisFile, FileName);\r
64 \r
65         if (!FixModelTJunctions())\r
66         {\r
67                 GHook.Error("ConvertGBSPToFile:  FixModelTJunctions failed.\n");\r
68                 return GE_FALSE;\r
69         }\r
70 \r
71         GFXVertIndexList = GE_RAM_ALLOCATE_ARRAY(int32,TotalIndexVerts);\r
72         NumGFXVerts = NumWeldedVerts;\r
73         GFXVerts = WeldedVerts;\r
74 \r
75         // Go through all the bsp models and setup data that the gfxmodels need\r
76         if (!PrepAllGBSPModels())\r
77         {\r
78                 GHook.Error("ConvertGBSPToFile:  Could not Prep Models.\n");\r
79                 return GE_FALSE;\r
80         }\r
81 \r
82         f = geVFile_OpenNewSystem(NULL, GE_VFILE_TYPE_DOS, FileName, NULL, GE_VFILE_OPEN_CREATE);\r
83 \r
84         if (!f)\r
85         {\r
86                 GHook.Error("ConvertGBSPToFile:  geVFile_OpenNewSystem failed.\n");\r
87                 return GE_FALSE;\r
88         }\r
89 \r
90         strcpy(GBSPHeader.TAG, "GBSP");\r
91         GBSPHeader.TAG[4] = NULL;\r
92 \r
93         GBSPHeader.Version = GBSP_VERSION;\r
94 \r
95         // Record the time the bsp was saved...\r
96         GetSystemTime(&GBSPHeader.BSPTime);\r
97 \r
98         Chunk.Type = GBSP_CHUNK_HEADER;\r
99         Chunk.Size = sizeof(GBSP_Header);\r
100         Chunk.Elements = 1;\r
101         WriteChunk(&Chunk, (void*)&GBSPHeader, f);\r
102 \r
103         // HACK!  Just point these to the GBSP versions, but reset them below...\r
104         NumGFXLeafSides = NumLeafSides;\r
105         GFXLeafSides = (GFX_LeafSide*)LeafSides;\r
106         \r
107         //GHook.Printf("Saving GFX Model Data\n");\r
108         if (!SaveGFXModelData(f))\r
109         {\r
110                 GHook.Error("ConvertGBSPToFile:  SaveGFXModelData failed.\n");\r
111                 return GE_FALSE;\r
112         }\r
113         if (!SaveGFXNodes(f))\r
114                 return GE_FALSE;\r
115         if (!SaveGFXLeafs(f))\r
116         {\r
117                 GHook.Error("ConvertGBSPToFile:  SaveGFXLeafs failed.\n");\r
118                 return GE_FALSE;\r
119         }\r
120         if (!SaveGFXClusters(f))\r
121                 return GE_FALSE;\r
122         if (!SaveGFXAreasAndPortals(f))\r
123                 return GE_FALSE;\r
124         if (!SaveGFXLeafSides(f))\r
125                 return GE_FALSE;\r
126         if (!SaveGFXFaces(f))\r
127                 return GE_FALSE;\r
128         if (!SaveGFXPlanes(f))\r
129                 return GE_FALSE;\r
130         if (!SaveGFXVerts(f))\r
131                 return GE_FALSE;\r
132         if (!SaveGFXVertIndexList(f))\r
133                 return GE_FALSE;\r
134         if (!SaveGFXTextures(f))\r
135                 return GE_FALSE;\r
136         if (!SaveGFXEntData(f))\r
137                 return GE_FALSE;\r
138         if (!SaveGFXMotionData(f))\r
139                 return GE_FALSE;\r
140         \r
141         Chunk.Type = GBSP_CHUNK_END;\r
142         Chunk.Elements = 0;\r
143         Chunk.Size = 0;\r
144         WriteChunk(&Chunk, NULL, f);\r
145 \r
146         geVFile_Close(f);\r
147 \r
148         GHook.Printf(" --- Save GBSP File --- \n");\r
149         \r
150         GHook.Printf("Num Models           : %5i, %6i\n", NumBSPModels, NumBSPModels*sizeof(GFX_Model));\r
151         GHook.Printf("Num Nodes            : %5i, %6i\n", NumGFXNodes, NumGFXNodes*sizeof(GFX_Node));\r
152         GHook.Printf("Num Solid Leafs      : %5i, %6i\n", NumSolidLeafs, NumSolidLeafs*sizeof(GFX_Leaf));\r
153         GHook.Printf("Num Total Leafs      : %5i, %6i\n", NumGFXLeafs, NumGFXLeafs*sizeof(GFX_Leaf));\r
154         GHook.Printf("Num Clusters         : %5i, %6i\n", NumGFXClusters, NumGFXClusters*sizeof(GFX_Cluster));\r
155         GHook.Printf("Num Areas            : %5i, %6i\n", NumGFXAreas-1, (NumGFXAreas-1)*sizeof(GFX_Area));\r
156         GHook.Printf("Num Area Portals     : %5i, %6i\n", NumGFXAreaPortals, NumGFXAreaPortals*sizeof(GFX_AreaPortal));\r
157         GHook.Printf("Num Leafs Sides      : %5i, %6i\n", NumGFXLeafSides, NumGFXLeafSides*sizeof(GFX_LeafSide));\r
158         GHook.Printf("Num Planes           : %5i, %6i\n", NumPlanes, NumPlanes*sizeof(GBSP_Plane));\r
159         GHook.Printf("Num Faces            : %5i, %6i\n", NumGFXFaces, NumGFXFaces*sizeof(GFX_Face));\r
160         GHook.Printf("Num Leaf Faces       : %5i, %6i\n", NumGFXLeafFaces, NumGFXLeafFaces*sizeof(int32));\r
161         GHook.Printf("Num Vert Index       : %5i, %6i\n", NumGFXVertIndexList, NumGFXVertIndexList*sizeof(int32));\r
162         GHook.Printf("Num Verts            : %5i, %6i\n", NumGFXVerts, NumGFXVerts*sizeof(geVec3d));\r
163         GHook.Printf("Num FaceInfo         : %5i, %6i\n", NumGFXTexInfo, NumGFXTexInfo*sizeof(GFX_TexInfo));\r
164         GHook.Printf("Num Textures         : %5i, %6i\n", NumGFXTextures, NumGFXTextures*sizeof(GFX_Texture));\r
165         GHook.Printf("Motion Data Size     :        %6i\n", NumGFXMotionBytes);\r
166         GHook.Printf("Tex Data Size        :        %6i\n", NumGFXTexData);\r
167 \r
168         geRam_Free(GFXVertIndexList);\r
169         GFXVertIndexList = NULL;\r
170         NumGFXVertIndexList = 0;\r
171         \r
172         //geRam_Free(GFXVerts);\r
173         GFXVerts = NULL;\r
174 \r
175         NumGFXEntData = 0;\r
176 \r
177         // Reset these back, since we did not actually create them, we just\r
178         // pointed them to the GBSP_LeafSide structure version (same structure size/type)\r
179         GFXLeafSides = NULL;\r
180         NumGFXLeafSides = 0;\r
181 \r
182         FreeGBSPFile();\r
183 \r
184         return GE_TRUE;\r
185 }\r
186 \r
187 geBoolean SaveGFXModelData(geVFile *f)\r
188 {\r
189         int32           i;\r
190         GBSP_Chunk      Chunk;\r
191         GFX_Model       GModel;\r
192 \r
193         Chunk.Type = GBSP_CHUNK_MODELS;\r
194         Chunk.Size = sizeof(GFX_Model);\r
195         Chunk.Elements = NumBSPModels;\r
196 \r
197         WriteChunk(&Chunk, NULL, f);\r
198 \r
199         for (i=0; i< NumBSPModels; i++)\r
200         {\r
201                 // FIXME:  Make a (BSPModel ---> GFXModel) function\r
202                 GModel.RootNode[0] = BSPModels[i].RootNodeID[0];\r
203                 GModel.Origin = BSPModels[i].Origin;\r
204                 GModel.Mins = BSPModels[i].Mins;\r
205                 GModel.Maxs = BSPModels[i].Maxs;\r
206                 GModel.RootNode[1] = BSPModels[i].RootNodeID[1];\r
207                 GModel.FirstFace = BSPModels[i].FirstFace;\r
208                 GModel.NumFaces = BSPModels[i].NumFaces;\r
209                 GModel.FirstLeaf = BSPModels[i].FirstLeaf;\r
210                 GModel.NumLeafs = BSPModels[i].NumLeafs;\r
211                 GModel.FirstCluster = BSPModels[i].FirstCluster;\r
212                 GModel.NumClusters = BSPModels[i].NumClusters;\r
213                 GModel.Areas[0] = BSPModels[i].Areas[0];\r
214                 GModel.Areas[1] = BSPModels[i].Areas[1];\r
215                 if (geVFile_Write(f, &GModel, sizeof(GFX_Model)) != GE_TRUE)\r
216                 {\r
217                         GHook.Error("SaveGFXModelData:  There was an error writing the model.\n");\r
218                         return GE_FALSE;\r
219                 }\r
220         }       \r
221         \r
222         return GE_TRUE; \r
223 }\r
224 \r
225 geBoolean SaveGFXNodes_r(GBSP_Node *Node, geVFile *f)\r
226 {\r
227         GFX_Node        GNode;\r
228 \r
229         if (Node->PlaneNum == PLANENUM_LEAF)\r
230                 return GE_TRUE;\r
231         \r
232         GNode.Children[0] = Node->ChildrenID[0];\r
233         GNode.Children[1] = Node->ChildrenID[1];\r
234         GNode.NumFaces = Node->NumFaces;\r
235         GNode.FirstFace = Node->FirstFace;\r
236         GNode.PlaneNum = Node->PlaneNum;\r
237         GNode.Mins = Node->Mins;\r
238         GNode.Maxs = Node->Maxs;\r
239 \r
240         if (geVFile_Write(f, &GNode, sizeof(GFX_Node)) != GE_TRUE)\r
241         {\r
242                 GHook.Error("SaveGFXNodes_r:  There was an error writing the node.\n");\r
243                 return GE_FALSE;\r
244         }\r
245 \r
246         if (!SaveGFXNodes_r(Node->Children[0], f))\r
247                 return GE_FALSE;\r
248 \r
249         if (!SaveGFXNodes_r(Node->Children[1], f))\r
250                 return GE_FALSE;\r
251 \r
252         return GE_TRUE;\r
253 }\r
254 \r
255 geBoolean SaveGFXNodes(geVFile *f)\r
256 {\r
257         int32           i;\r
258         GBSP_Chunk      Chunk;\r
259 \r
260         Chunk.Type = GBSP_CHUNK_NODES;\r
261         Chunk.Size = sizeof(GFX_Node);\r
262         Chunk.Elements = NumGFXNodes;\r
263 \r
264         WriteChunk(&Chunk, NULL, f);\r
265         \r
266         for (i=0; i< NumBSPModels; i++)\r
267         {\r
268                 if (!SaveGFXNodes_r(BSPModels[i].RootNode[0], f))\r
269                         return GE_FALSE;\r
270         }\r
271 \r
272         return GE_TRUE;\r
273 }\r
274 \r
275 geBoolean SaveGFXPortals_r(GBSP_Node *Node, geVFile *f)\r
276 {\r
277         GBSP_Portal     *Portal;\r
278         GFX_Portal      GPortal;\r
279         int32           Side, i;\r
280         geVec3d         Origin;\r
281         GBSP_Poly       *Poly;\r
282 \r
283         if (Node->PlaneNum == PLANENUM_LEAF)\r
284         {\r
285                 if (Node->Contents & BSP_CONTENTS_SOLID2)\r
286                         return GE_TRUE; \r
287 \r
288                 for (Portal = Node->Portals; Portal; Portal = Portal->Next[Side])\r
289                 {\r
290                         Side = (Portal->Nodes[1] == Node);\r
291                         \r
292                         if (!(Portal->Nodes[0]->Contents & BSP_CONTENTS_SOLID2) &&\r
293                                 !(Portal->Nodes[1]->Contents & BSP_CONTENTS_SOLID2))\r
294                         {\r
295                                 Poly = Portal->Poly;\r
296                                 geVec3d_Clear(&Origin);\r
297                                 for (i=0; i< Poly->NumVerts; i++)\r
298                                         geVec3d_Add(&Origin, &Poly->Verts[i], &Origin);\r
299                                 for (i=0; i<3; i++)\r
300                                         VectorToSUB(Origin, i) /= Poly->NumVerts;\r
301 \r
302                                 GPortal.Origin = Origin;\r
303                                 GPortal.LeafTo = Portal->Nodes[!Side]->PortalLeafNum;\r
304 \r
305                                 if (geVFile_Write(f, &GPortal, sizeof(GFX_Portal)) != GE_TRUE)\r
306                                 {\r
307                                         GHook.Error("SaveGFXPortals_r:  There was an error writing the portal.\n");\r
308                                         return GE_FALSE;\r
309                                 }\r
310                         }\r
311                 }\r
312                 return GE_TRUE;\r
313         }\r
314         \r
315         if (!SaveGFXPortals_r(Node->Children[0], f))\r
316                 return GE_FALSE;\r
317 \r
318         if (!SaveGFXPortals_r(Node->Children[1], f))\r
319                 return GE_FALSE;\r
320 \r
321         return GE_TRUE;\r
322 }\r
323 \r
324 geBoolean SaveGFXPortals(geVFile *f)\r
325 {\r
326         int32           i;\r
327         GBSP_Chunk      Chunk;\r
328 \r
329         Chunk.Type = GBSP_CHUNK_PORTALS;\r
330         Chunk.Size = sizeof(GFX_Portal);\r
331         Chunk.Elements = NumGFXPortals;\r
332 \r
333         WriteChunk(&Chunk, NULL, f);\r
334         \r
335         for (i=0; i< NumBSPModels; i++)\r
336         {\r
337                 if (!SaveGFXPortals_r(BSPModels[i].RootNode[0], f))\r
338                         return GE_FALSE;\r
339         }\r
340 \r
341         return GE_TRUE;\r
342 }\r
343 \r
344 geBoolean SaveGFXBNodes_r(GBSP_Node *Node, geVFile *f)\r
345 {\r
346         GFX_BNode       GBNode;\r
347 \r
348         if (Node->PlaneNum == PLANENUM_LEAF)\r
349                 return GE_TRUE;\r
350         \r
351         GBNode.Children[0] = Node->ChildrenID[0];\r
352         GBNode.Children[1] = Node->ChildrenID[1];\r
353         GBNode.PlaneNum = Node->PlaneNum;\r
354         //GBNode.PlaneSide = Node->PlaneSide;\r
355 \r
356         if (geVFile_Write(f, &GBNode, sizeof(GFX_BNode)) != GE_TRUE)\r
357         {\r
358                 GHook.Error("SaveGFXBNodes_r:  There was an error writing the node.\n");\r
359                 return GE_FALSE;\r
360         }\r
361 \r
362         if (!SaveGFXBNodes_r(Node->Children[0], f))\r
363                 return GE_FALSE;\r
364         if (!SaveGFXBNodes_r(Node->Children[1], f))\r
365                 return GE_FALSE;\r
366 \r
367         return GE_TRUE;\r
368 }\r
369 \r
370 geBoolean SaveGFXBNodes(geVFile *f)\r
371 {\r
372         int32           i;\r
373         GBSP_Chunk      Chunk;\r
374 \r
375         Chunk.Type = GBSP_CHUNK_BNODES;\r
376         Chunk.Size = sizeof(GFX_BNode);\r
377         Chunk.Elements = NumGFXBNodes;\r
378 \r
379         WriteChunk(&Chunk, NULL, f);\r
380         \r
381         for (i=0; i< NumBSPModels; i++)\r
382                 if (!SaveGFXBNodes_r(BSPModels[i].RootNode[1], f))\r
383                         return GE_FALSE;\r
384 \r
385         return GE_TRUE;\r
386 }\r
387 \r
388 int32 TotalLeafSize;\r
389 \r
390 //========================================================================================\r
391 //      SaveGFXLeafs_r\r
392 //========================================================================================\r
393 geBoolean SaveGFXLeafs_r(GBSP_Node *Node, geVFile *f)\r
394 {\r
395         GFX_Leaf        GLeaf;\r
396         int32           i;\r
397 \r
398         if (Node->PlaneNum == PLANENUM_LEAF)\r
399         {\r
400                 GLeaf.Contents = Node->Contents;\r
401 \r
402                 #if 0\r
403                 if (!GLeaf.Contents)\r
404                         GLeaf.Contents = BSP_CONTENTS_AIR;\r
405                 #endif\r
406 \r
407                 GLeaf.Mins = Node->Mins;\r
408                 GLeaf.Maxs = Node->Maxs;\r
409 \r
410                 GLeaf.FirstFace = NumGFXLeafFaces;\r
411                 GLeaf.FirstPortal = Node->FirstPortal;\r
412                 GLeaf.NumPortals = Node->NumPortals;\r
413 \r
414                 GLeaf.Cluster = Node->Cluster;          // CHANGE: CLUSTER\r
415                 GLeaf.Area = Node->Area;\r
416 \r
417                 GLeaf.FirstSide = Node->FirstSide;\r
418                 GLeaf.NumSides = Node->NumSides;\r
419 \r
420                 GLeaf.NumFaces = 0;\r
421 \r
422                 for (i=0; i< Node->NumLeafFaces; i++)\r
423                 {\r
424                         if (!Node->LeafFaces[i]->Visible)\r
425                                 continue;\r
426                         \r
427                         // Don't output mark face if it was skipped in the face output stage\r
428                         // (or it will reference an invalid face...)\r
429                         if (Node->LeafFaces[i]->NumIndexVerts <= 0)\r
430                                 continue;\r
431 \r
432                         GFXLeafFaces[NumGFXLeafFaces] = Node->LeafFaces[i]->OutputNum;\r
433                         NumGFXLeafFaces++;\r
434 \r
435                         GLeaf.NumFaces++;\r
436                 }\r
437 \r
438                 TotalLeafSize += sizeof(GFX_Leaf);\r
439 \r
440                 if (geVFile_Write(f, &GLeaf, sizeof(GFX_Leaf)) != GE_TRUE)\r
441                 {\r
442                         GHook.Error("SaveGFXLeafs_r:  There was an error writing the leaf.\n");\r
443                         return GE_FALSE;\r
444                 }\r
445                 return GE_TRUE;\r
446         }\r
447 \r
448         if (!SaveGFXLeafs_r(Node->Children[0], f))\r
449                 return GE_FALSE;\r
450         if (!SaveGFXLeafs_r(Node->Children[1], f))\r
451                 return GE_FALSE;\r
452 \r
453         return GE_TRUE;\r
454 }\r
455 \r
456 //========================================================================================\r
457 //      SaveGFXLeafs\r
458 //========================================================================================\r
459 geBoolean SaveGFXLeafs(geVFile *f)\r
460 {\r
461         int32           i;\r
462         GBSP_Chunk      Chunk;\r
463 \r
464         Chunk.Type = GBSP_CHUNK_LEAFS;\r
465         Chunk.Size = sizeof(GFX_Leaf);\r
466         Chunk.Elements = NumGFXLeafs;\r
467 \r
468         WriteChunk(&Chunk, NULL, f);\r
469 \r
470         TotalLeafSize = 0;\r
471 \r
472         // NumGFXLeafFaces was counted earlier in the PrepGfxNodes Stage\r
473         GFXLeafFaces = GE_RAM_ALLOCATE_ARRAY(int32,NumGFXLeafFaces);\r
474 \r
475         NumGFXLeafFaces = 0;            // We must reset this...\r
476 \r
477         for (i=0; i< NumBSPModels; i++)\r
478         {\r
479                 // Save all the leafs for this model\r
480                 if (!SaveGFXLeafs_r(BSPModels[i].RootNode[0], f))\r
481                 {\r
482                         GHook.Error("SaveGFXLeafs:  SaveGFXLeafs_r failed.\n");\r
483                         return GE_FALSE;\r
484                 }\r
485         }\r
486 \r
487         if (TotalLeafSize != Chunk.Size * Chunk.Elements)\r
488         {\r
489                 GHook.Error("SaveGFXLeafs:  Leaf sizes don't match.\n");\r
490         //      return GE_FALSE;\r
491         }\r
492 \r
493         // Save gfx leaf faces here...\r
494         Chunk.Type = GBSP_CHUNK_LEAF_FACES;\r
495         Chunk.Size = sizeof(int32);\r
496         Chunk.Elements = NumGFXLeafFaces;\r
497 \r
498         WriteChunk(&Chunk, GFXLeafFaces, f);\r
499 \r
500         return GE_TRUE;\r
501 }\r
502 \r
503 // CHANGE: CLUSTER\r
504 //========================================================================================\r
505 // SaveGFXClusters\r
506 //========================================================================================\r
507 geBoolean SaveGFXClusters(geVFile *f)\r
508 {\r
509         int32           i;\r
510         GBSP_Chunk      Chunk;\r
511         GFX_Cluster     GCluster;\r
512 \r
513         NumGFXClusters = NumLeafClusters;\r
514         Chunk.Type = GBSP_CHUNK_CLUSTERS;\r
515         Chunk.Size = sizeof(GFX_Cluster);\r
516         Chunk.Elements = NumGFXClusters;\r
517 \r
518         WriteChunk(&Chunk, NULL, f);\r
519 \r
520         for (i=0; i< NumGFXClusters; i++)\r
521         {\r
522                 GCluster.VisOfs = -1;\r
523 \r
524                 if (geVFile_Write(f, &GCluster, sizeof(GFX_Cluster)) != GE_TRUE)\r
525                 {\r
526                         GHook.Error("SaveGFXClusters:  There was an error saving the cluster.\n");\r
527                         return GE_FALSE;\r
528                 }\r
529         }\r
530 \r
531         return GE_TRUE;\r
532 }\r
533 //========================================================================================\r
534 //      SaveGFXAreasAndPortals\r
535 //========================================================================================\r
536 geBoolean SaveGFXAreasAndPortals(geVFile *f)\r
537 {\r
538         GBSP_Chunk      Chunk;\r
539 \r
540         //\r
541         // Save the areas first\r
542         //\r
543         Chunk.Type = GBSP_CHUNK_AREAS;\r
544         Chunk.Size = sizeof(GFX_Area);\r
545         Chunk.Elements = NumGFXAreas;\r
546 \r
547         WriteChunk(&Chunk, GFXAreas, f);\r
548 \r
549         //\r
550         //      Then, save the areaportals\r
551         //\r
552         Chunk.Type = GBSP_CHUNK_AREA_PORTALS;\r
553         Chunk.Size = sizeof(GFX_AreaPortal);\r
554         Chunk.Elements = NumGFXAreaPortals;\r
555 \r
556         WriteChunk(&Chunk, GFXAreaPortals, f);\r
557 \r
558         return GE_TRUE;\r
559 }\r
560 \r
561 //========================================================================================\r
562 //      SaveGFXFaces_r\r
563 //========================================================================================\r
564 geBoolean SaveGFXFaces_r(GBSP_Node *Node, geVFile *f)\r
565 {\r
566         GBSP_Face       *Face;\r
567         GFX_Face        GFace;\r
568 \r
569         if (Node->PlaneNum == PLANENUM_LEAF)\r
570                 return GE_TRUE;\r
571         \r
572         for (Face = Node->Faces; Face; Face = Face->Next)\r
573         {\r
574                 if (!Face->Visible)\r
575                         continue;\r
576 \r
577                 if (Face->Merged || Face->Split[0] || Face->Split[1])\r
578                         continue;\r
579 \r
580                 if (Face->NumIndexVerts > 0)\r
581                 {\r
582                         GFace.FirstVert = Face->FirstIndexVert;\r
583                         GFace.NumVerts = Face->NumIndexVerts;\r
584                         GFace.PlaneNum = Face->PlaneNum;\r
585                         GFace.PlaneSide = Face->PlaneSide;\r
586                         GFace.TexInfo = Face->TexInfo;\r
587                         #pragma message ("Make LWidth/Height correct!")\r
588                         GFace.LWidth = 0;\r
589                         GFace.LHeight = 0;\r
590                         GFace.LightOfs = -1;            // No light info yet\r
591                         GFace.LTypes[0] = 255;          // Of course, no styles yet either\r
592                         GFace.LTypes[1] = 255;\r
593                         GFace.LTypes[2] = 255;\r
594                         GFace.LTypes[3] = 255;\r
595 \r
596                         if (geVFile_Write(f, &GFace, sizeof(GFX_Face)) != GE_TRUE)\r
597                         {\r
598                                 GHook.Error("SaveGFXFace_r:  There was an error writing the face.\n");\r
599                                 return GE_FALSE;\r
600                         }\r
601                 }\r
602         }\r
603 \r
604         if (!SaveGFXFaces_r(Node->Children[0], f))\r
605                 return GE_FALSE;\r
606 \r
607         if (!SaveGFXFaces_r(Node->Children[1], f))\r
608                 return GE_FALSE;\r
609 \r
610         return GE_TRUE;\r
611 }\r
612 \r
613 //========================================================================================\r
614 //      SaveGFXFaces\r
615 //========================================================================================\r
616 geBoolean SaveGFXFaces(geVFile *f)\r
617 {\r
618         int32           i;\r
619         GBSP_Chunk      Chunk;\r
620 \r
621         Chunk.Type = GBSP_CHUNK_FACES;\r
622         Chunk.Size = sizeof(GFX_Face);\r
623         Chunk.Elements = NumGFXFaces;\r
624 \r
625         WriteChunk(&Chunk, NULL, f);\r
626         \r
627         for (i=0; i< NumBSPModels; i++)\r
628                 if (!SaveGFXFaces_r(BSPModels[i].RootNode[0], f))\r
629                         return GE_FALSE;\r
630 \r
631         return GE_TRUE;\r
632 }\r
633 \r
634 //========================================================================================\r
635 //      SaveGFXPlanes\r
636 //========================================================================================\r
637 geBoolean SaveGFXPlanes(geVFile *f)\r
638 {\r
639         int32                   i;\r
640         GBSP_Chunk      Chunk;\r
641         GFX_Plane       GPlane;\r
642 \r
643         NumGFXPlanes = NumPlanes;\r
644         Chunk.Type = GBSP_CHUNK_PLANES;\r
645         Chunk.Size = sizeof(GFX_Plane);\r
646         Chunk.Elements = NumGFXPlanes;\r
647 \r
648         WriteChunk(&Chunk, NULL, f);\r
649 \r
650         for (i=0; i< NumGFXPlanes; i++)\r
651         {\r
652                 GPlane.Normal = Planes[i].Normal;\r
653                 GPlane.Dist = Planes[i].Dist;\r
654                 GPlane.Type = Planes[i].Type;\r
655 \r
656                 if (geVFile_Write(f, &GPlane, sizeof(GFX_Plane)) != GE_TRUE)\r
657                 {\r
658                         GHook.Error("SaveGFXPlanes:  There was an error saving the plane.\n");\r
659                         return GE_FALSE;\r
660                 }\r
661         }\r
662 \r
663         return GE_TRUE;\r
664 }\r
665 \r
666 //========================================================================================\r
667 //      SaveGFXLeafSides\r
668 //========================================================================================\r
669 geBoolean SaveGFXLeafSides(geVFile *f)\r
670 {\r
671         GBSP_Chunk      Chunk;\r
672 \r
673         Chunk.Type = GBSP_CHUNK_LEAF_SIDES;\r
674         Chunk.Size = sizeof(GFX_LeafSide);\r
675         Chunk.Elements = NumGFXLeafSides;\r
676 \r
677         if (!WriteChunk(&Chunk, GFXLeafSides, f))\r
678         {\r
679                 GHook.Error("There was an error writing the verts.\n");\r
680                 return GE_FALSE;\r
681         }\r
682 \r
683         return GE_TRUE;\r
684 }\r
685 \r
686 //========================================================================================\r
687 //      SaveGFXVerts\r
688 //========================================================================================\r
689 geBoolean SaveGFXVerts(geVFile *f)\r
690 {\r
691         GBSP_Chunk      Chunk;\r
692 \r
693         Chunk.Type = GBSP_CHUNK_VERTS;\r
694         Chunk.Size = sizeof(geVec3d);\r
695         Chunk.Elements = NumGFXVerts;\r
696 \r
697         if (!WriteChunk(&Chunk, GFXVerts, f))\r
698         {\r
699                 GHook.Error("There was an error writing the verts.\n");\r
700                 return GE_FALSE;\r
701         }\r
702 \r
703         return GE_TRUE;\r
704 }\r
705 \r
706 //========================================================================================\r
707 //      SaveGFXVertIndexList\r
708 //========================================================================================\r
709 geBoolean SaveGFXVertIndexList(geVFile *f)\r
710 {\r
711         GBSP_Chunk      Chunk;\r
712 \r
713         Chunk.Type = GBSP_CHUNK_VERT_INDEX;\r
714         Chunk.Size = sizeof(int32);\r
715         Chunk.Elements = NumGFXVertIndexList;\r
716 \r
717         if (!WriteChunk(&Chunk, GFXVertIndexList, f))\r
718         {\r
719                 GHook.Error("SaveGFXvertIndexList:  There was an error saving the VertIndexList.\n");\r
720                 return GE_FALSE;\r
721         }\r
722 \r
723         return GE_TRUE;\r
724 }\r
725 \r
726 //========================================================================================\r
727 //      PrepGFXNode\r
728 //========================================================================================\r
729 void PrepGFXNode(GBSP_Node *Node)\r
730 {\r
731         GBSP_Face       *Face;\r
732         int32           NumFaces;\r
733         int32           i;\r
734         geVec3d         *Verts;\r
735 \r
736         NumFaces = 0;\r
737         Node->FirstFace = NumGFXFaces;\r
738 \r
739         for (Face = Node->Faces; Face; Face = Face->Next)\r
740         {\r
741                 if (!Face->Visible)\r
742                         continue;\r
743 \r
744                 if (Face->Merged || Face->Split[0] || Face->Split[1])\r
745                         continue;\r
746 \r
747                 // Skip output of face, if IndexVerts not > 0\r
748                 // NOTE - The leaf faces output stage will also skip these same faces...\r
749                 if (Face->NumIndexVerts <= 0)\r
750                         continue;\r
751 \r
752                 Face->FirstIndexVert = NumGFXVertIndexList;\r
753                 Face->OutputNum = NumGFXFaces;\r
754 \r
755                 Verts = Face->Poly->Verts;\r
756                 \r
757                 for (i=0; i< Face->NumIndexVerts; i++)\r
758                 {\r
759                         GFXVertIndexList[NumGFXVertIndexList] = Face->IndexVerts[i];\r
760                         Verts++;\r
761                         NumGFXVertIndexList++;\r
762                 }\r
763                 NumGFXFaces ++;\r
764                 NumFaces++;\r
765         }\r
766 \r
767         Node->NumFaces = NumFaces;\r
768 }\r
769 \r
770 //========================================================================================\r
771 //      PrepGFXNodes_r\r
772 //      Store current nodes for model in GFXNodes/GFXLeafs so they can be saved to disk\r
773 //========================================================================================\r
774 int32 PrepGFXNodes_r(int32 Original, GBSP_Node *Node)\r
775 {\r
776         int32                   CurrentNode;\r
777 \r
778         // Prep the leaf and it's portals\r
779         if (Node->PlaneNum == PLANENUM_LEAF)\r
780         {\r
781                 if (Node->Contents & BSP_CONTENTS_SOLID2)\r
782                         NumSolidLeafs++;                // Remember how many solid leafs there are\r
783 \r
784                 Node->NumPortals = 0;\r
785                 Node->FirstPortal = -1;\r
786 \r
787                 // To be able to save out portal LeafTo's\r
788                 Node->PortalLeafNum = NumGFXLeafs;\r
789 \r
790                 //  Count num gfx leaf faces here, so we know how big to make the array\r
791                 //      later, when they are saved out...\r
792                 NumGFXLeafFaces += Node->NumLeafFaces;\r
793 \r
794                 #if 0\r
795                 {\r
796                         GBSP_Portal     *Portal;\r
797                         int32                   Side;\r
798 \r
799                         // Setup leaf portals\r
800                         Node->FirstPortal = NumGFXPortals;\r
801                         for (Portal = Node->Portals; Portal; Portal = Portal->Next[Side])\r
802                         {\r
803                                 Side = (Portal->Nodes[1] == Node);\r
804 \r
805                                 if (!(Portal->Nodes[0]->Contents & BSP_CONTENTS_SOLID2) &&\r
806                                         !(Portal->Nodes[1]->Contents & BSP_CONTENTS_SOLID2))\r
807                                 {\r
808                                         Node->NumPortals++;\r
809                                         NumGFXPortals++;\r
810                                 }\r
811                         }\r
812                 }\r
813                 #endif\r
814 \r
815                 // Increase the number of leafs\r
816                 NumGFXLeafs++;\r
817 \r
818                 return -(NumGFXLeafs);\r
819         }\r
820                 \r
821         CurrentNode = NumGFXNodes;\r
822 \r
823         PrepGFXNode(Node);\r
824 \r
825         NumGFXNodes++;\r
826 \r
827         Node->ChildrenID[0] = PrepGFXNodes_r(Node->ChildrenID[0], Node->Children[0]);\r
828         Node->ChildrenID[1] = PrepGFXNodes_r(Node->ChildrenID[1], Node->Children[1]);\r
829 \r
830         return CurrentNode;\r
831 }\r
832 \r
833 //typedef       unsigned char   RawPalette[256*3];\r
834                                 \r
835 geBoolean SaveGFXTextures(geVFile *f)\r
836 {\r
837         GBSP_Chunk      Chunk;\r
838         int32           Pos1, Pos2;\r
839         uint8           Data[256*256*4];\r
840         int32           Size, Width, Height, Offset, i;\r
841         char            *File;\r
842         DRV_Palette     Palette;\r
843         int TexNum;\r
844 \r
845         File = ValueForKey(&Entities[0], "TextureLib");\r
846         if (!File || !File[0])\r
847         {\r
848                 GHook.Error("SaveGFXTextures:  No TextureLib specified in map file.\n");\r
849                 return GE_FALSE;\r
850         }\r
851 \r
852         if (!InitTextureLib(File))\r
853                 return GE_FALSE;\r
854 \r
855         Offset = 0;\r
856         \r
857         geVFile_Tell(f, &Pos1);\r
858 \r
859         Chunk.Type = GBSP_CHUNK_TEXDATA;\r
860         Chunk.Size = 0;\r
861         Chunk.Elements = 1;\r
862 \r
863         WriteChunk(&Chunk, NULL, f);\r
864 \r
865         //GHook.Printf("Num Textures:  %i\n", NumTextures);\r
866 \r
867         for (i=0; i< NumTextures; i++)\r
868         {\r
869                 //GHook.Printf("Texture : %i, %s\n", i, Textures[i].Name);\r
870                 \r
871                 if (!GetTexture(Textures[i].Name, Data, &Size, &Width, &Height, f))\r
872                         return GE_FALSE;\r
873 \r
874                 Textures[i].Width = Width;\r
875                 Textures[i].Height = Height;\r
876                 Textures[i].Offset = NumGFXTexData;\r
877                 Textures[i].PaletteIndex = i;\r
878 \r
879                 NumGFXTexData += Size;\r
880         }\r
881 \r
882         geVFile_Tell(f, &Pos2);\r
883 \r
884         geVFile_Seek(f, Pos1, GE_VFILE_SEEKSET);\r
885 \r
886         Chunk.Type = GBSP_CHUNK_TEXDATA;\r
887         Chunk.Size = 1;\r
888         Chunk.Elements = NumGFXTexData;\r
889         WriteChunk(&Chunk, NULL, f);\r
890 \r
891         geVFile_Seek(f, Pos2, GE_VFILE_SEEKSET);\r
892 \r
893         // Now save textures\r
894         NumGFXTextures = NumTextures;\r
895         \r
896         Chunk.Type = GBSP_CHUNK_TEXTURES;\r
897         Chunk.Size = sizeof(GFX_Texture);\r
898         Chunk.Elements = NumGFXTextures;\r
899 \r
900         WriteChunk(&Chunk, NULL, f);\r
901 \r
902         if (geVFile_Write(f, (GFX_Texture*)Textures, sizeof(GFX_Texture) * NumGFXTextures) != GE_TRUE)\r
903         {\r
904                 GHook.Error("SaveGFXTexture:  There was an error saving the texture.\n");\r
905                 return GE_FALSE;\r
906         }\r
907 // added transparent textures\r
908         for(i=0;i<NumTexInfo;i++)\r
909         {\r
910                 TexNum = TexInfo[i].Texture;\r
911                 if(HasTextureAlpha(Textures[TexNum].Name)==GE_TRUE)\r
912                 {\r
913                         TexInfo[i].Flags |= TEXINFO_TRANS;\r
914                         TexInfo[i].Alpha = 255.0f;\r
915                 }\r
916         }\r
917 // end transparent textures\r
918 \r
919         // Now save tex info\r
920         NumGFXTexInfo = NumTexInfo;\r
921 \r
922         Chunk.Type = GBSP_CHUNK_TEXINFO;\r
923         Chunk.Size = sizeof(GFX_TexInfo);\r
924         Chunk.Elements = NumGFXTexInfo;\r
925 \r
926         WriteChunk(&Chunk, NULL, f);\r
927 \r
928         if (geVFile_Write(f, (GFX_TexInfo*)TexInfo, sizeof(GFX_TexInfo) * NumGFXTexInfo) != GE_TRUE)\r
929         {\r
930                 GHook.Error("SaveGFXTexture:  There was an error saving the tex info.\n");\r
931                 return GE_FALSE;\r
932         }\r
933 \r
934         // Save all of the palettes out, too\r
935         Chunk.Type = GBSP_CHUNK_PALETTES;\r
936         Chunk.Size = 256 * 3 * sizeof(unsigned char);\r
937         Chunk.Elements = NumTextures;\r
938 \r
939         WriteChunk(&Chunk, NULL, f);\r
940 \r
941         for (i=0; i< NumTextures; i++)\r
942         {\r
943                 //GHook.Printf("Texture : %i, %s\n", i, Textures[i].Name);\r
944                 \r
945                 if (!GetTexturePalette(Textures[i].Name, Palette))\r
946                         return GE_FALSE;\r
947 \r
948                 if      (geVFile_Write(f, &Palette[0], sizeof(Palette)) != GE_TRUE)\r
949                 {\r
950                         GHook.Error("There was an error saving the palettes");\r
951                         return GE_FALSE;\r
952                 }\r
953         }\r
954 \r
955         ShutdownTextureLib();\r
956 \r
957         return GE_TRUE;\r
958 }\r
959 \r
960 //========================================================================================\r
961 //      SaveGFXEntData\r
962 //========================================================================================\r
963 geBoolean SaveGFXEntData(geVFile *f)\r
964 {\r
965         geVFile_MemoryContext   Context;\r
966         geVFile                                 *MemFile;\r
967         GBSP_Chunk                              Chunk;\r
968 \r
969         // Start an empty memory file\r
970         Context.Data = NULL;\r
971         Context.DataLength = 0;\r
972 \r
973         MemFile = geVFile_OpenNewSystem(NULL, GE_VFILE_TYPE_MEMORY, NULL, &Context, GE_VFILE_OPEN_CREATE);\r
974 \r
975         if (!MemFile)\r
976                 return GE_FALSE;\r
977         \r
978         // Fill this file with the entitydata\r
979         if (!SaveEntityData(MemFile))\r
980         {\r
981                 geVFile_Close(MemFile);\r
982                 GHook.Error("SaveGFXEntData:  SaveEntityData failed.\n");\r
983                 return GE_FALSE;\r
984         }\r
985 \r
986         // Update the context with this data\r
987         if (!geVFile_UpdateContext(MemFile, &Context, sizeof(Context)))\r
988         {\r
989                 geVFile_Close(MemFile);\r
990                 return GE_FALSE;\r
991         }\r
992         \r
993         // Write the chunk out\r
994         Chunk.Type = GBSP_CHUNK_ENTDATA;\r
995         Chunk.Size = sizeof(uint8);\r
996         Chunk.Elements = Context.DataLength;\r
997 \r
998         if (!WriteChunk(&Chunk, Context.Data, f))\r
999         {\r
1000                 GHook.Error("SaveEntData:  There was an error saving the EntData.\n");\r
1001                 return GE_FALSE;\r
1002         }\r
1003 \r
1004         geVFile_Close(MemFile);\r
1005 \r
1006         return GE_TRUE;\r
1007 }\r
1008 \r
1009 //========================================================================================\r
1010 //========================================================================================\r
1011 void BeginGBSPModels(void)\r
1012 {\r
1013         NumLeafClusters = 0;\r
1014         NumSolidLeafs = 0;\r
1015         NumLeafSides = 0;\r
1016         NumLeafBevels = 0;\r
1017 \r
1018         // Clear all gfx variables\r
1019         NumGFXPortals = 0;\r
1020         NumGFXNodes = 0;\r
1021         NumGFXBNodes = 0;\r
1022         NumGFXLeafs = 0;\r
1023         NumGFXFaces = 0;\r
1024         NumGFXVerts = 0;\r
1025         NumGFXVertIndexList = 0;\r
1026         NumGFXLeafFaces = 0;\r
1027 \r
1028 }\r
1029 \r
1030 void FinalizeNodeMinMax(GBSP_Node *RootNode);\r
1031 \r
1032 //========================================================================================\r
1033 //      PrepGBSPModel\r
1034 //========================================================================================\r
1035 geBoolean PrepGBSPModel(GBSP_Model *Model, geBoolean SaveVis)\r
1036 {\r
1037         // Save vis file for vising model 0\r
1038         if (SaveVis)            \r
1039         {\r
1040                 // Create vis portals\r
1041                 if (!CreatePortals(Model->RootNode[0], Model, GE_TRUE))\r
1042                 {\r
1043                         GHook.Printf("PrepGBSPModel:  Could not create VIS portals.\n");\r
1044                         return GE_FALSE;\r
1045                 }\r
1046                 \r
1047                 // Mark clusters\r
1048                 Model->FirstCluster = NumLeafClusters;\r
1049                         \r
1050                 if (!CreateLeafClusters(Model->RootNode[0]))\r
1051                 {\r
1052                         GHook.Error("Could not create leaf clusters.\n");\r
1053                         return GE_FALSE;\r
1054                 }\r
1055                         \r
1056                 Model->NumClusters = NumLeafClusters - Model->FirstCluster;\r
1057 \r
1058                 if (!SavePortalFile(Model, VisFile))\r
1059                         return GE_FALSE;\r
1060 \r
1061                 // Free vis portals...\r
1062                 if (!FreePortals(Model->RootNode[0]))\r
1063                 {\r
1064                         GHook.Printf("PrepGBSPModel:  Could not free portals.\n");\r
1065                         return GE_FALSE;\r
1066                 }\r
1067                 \r
1068         }\r
1069         else    // Models > 0 are assumed simple and no vising performed, clusters are not needed either...\r
1070         {\r
1071                 Model->FirstCluster = -1;\r
1072                 Model->NumClusters = 0;\r
1073         }\r
1074 \r
1075         // Create the REAL structural portals\r
1076         if (!CreatePortals(Model->RootNode[0], Model, GE_FALSE))\r
1077         {\r
1078                 GHook.Printf("PrepGBSPModel:  Could not create REAL portals.\n");\r
1079                 return GE_FALSE;\r
1080         }\r
1081         \r
1082         // Create the leaf collision hulls for bevel bbox collisions\r
1083         if (!CreateLeafSides(Model->RootNode[0]))\r
1084         {\r
1085                 GHook.Error("Could not create leaf sides.\n");\r
1086                 return GE_FALSE;\r
1087         }\r
1088 \r
1089         // Create the area leafs\r
1090         if (Model == BSPModels)         // Only world needs areas set...\r
1091         if (!CreateAreas(Model->RootNode[0]))\r
1092         {\r
1093                 GHook.Error("Could not create Areas.\n");\r
1094                 return GE_FALSE;\r
1095         }\r
1096 \r
1097         //====\r
1098         Model->FirstFace = NumGFXFaces;\r
1099         Model->FirstLeaf = NumGFXLeafs;\r
1100                 \r
1101         // Prep the nodes, so we can save them out later to disk\r
1102         Model->RootNodeID[0] = PrepGFXNodes_r(Model->RootNodeID[0], Model->RootNode[0]);\r
1103 \r
1104         Model->NumFaces = NumGFXFaces - Model->FirstFace;\r
1105         Model->NumLeafs = NumGFXLeafs - Model->FirstLeaf;\r
1106         \r
1107         return GE_TRUE;\r
1108 }\r
1109 \r
1110 geBoolean PrepAllGBSPModels(void)\r
1111 {\r
1112         int32   i;\r
1113 \r
1114         // Restore verbose since BSP stage turns it off for entities\r
1115         Verbose = OriginalVerbose;\r
1116 \r
1117         for (i=0; i< NumBSPModels; i++)\r
1118         {\r
1119                 // Turn it back off for entities if asked to do so...\r
1120                 if (i > 0 && !EntityVerbose)\r
1121                         Verbose = GE_FALSE;\r
1122 \r
1123                 if (!PrepGBSPModel(&BSPModels[i], i == 0))\r
1124                 {\r
1125                         GHook.Error("PrepAllGBSPModels:  Could not prep model %i.\n", i);\r
1126                         return GE_FALSE;\r
1127                 }\r
1128         }\r
1129 \r
1130         return GE_TRUE;\r
1131 }\r