]> icculus.org git repositories - icculus/iodoom3.git/blob - neo/renderer/RenderWorld_load.cpp
Use the same OpenAL headers on all platforms.
[icculus/iodoom3.git] / neo / renderer / RenderWorld_load.cpp
1 /*
2 ===========================================================================
3
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company. 
6
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).  
8
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code.  If not, see <http://www.gnu.org/licenses/>.
21
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code.  If not, please request a copy in writing from id Software at the address below.
23
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
25
26 ===========================================================================
27 */
28
29 #include "../idlib/precompiled.h"
30 #pragma hdrstop
31
32 #include "tr_local.h"
33
34
35 /*
36 ================
37 idRenderWorldLocal::FreeWorld
38 ================
39 */
40 void idRenderWorldLocal::FreeWorld() {
41         int i;
42
43         // this will free all the lightDefs and entityDefs
44         FreeDefs();
45
46         // free all the portals and check light/model references
47         for ( i = 0 ; i < numPortalAreas ; i++ ) {
48                 portalArea_t    *area;
49                 portal_t                *portal, *nextPortal;
50
51                 area = &portalAreas[i];
52                 for ( portal = area->portals ; portal ; portal = nextPortal ) {
53                         nextPortal = portal->next;
54                         delete portal->w;
55                         R_StaticFree( portal );
56                 }
57
58                 // there shouldn't be any remaining lightRefs or entityRefs
59                 if ( area->lightRefs.areaNext != &area->lightRefs ) {
60                         common->Error( "FreeWorld: unexpected remaining lightRefs" );
61                 }
62                 if ( area->entityRefs.areaNext != &area->entityRefs ) {
63                         common->Error( "FreeWorld: unexpected remaining entityRefs" );
64                 }
65         }
66
67         if ( portalAreas ) {
68                 R_StaticFree( portalAreas );
69                 portalAreas = NULL;
70                 numPortalAreas = 0;
71                 R_StaticFree( areaScreenRect );
72                 areaScreenRect = NULL;
73         }
74
75         if ( doublePortals ) {
76                 R_StaticFree( doublePortals );
77                 doublePortals = NULL;
78                 numInterAreaPortals = 0;
79         }
80
81         if ( areaNodes ) {
82                 R_StaticFree( areaNodes );
83                 areaNodes = NULL;
84         }
85
86         // free all the inline idRenderModels 
87         for ( i = 0 ; i < localModels.Num() ; i++ ) {
88                 renderModelManager->RemoveModel( localModels[i] );
89                 delete localModels[i];
90         }
91         localModels.Clear();
92
93         areaReferenceAllocator.Shutdown();
94         interactionAllocator.Shutdown();
95         areaNumRefAllocator.Shutdown();
96
97         mapName = "<FREED>";
98 }
99
100 /*
101 ================
102 idRenderWorldLocal::TouchWorldModels
103 ================
104 */
105 void idRenderWorldLocal::TouchWorldModels( void ) {
106         int i;
107
108         for ( i = 0 ; i < localModels.Num() ; i++ ) {
109                 renderModelManager->CheckModel( localModels[i]->Name() );
110         }
111 }
112
113 /*
114 ================
115 idRenderWorldLocal::ParseModel
116 ================
117 */
118 idRenderModel *idRenderWorldLocal::ParseModel( idLexer *src ) {
119         idRenderModel   *model;
120         idToken                 token;
121         int                             i, j;
122         srfTriangles_t  *tri;
123         modelSurface_t  surf;
124
125         src->ExpectTokenString( "{" );
126
127         // parse the name
128         src->ExpectAnyToken( &token );
129
130         model = renderModelManager->AllocModel();
131         model->InitEmpty( token );
132
133         int numSurfaces = src->ParseInt();
134         if ( numSurfaces < 0 ) {
135                 src->Error( "R_ParseModel: bad numSurfaces" );
136         }
137
138         for ( i = 0 ; i < numSurfaces ; i++ ) {
139                 src->ExpectTokenString( "{" );
140
141                 src->ExpectAnyToken( &token );
142
143                 surf.shader = declManager->FindMaterial( token );
144
145                 ((idMaterial*)surf.shader)->AddReference();
146
147                 tri = R_AllocStaticTriSurf();
148                 surf.geometry = tri;
149
150                 tri->numVerts = src->ParseInt();
151                 tri->numIndexes = src->ParseInt();
152
153                 R_AllocStaticTriSurfVerts( tri, tri->numVerts );
154                 for ( j = 0 ; j < tri->numVerts ; j++ ) {
155                         float   vec[8];
156
157                         src->Parse1DMatrix( 8, vec );
158
159                         tri->verts[j].xyz[0] = vec[0];
160                         tri->verts[j].xyz[1] = vec[1];
161                         tri->verts[j].xyz[2] = vec[2];
162                         tri->verts[j].st[0] = vec[3];
163                         tri->verts[j].st[1] = vec[4];
164                         tri->verts[j].normal[0] = vec[5];
165                         tri->verts[j].normal[1] = vec[6];
166                         tri->verts[j].normal[2] = vec[7];
167                 }
168
169                 R_AllocStaticTriSurfIndexes( tri, tri->numIndexes );
170                 for ( j = 0 ; j < tri->numIndexes ; j++ ) {
171                         tri->indexes[j] = src->ParseInt();
172                 }
173                 src->ExpectTokenString( "}" );
174
175                 // add the completed surface to the model
176                 model->AddSurface( surf );
177         }
178
179         src->ExpectTokenString( "}" );
180
181         model->FinishSurfaces();
182
183         return model;
184 }
185
186 /*
187 ================
188 idRenderWorldLocal::ParseShadowModel
189 ================
190 */
191 idRenderModel *idRenderWorldLocal::ParseShadowModel( idLexer *src ) {
192         idRenderModel   *model;
193         idToken                 token;
194         int                             j;
195         srfTriangles_t  *tri;
196         modelSurface_t  surf;
197
198         src->ExpectTokenString( "{" );
199
200         // parse the name
201         src->ExpectAnyToken( &token );
202
203         model = renderModelManager->AllocModel();
204         model->InitEmpty( token );
205
206         surf.shader = tr.defaultMaterial;
207
208         tri = R_AllocStaticTriSurf();
209         surf.geometry = tri;
210
211         tri->numVerts = src->ParseInt();
212         tri->numShadowIndexesNoCaps = src->ParseInt();
213         tri->numShadowIndexesNoFrontCaps = src->ParseInt();
214         tri->numIndexes = src->ParseInt();
215         tri->shadowCapPlaneBits = src->ParseInt();
216
217         R_AllocStaticTriSurfShadowVerts( tri, tri->numVerts );
218         tri->bounds.Clear();
219         for ( j = 0 ; j < tri->numVerts ; j++ ) {
220                 float   vec[8];
221
222                 src->Parse1DMatrix( 3, vec );
223                 tri->shadowVertexes[j].xyz[0] = vec[0];
224                 tri->shadowVertexes[j].xyz[1] = vec[1];
225                 tri->shadowVertexes[j].xyz[2] = vec[2];
226                 tri->shadowVertexes[j].xyz[3] = 1;              // no homogenous value
227
228                 tri->bounds.AddPoint( tri->shadowVertexes[j].xyz.ToVec3() );
229         }
230
231         R_AllocStaticTriSurfIndexes( tri, tri->numIndexes );
232         for ( j = 0 ; j < tri->numIndexes ; j++ ) {
233                 tri->indexes[j] = src->ParseInt();
234         }
235
236         // add the completed surface to the model
237         model->AddSurface( surf );
238
239         src->ExpectTokenString( "}" );
240
241         // we do NOT do a model->FinishSurfaceces, because we don't need sil edges, planes, tangents, etc.
242 //      model->FinishSurfaces();
243
244         return model;
245 }
246
247 /*
248 ================
249 idRenderWorldLocal::SetupAreaRefs
250 ================
251 */
252 void idRenderWorldLocal::SetupAreaRefs() {
253         int             i;
254
255         connectedAreaNum = 0;
256         for ( i = 0 ; i < numPortalAreas ; i++ ) {
257                 portalAreas[i].areaNum = i;
258                 portalAreas[i].lightRefs.areaNext =
259                 portalAreas[i].lightRefs.areaPrev =
260                         &portalAreas[i].lightRefs;
261                 portalAreas[i].entityRefs.areaNext =
262                 portalAreas[i].entityRefs.areaPrev =
263                         &portalAreas[i].entityRefs;
264         }
265 }
266
267 /*
268 ================
269 idRenderWorldLocal::ParseInterAreaPortals
270 ================
271 */
272 void idRenderWorldLocal::ParseInterAreaPortals( idLexer *src ) {
273         int i, j;
274
275         src->ExpectTokenString( "{" );
276
277         numPortalAreas = src->ParseInt();
278         if ( numPortalAreas < 0 ) {
279                 src->Error( "R_ParseInterAreaPortals: bad numPortalAreas" );
280                 return;
281         }
282         portalAreas = (portalArea_t *)R_ClearedStaticAlloc( numPortalAreas * sizeof( portalAreas[0] ) );
283         areaScreenRect = (idScreenRect *) R_ClearedStaticAlloc( numPortalAreas * sizeof( idScreenRect ) );
284
285         // set the doubly linked lists
286         SetupAreaRefs();
287
288         numInterAreaPortals = src->ParseInt();
289         if ( numInterAreaPortals < 0 ) {
290                 src->Error(  "R_ParseInterAreaPortals: bad numInterAreaPortals" );
291                 return;
292         }
293
294         doublePortals = (doublePortal_t *)R_ClearedStaticAlloc( numInterAreaPortals * 
295                 sizeof( doublePortals [0] ) );
296
297         for ( i = 0 ; i < numInterAreaPortals ; i++ ) {
298                 int             numPoints, a1, a2;
299                 idWinding       *w;
300                 portal_t        *p;
301
302                 numPoints = src->ParseInt();
303                 a1 = src->ParseInt();
304                 a2 = src->ParseInt();
305
306                 w = new idWinding( numPoints );
307                 w->SetNumPoints( numPoints );
308                 for ( j = 0 ; j < numPoints ; j++ ) {
309                         src->Parse1DMatrix( 3, (*w)[j].ToFloatPtr() );
310                         // no texture coordinates
311                         (*w)[j][3] = 0;
312                         (*w)[j][4] = 0;
313                 }
314
315                 // add the portal to a1
316                 p = (portal_t *)R_ClearedStaticAlloc( sizeof( *p ) );
317                 p->intoArea = a2;
318                 p->doublePortal = &doublePortals[i];
319                 p->w = w;
320                 p->w->GetPlane( p->plane );
321
322                 p->next = portalAreas[a1].portals;
323                 portalAreas[a1].portals = p;
324
325                 doublePortals[i].portals[0] = p;
326
327                 // reverse it for a2
328                 p = (portal_t *)R_ClearedStaticAlloc( sizeof( *p ) );
329                 p->intoArea = a1;
330                 p->doublePortal = &doublePortals[i];
331                 p->w = w->Reverse();
332                 p->w->GetPlane( p->plane );
333
334                 p->next = portalAreas[a2].portals;
335                 portalAreas[a2].portals = p;
336
337                 doublePortals[i].portals[1] = p;
338         }
339
340         src->ExpectTokenString( "}" );
341 }
342
343 /*
344 ================
345 idRenderWorldLocal::ParseNodes
346 ================
347 */
348 void idRenderWorldLocal::ParseNodes( idLexer *src ) {
349         int                     i;
350
351         src->ExpectTokenString( "{" );
352
353         numAreaNodes = src->ParseInt();
354         if ( numAreaNodes < 0 ) {
355                 src->Error( "R_ParseNodes: bad numAreaNodes" );
356         }
357         areaNodes = (areaNode_t *)R_ClearedStaticAlloc( numAreaNodes * sizeof( areaNodes[0] ) );
358
359         for ( i = 0 ; i < numAreaNodes ; i++ ) {
360                 areaNode_t      *node;
361
362                 node = &areaNodes[i];
363
364                 src->Parse1DMatrix( 4, node->plane.ToFloatPtr() );
365                 node->children[0] = src->ParseInt();
366                 node->children[1] = src->ParseInt();
367         }
368
369         src->ExpectTokenString( "}" );
370 }
371
372 /*
373 ================
374 idRenderWorldLocal::CommonChildrenArea_r
375 ================
376 */
377 int idRenderWorldLocal::CommonChildrenArea_r( areaNode_t *node ) {
378         int     nums[2];
379
380         for ( int i = 0 ; i < 2 ; i++ ) {
381                 if ( node->children[i] <= 0 ) {
382                         nums[i] = -1 - node->children[i];
383                 } else {
384                         nums[i] = CommonChildrenArea_r( &areaNodes[ node->children[i] ] );
385                 }
386         }
387
388         // solid nodes will match any area
389         if ( nums[0] == AREANUM_SOLID ) {
390                 nums[0] = nums[1];
391         }
392         if ( nums[1] == AREANUM_SOLID ) {
393                 nums[1] = nums[0];
394         }
395
396         int     common;
397         if ( nums[0] == nums[1] ) {
398                 common = nums[0];
399         } else {
400                 common = CHILDREN_HAVE_MULTIPLE_AREAS;
401         }
402
403         node->commonChildrenArea = common;
404
405         return common;
406 }
407
408 /*
409 =================
410 idRenderWorldLocal::ClearWorld
411
412 Sets up for a single area world
413 =================
414 */
415 void idRenderWorldLocal::ClearWorld() {
416         numPortalAreas = 1;
417         portalAreas = (portalArea_t *)R_ClearedStaticAlloc( sizeof( portalAreas[0] ) );
418         areaScreenRect = (idScreenRect *) R_ClearedStaticAlloc( sizeof( idScreenRect ) );
419
420         SetupAreaRefs();
421
422         // even though we only have a single area, create a node
423         // that has both children pointing at it so we don't need to
424         //
425         areaNodes = (areaNode_t *)R_ClearedStaticAlloc( sizeof( areaNodes[0] ) );
426         areaNodes[0].plane[3] = 1;
427         areaNodes[0].children[0] = -1;
428         areaNodes[0].children[1] = -1;
429 }
430
431 /*
432 =================
433 idRenderWorldLocal::FreeDefs
434
435 dump all the interactions
436 =================
437 */
438 void idRenderWorldLocal::FreeDefs() {
439         int             i;
440
441         generateAllInteractionsCalled = false;
442
443         if ( interactionTable ) {
444                 R_StaticFree( interactionTable );
445                 interactionTable = NULL;
446         }
447
448         // free all lightDefs
449         for ( i = 0 ; i < lightDefs.Num() ; i++ ) {
450                 idRenderLightLocal      *light;
451
452                 light = lightDefs[i];
453                 if ( light && light->world == this ) {
454                         FreeLightDef( i );
455                         lightDefs[i] = NULL;
456                 }
457         }
458
459         // free all entityDefs
460         for ( i = 0 ; i < entityDefs.Num() ; i++ ) {
461                 idRenderEntityLocal     *mod;
462
463                 mod = entityDefs[i];
464                 if ( mod && mod->world == this ) {
465                         FreeEntityDef( i );
466                         entityDefs[i] = NULL;
467                 }
468         }
469 }
470
471 /*
472 =================
473 idRenderWorldLocal::InitFromMap
474
475 A NULL or empty name will make a world without a map model, which
476 is still useful for displaying a bare model
477 =================
478 */
479 bool idRenderWorldLocal::InitFromMap( const char *name ) {
480         idLexer *               src;
481         idToken                 token;
482         idStr                   filename;
483         idRenderModel * lastModel;
484
485         // if this is an empty world, initialize manually
486         if ( !name || !name[0] ) {
487                 FreeWorld();
488                 mapName.Clear();
489                 ClearWorld();
490                 return true;
491         }
492
493
494         // load it
495         filename = name;
496         filename.SetFileExtension( PROC_FILE_EXT );
497
498         // if we are reloading the same map, check the timestamp
499         // and try to skip all the work
500         ID_TIME_T currentTimeStamp;
501         fileSystem->ReadFile( filename, NULL, &currentTimeStamp );
502
503         if ( name == mapName ) {
504                 if ( currentTimeStamp != FILE_NOT_FOUND_TIMESTAMP && currentTimeStamp == mapTimeStamp ) {
505                         common->Printf( "idRenderWorldLocal::InitFromMap: retaining existing map\n" );
506                         FreeDefs();
507                         TouchWorldModels();
508                         AddWorldModelEntities();
509                         ClearPortalStates();
510                         return true;
511                 }
512                 common->Printf( "idRenderWorldLocal::InitFromMap: timestamp has changed, reloading.\n" );
513         }
514
515         FreeWorld();
516
517         src = new idLexer( filename, LEXFL_NOSTRINGCONCAT | LEXFL_NODOLLARPRECOMPILE );
518         if ( !src->IsLoaded() ) {
519                 common->Printf( "idRenderWorldLocal::InitFromMap: %s not found\n", filename.c_str() );
520                 ClearWorld();
521                 return false;
522         }
523
524
525         mapName = name;
526         mapTimeStamp = currentTimeStamp;
527
528         // if we are writing a demo, archive the load command
529         if ( session->writeDemo ) {
530                 WriteLoadMap();
531         }
532
533         if ( !src->ReadToken( &token ) || token.Icmp( PROC_FILE_ID ) ) {
534                 common->Printf( "idRenderWorldLocal::InitFromMap: bad id '%s' instead of '%s'\n", token.c_str(), PROC_FILE_ID );
535                 delete src;
536                 return false;
537         }
538
539         // parse the file
540         while ( 1 ) {
541                 if ( !src->ReadToken( &token ) ) {
542                         break;
543                 }
544
545                 if ( token == "model" ) {
546                         lastModel = ParseModel( src );
547
548                         // add it to the model manager list
549                         renderModelManager->AddModel( lastModel );
550
551                         // save it in the list to free when clearing this map
552                         localModels.Append( lastModel );
553                         continue;
554                 }
555
556                 if ( token == "shadowModel" ) {
557                         lastModel = ParseShadowModel( src );
558
559                         // add it to the model manager list
560                         renderModelManager->AddModel( lastModel );
561
562                         // save it in the list to free when clearing this map
563                         localModels.Append( lastModel );
564                         continue;
565                 }
566
567                 if ( token == "interAreaPortals" ) {
568                         ParseInterAreaPortals( src );
569                         continue;
570                 }
571
572                 if ( token == "nodes" ) {
573                         ParseNodes( src );
574                         continue;
575                 }
576
577                 src->Error( "idRenderWorldLocal::InitFromMap: bad token \"%s\"", token.c_str() );
578         }
579
580         delete src;
581
582         // if it was a trivial map without any areas, create a single area
583         if ( !numPortalAreas ) {
584                 ClearWorld();
585         }
586
587         // find the points where we can early-our of reference pushing into the BSP tree
588         CommonChildrenArea_r( &areaNodes[0] );
589
590         AddWorldModelEntities();
591         ClearPortalStates();
592
593         // done!
594         return true;
595 }
596
597 /*
598 =====================
599 idRenderWorldLocal::ClearPortalStates
600 =====================
601 */
602 void idRenderWorldLocal::ClearPortalStates() {
603         int             i, j;
604
605         // all portals start off open
606         for ( i = 0 ; i < numInterAreaPortals ; i++ ) {
607                 doublePortals[i].blockingBits = PS_BLOCK_NONE;
608         }
609
610         // flood fill all area connections
611         for ( i = 0 ; i < numPortalAreas ; i++ ) {
612                 for ( j = 0 ; j < NUM_PORTAL_ATTRIBUTES ; j++ ) {
613                         connectedAreaNum++;
614                         FloodConnectedAreas( &portalAreas[i], j );
615                 }
616         }
617 }
618
619 /*
620 =====================
621 idRenderWorldLocal::AddWorldModelEntities
622 =====================
623 */
624 void idRenderWorldLocal::AddWorldModelEntities() {
625         int             i;
626
627         // add the world model for each portal area
628         // we can't just call AddEntityDef, because that would place the references
629         // based on the bounding box, rather than explicitly into the correct area
630         for ( i = 0 ; i < numPortalAreas ; i++ ) {
631                 idRenderEntityLocal     *def;
632                 int                     index;
633
634                 def = new idRenderEntityLocal;
635
636                 // try and reuse a free spot
637                 index = entityDefs.FindNull();
638                 if ( index == -1 ) {
639                         index = entityDefs.Append(def);
640                 } else {
641                         entityDefs[index] = def;
642                 }
643
644                 def->index = index;
645                 def->world = this;
646
647                 def->parms.hModel = renderModelManager->FindModel( va("_area%i", i ) );
648                 if ( def->parms.hModel->IsDefaultModel() || !def->parms.hModel->IsStaticWorldModel() ) {
649                         common->Error( "idRenderWorldLocal::InitFromMap: bad area model lookup" );
650                 }
651
652                 idRenderModel *hModel = def->parms.hModel;
653
654                 for ( int j = 0; j < hModel->NumSurfaces(); j++ ) {
655                         const modelSurface_t *surf = hModel->Surface( j );
656
657                         if ( surf->shader->GetName() == idStr( "textures/smf/portal_sky" ) ) {
658                                 def->needsPortalSky = true;
659                         }
660                 }
661
662                 def->referenceBounds = def->parms.hModel->Bounds();
663
664                 def->parms.axis[0][0] = 1;
665                 def->parms.axis[1][1] = 1;
666                 def->parms.axis[2][2] = 1;
667
668                 R_AxisToModelMatrix( def->parms.axis, def->parms.origin, def->modelMatrix );
669
670                 // in case an explicit shader is used on the world, we don't
671                 // want it to have a 0 alpha or color
672                 def->parms.shaderParms[0] =
673                 def->parms.shaderParms[1] =
674                 def->parms.shaderParms[2] =
675                 def->parms.shaderParms[3] = 1;
676
677                 AddEntityRefToArea( def, &portalAreas[i] );
678         }
679 }
680
681 /*
682 =====================
683 CheckAreaForPortalSky
684 =====================
685 */
686 bool idRenderWorldLocal::CheckAreaForPortalSky( int areaNum ) {
687         areaReference_t *ref;
688
689         assert( areaNum >= 0 && areaNum < numPortalAreas );
690
691         for ( ref = portalAreas[areaNum].entityRefs.areaNext; ref->entity; ref = ref->areaNext ) {
692                 assert( ref->area == &portalAreas[areaNum] );
693
694                 if ( ref->entity && ref->entity->needsPortalSky ) {
695                         return true;
696                 }
697         }
698
699         return false;
700 }