tr_scene.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  1. /*
  2. ===========================================================================
  3. Copyright (C) 1999-2005 Id Software, Inc.
  4. This file is part of Quake III Arena source code.
  5. Quake III Arena source code is free software; you can redistribute it
  6. and/or modify it under the terms of the GNU General Public License as
  7. published by the Free Software Foundation; either version 2 of the License,
  8. or (at your option) any later version.
  9. Quake III Arena source code is distributed in the hope that it will be
  10. useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with Foobar; if not, write to the Free Software
  15. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  16. ===========================================================================
  17. */
  18. #include "tr_local.h"
  19. int r_firstSceneDrawSurf;
  20. int r_numdlights;
  21. int r_firstSceneDlight;
  22. int r_numentities;
  23. int r_firstSceneEntity;
  24. int r_numpolys;
  25. int r_firstScenePoly;
  26. int r_numpolyverts;
  27. /*
  28. ====================
  29. R_ToggleSmpFrame
  30. ====================
  31. */
  32. void R_ToggleSmpFrame( void ) {
  33. if ( r_smp->integer ) {
  34. // use the other buffers next frame, because another CPU
  35. // may still be rendering into the current ones
  36. tr.smpFrame ^= 1;
  37. } else {
  38. tr.smpFrame = 0;
  39. }
  40. backEndData[tr.smpFrame]->commands.used = 0;
  41. r_firstSceneDrawSurf = 0;
  42. r_numdlights = 0;
  43. r_firstSceneDlight = 0;
  44. r_numentities = 0;
  45. r_firstSceneEntity = 0;
  46. r_numpolys = 0;
  47. r_firstScenePoly = 0;
  48. r_numpolyverts = 0;
  49. }
  50. /*
  51. ====================
  52. RE_ClearScene
  53. ====================
  54. */
  55. void RE_ClearScene( void ) {
  56. r_firstSceneDlight = r_numdlights;
  57. r_firstSceneEntity = r_numentities;
  58. r_firstScenePoly = r_numpolys;
  59. }
  60. /*
  61. ===========================================================================
  62. DISCRETE POLYS
  63. ===========================================================================
  64. */
  65. /*
  66. =====================
  67. R_AddPolygonSurfaces
  68. Adds all the scene's polys into this view's drawsurf list
  69. =====================
  70. */
  71. void R_AddPolygonSurfaces( void ) {
  72. int i;
  73. shader_t *sh;
  74. srfPoly_t *poly;
  75. tr.currentEntityNum = ENTITYNUM_WORLD;
  76. tr.shiftedEntityNum = tr.currentEntityNum << QSORT_ENTITYNUM_SHIFT;
  77. for ( i = 0, poly = tr.refdef.polys; i < tr.refdef.numPolys ; i++, poly++ ) {
  78. sh = R_GetShaderByHandle( poly->hShader );
  79. R_AddDrawSurf( ( void * )poly, sh, poly->fogIndex, qfalse );
  80. }
  81. }
  82. /*
  83. =====================
  84. RE_AddPolyToScene
  85. =====================
  86. */
  87. void RE_AddPolyToScene( qhandle_t hShader, int numVerts, const polyVert_t *verts, int numPolys ) {
  88. srfPoly_t *poly;
  89. int i, j;
  90. int fogIndex;
  91. fog_t *fog;
  92. vec3_t bounds[2];
  93. if ( !tr.registered ) {
  94. return;
  95. }
  96. if ( !hShader ) {
  97. ri.Printf( PRINT_WARNING, "WARNING: RE_AddPolyToScene: NULL poly shader\n");
  98. return;
  99. }
  100. for ( j = 0; j < numPolys; j++ ) {
  101. if ( r_numpolyverts + numVerts > max_polyverts || r_numpolys >= max_polys ) {
  102. /*
  103. NOTE TTimo this was initially a PRINT_WARNING
  104. but it happens a lot with high fighting scenes and particles
  105. since we don't plan on changing the const and making for room for those effects
  106. simply cut this message to developer only
  107. */
  108. ri.Printf( PRINT_DEVELOPER, "WARNING: RE_AddPolyToScene: r_max_polys or r_max_polyverts reached\n");
  109. return;
  110. }
  111. poly = &backEndData[tr.smpFrame]->polys[r_numpolys];
  112. poly->surfaceType = SF_POLY;
  113. poly->hShader = hShader;
  114. poly->numVerts = numVerts;
  115. poly->verts = &backEndData[tr.smpFrame]->polyVerts[r_numpolyverts];
  116. Com_Memcpy( poly->verts, &verts[numVerts*j], numVerts * sizeof( *verts ) );
  117. if ( glConfig.hardwareType == GLHW_RAGEPRO ) {
  118. poly->verts->modulate[0] = 255;
  119. poly->verts->modulate[1] = 255;
  120. poly->verts->modulate[2] = 255;
  121. poly->verts->modulate[3] = 255;
  122. }
  123. // done.
  124. r_numpolys++;
  125. r_numpolyverts += numVerts;
  126. // if no world is loaded
  127. if ( tr.world == NULL ) {
  128. fogIndex = 0;
  129. }
  130. // see if it is in a fog volume
  131. else if ( tr.world->numfogs == 1 ) {
  132. fogIndex = 0;
  133. } else {
  134. // find which fog volume the poly is in
  135. VectorCopy( poly->verts[0].xyz, bounds[0] );
  136. VectorCopy( poly->verts[0].xyz, bounds[1] );
  137. for ( i = 1 ; i < poly->numVerts ; i++ ) {
  138. AddPointToBounds( poly->verts[i].xyz, bounds[0], bounds[1] );
  139. }
  140. for ( fogIndex = 1 ; fogIndex < tr.world->numfogs ; fogIndex++ ) {
  141. fog = &tr.world->fogs[fogIndex];
  142. if ( bounds[1][0] >= fog->bounds[0][0]
  143. && bounds[1][1] >= fog->bounds[0][1]
  144. && bounds[1][2] >= fog->bounds[0][2]
  145. && bounds[0][0] <= fog->bounds[1][0]
  146. && bounds[0][1] <= fog->bounds[1][1]
  147. && bounds[0][2] <= fog->bounds[1][2] ) {
  148. break;
  149. }
  150. }
  151. if ( fogIndex == tr.world->numfogs ) {
  152. fogIndex = 0;
  153. }
  154. }
  155. poly->fogIndex = fogIndex;
  156. }
  157. }
  158. //=================================================================================
  159. /*
  160. =====================
  161. RE_AddRefEntityToScene
  162. =====================
  163. */
  164. void RE_AddRefEntityToScene( const refEntity_t *ent ) {
  165. if ( !tr.registered ) {
  166. return;
  167. }
  168. // https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=402
  169. if ( r_numentities >= ENTITYNUM_WORLD ) {
  170. return;
  171. }
  172. if ( ent->reType < 0 || ent->reType >= RT_MAX_REF_ENTITY_TYPE ) {
  173. ri.Error( ERR_DROP, "RE_AddRefEntityToScene: bad reType %i", ent->reType );
  174. }
  175. backEndData[tr.smpFrame]->entities[r_numentities].e = *ent;
  176. backEndData[tr.smpFrame]->entities[r_numentities].lightingCalculated = qfalse;
  177. r_numentities++;
  178. }
  179. /*
  180. =====================
  181. RE_AddDynamicLightToScene
  182. =====================
  183. */
  184. void RE_AddDynamicLightToScene( const vec3_t org, float intensity, float r, float g, float b, int additive ) {
  185. dlight_t *dl;
  186. if ( !tr.registered ) {
  187. return;
  188. }
  189. if ( r_numdlights >= MAX_DLIGHTS ) {
  190. return;
  191. }
  192. if ( intensity <= 0 ) {
  193. return;
  194. }
  195. // these cards don't have the correct blend mode
  196. if ( glConfig.hardwareType == GLHW_RIVA128 || glConfig.hardwareType == GLHW_PERMEDIA2 ) {
  197. return;
  198. }
  199. dl = &backEndData[tr.smpFrame]->dlights[r_numdlights++];
  200. VectorCopy (org, dl->origin);
  201. dl->radius = intensity;
  202. dl->color[0] = r;
  203. dl->color[1] = g;
  204. dl->color[2] = b;
  205. dl->additive = additive;
  206. }
  207. /*
  208. =====================
  209. RE_AddLightToScene
  210. =====================
  211. */
  212. void RE_AddLightToScene( const vec3_t org, float intensity, float r, float g, float b ) {
  213. RE_AddDynamicLightToScene( org, intensity, r, g, b, qfalse );
  214. }
  215. /*
  216. =====================
  217. RE_AddAdditiveLightToScene
  218. =====================
  219. */
  220. void RE_AddAdditiveLightToScene( const vec3_t org, float intensity, float r, float g, float b ) {
  221. RE_AddDynamicLightToScene( org, intensity, r, g, b, qtrue );
  222. }
  223. /*
  224. @@@@@@@@@@@@@@@@@@@@@
  225. RE_RenderScene
  226. Draw a 3D view into a part of the window, then return
  227. to 2D drawing.
  228. Rendering a scene may require multiple views to be rendered
  229. to handle mirrors,
  230. @@@@@@@@@@@@@@@@@@@@@
  231. */
  232. void RE_RenderScene( const refdef_t *fd ) {
  233. viewParms_t parms;
  234. int startTime;
  235. if ( !tr.registered ) {
  236. return;
  237. }
  238. GLimp_LogComment( "====== RE_RenderScene =====\n" );
  239. if ( r_norefresh->integer ) {
  240. return;
  241. }
  242. startTime = ri.Milliseconds();
  243. if (!tr.world && !( fd->rdflags & RDF_NOWORLDMODEL ) ) {
  244. ri.Error (ERR_DROP, "R_RenderScene: NULL worldmodel");
  245. }
  246. Com_Memcpy( tr.refdef.text, fd->text, sizeof( tr.refdef.text ) );
  247. tr.refdef.x = fd->x;
  248. tr.refdef.y = fd->y;
  249. tr.refdef.width = fd->width;
  250. tr.refdef.height = fd->height;
  251. tr.refdef.fov_x = fd->fov_x;
  252. tr.refdef.fov_y = fd->fov_y;
  253. VectorCopy( fd->vieworg, tr.refdef.vieworg );
  254. VectorCopy( fd->viewaxis[0], tr.refdef.viewaxis[0] );
  255. VectorCopy( fd->viewaxis[1], tr.refdef.viewaxis[1] );
  256. VectorCopy( fd->viewaxis[2], tr.refdef.viewaxis[2] );
  257. tr.refdef.time = fd->time;
  258. tr.refdef.rdflags = fd->rdflags;
  259. // copy the areamask data over and note if it has changed, which
  260. // will force a reset of the visible leafs even if the view hasn't moved
  261. tr.refdef.areamaskModified = qfalse;
  262. if ( ! (tr.refdef.rdflags & RDF_NOWORLDMODEL) ) {
  263. int areaDiff;
  264. int i;
  265. // compare the area bits
  266. areaDiff = 0;
  267. for (i = 0 ; i < MAX_MAP_AREA_BYTES/4 ; i++) {
  268. areaDiff |= ((int *)tr.refdef.areamask)[i] ^ ((int *)fd->areamask)[i];
  269. ((int *)tr.refdef.areamask)[i] = ((int *)fd->areamask)[i];
  270. }
  271. if ( areaDiff ) {
  272. // a door just opened or something
  273. tr.refdef.areamaskModified = qtrue;
  274. }
  275. }
  276. // derived info
  277. tr.refdef.floatTime = tr.refdef.time * 0.001f;
  278. tr.refdef.numDrawSurfs = r_firstSceneDrawSurf;
  279. tr.refdef.drawSurfs = backEndData[tr.smpFrame]->drawSurfs;
  280. tr.refdef.num_entities = r_numentities - r_firstSceneEntity;
  281. tr.refdef.entities = &backEndData[tr.smpFrame]->entities[r_firstSceneEntity];
  282. tr.refdef.num_dlights = r_numdlights - r_firstSceneDlight;
  283. tr.refdef.dlights = &backEndData[tr.smpFrame]->dlights[r_firstSceneDlight];
  284. tr.refdef.numPolys = r_numpolys - r_firstScenePoly;
  285. tr.refdef.polys = &backEndData[tr.smpFrame]->polys[r_firstScenePoly];
  286. // turn off dynamic lighting globally by clearing all the
  287. // dlights if it needs to be disabled or if vertex lighting is enabled
  288. if ( r_dynamiclight->integer == 0 ||
  289. r_vertexLight->integer == 1 ||
  290. glConfig.hardwareType == GLHW_PERMEDIA2 ) {
  291. tr.refdef.num_dlights = 0;
  292. }
  293. // a single frame may have multiple scenes draw inside it --
  294. // a 3D game view, 3D status bar renderings, 3D menus, etc.
  295. // They need to be distinguished by the light flare code, because
  296. // the visibility state for a given surface may be different in
  297. // each scene / view.
  298. tr.frameSceneNum++;
  299. tr.sceneCount++;
  300. // setup view parms for the initial view
  301. //
  302. // set up viewport
  303. // The refdef takes 0-at-the-top y coordinates, so
  304. // convert to GL's 0-at-the-bottom space
  305. //
  306. Com_Memset( &parms, 0, sizeof( parms ) );
  307. parms.viewportX = tr.refdef.x;
  308. parms.viewportY = glConfig.vidHeight - ( tr.refdef.y + tr.refdef.height );
  309. parms.viewportWidth = tr.refdef.width;
  310. parms.viewportHeight = tr.refdef.height;
  311. parms.isPortal = qfalse;
  312. parms.fovX = tr.refdef.fov_x;
  313. parms.fovY = tr.refdef.fov_y;
  314. VectorCopy( fd->vieworg, parms.or.origin );
  315. VectorCopy( fd->viewaxis[0], parms.or.axis[0] );
  316. VectorCopy( fd->viewaxis[1], parms.or.axis[1] );
  317. VectorCopy( fd->viewaxis[2], parms.or.axis[2] );
  318. VectorCopy( fd->vieworg, parms.pvsOrigin );
  319. R_RenderView( &parms );
  320. // the next scene rendered in this frame will tack on after this one
  321. r_firstSceneDrawSurf = tr.refdef.numDrawSurfs;
  322. r_firstSceneEntity = r_numentities;
  323. r_firstSceneDlight = r_numdlights;
  324. r_firstScenePoly = r_numpolys;
  325. tr.frontEndMsec += ri.Milliseconds() - startTime;
  326. }