World Draw.cpp 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. /******************************************************************************/
  2. #include "stdafx.h"
  3. namespace EE{
  4. namespace Game{
  5. #define EPS_GRASS_RANGE 0.01f
  6. /******************************************************************************
  7. static void AreaDrawState(Cell<Game::Area> &cell, Ptr)
  8. {
  9. (cell.xy().vec2()*0.03).draw(cell().state ? ((cell().state==2) ? GREEN : RED) : BLACK);
  10. }
  11. /******************************************************************************/
  12. inline void Area::drawObjAndTerrain()
  13. {
  14. // first process objects before terrain, so they will be first on the list (if possible), objects don't use EarlyZ, so terrain will always be displayed as first in the EarlyZ stage
  15. REPA(_objs)
  16. {
  17. Obj &obj=*_objs[i];
  18. if(UInt modes=obj.drawPrepare())if(Renderer.firstPass())
  19. {
  20. if(modes&IndexToFlag(RM_OVERLAY )) OverlayObjects.add(&obj);
  21. if(modes&IndexToFlag(RM_BLEND )) BlendInstances.add( obj);
  22. if(modes&IndexToFlag(RM_PALETTE )) PaletteObjects.add(&obj);
  23. if(modes&IndexToFlag(RM_PALETTE1))Palette1Objects.add(&obj);
  24. if(modes&IndexToFlag(RM_SOLID )) SolidObjects.add(&obj);
  25. if(modes&IndexToFlag(RM_AMBIENT )) AmbientObjects.add(&obj);
  26. if(modes&IndexToFlag(RM_OUTLINE )) OutlineObjects.add(&obj);
  27. if(modes&IndexToFlag(RM_BEHIND )) BehindObjects.add(&obj);
  28. }
  29. }
  30. // data
  31. if(_data)
  32. {
  33. if(UInt modes=_data->customDrawPrepare())if(Renderer.firstPass()) // custom
  34. {
  35. if(modes&IndexToFlag(RM_BLEND ))BlendInstances.add(*_data);
  36. if(modes&IndexToFlag(RM_PALETTE )) PaletteAreas.add( _data);
  37. if(modes&IndexToFlag(RM_PALETTE1)) Palette1Areas.add( _data);
  38. }
  39. // terrain
  40. {
  41. Bool fully_inside;
  42. SetStencilValue(true);
  43. // terrain objects
  44. {
  45. C Memc<Data::TerrainObj> &to=_data->terrain_objs;
  46. if(to.elms() && Frustum(_data->terrain_objs_box, fully_inside))REPA(to)
  47. {
  48. C Data::TerrainObj &obj=to[i];
  49. if(C MeshPtr &mesh=obj.obj->mesh())
  50. if(fully_inside || Frustum(*mesh, obj.matrix))
  51. {
  52. SetVariation(obj.mesh_variation);
  53. mesh->draw(obj.matrix);
  54. }
  55. }
  56. }
  57. // grass objects
  58. if(D.grassRange()>EPS_GRASS_RANGE)
  59. {
  60. C Memc<Data::GrassObj> &fo=_data->foliage_objs;
  61. if(fo.elms() && FrustumGrass(_data->foliage_objs_box, fully_inside))
  62. {
  63. UInt density=RoundPos(D.grassDensity()*256);
  64. REPA(fo)
  65. {
  66. C Data::GrassObj &obj=fo[i]; if(C MeshPtr &mesh=obj.mesh)
  67. {
  68. Ball ball=mesh->ext;
  69. SetVariation(obj.mesh_variation);
  70. REP((obj.instances.elms()*density)>>8)
  71. {
  72. C Data::GrassObj::Instance &instance=obj.instances[i];
  73. Flt dist2=Dist2(instance.matrix.pos, ActiveCam.matrix.pos);
  74. if( dist2<D._grass_range_sqr && (fully_inside || FrustumGrass(ball*instance.matrix)))
  75. {
  76. if(!obj.shrink)mesh->draw(instance.matrix);else
  77. {
  78. Flt f=dist2/D._grass_range_sqr;
  79. if( f>Sqr(0.9f))
  80. {
  81. auto shrinked=instance.matrix;
  82. mesh->draw(shrinked.scaleOrn(LerpR(1.0f, Sqr(0.9f), f)));
  83. }else
  84. {
  85. mesh->draw(instance.matrix);
  86. }
  87. }
  88. }
  89. }
  90. }
  91. }
  92. }
  93. }
  94. SetVariation();
  95. // terrain mesh
  96. SetEarlyZ(WorldManager::use_early_z_for_terrain); _data->mesh.draw(MatrixIdentity);
  97. SetEarlyZ();
  98. SetStencilValue();
  99. }
  100. }
  101. }
  102. inline void Area::drawTerrainShadow()
  103. {
  104. if(_data)
  105. {
  106. Bool fully_inside;
  107. // terrain objects
  108. {
  109. Memc<Data::TerrainObj> &to=_data->terrain_objs;
  110. if(to.elms() && Frustum(_data->terrain_objs_box, fully_inside))REPA(to)
  111. {
  112. C Data::TerrainObj &obj=to[i];
  113. if(obj.obj->mesh() && (fully_inside || Frustum(*obj.obj->mesh(), obj.matrix)))
  114. {
  115. SetVariation(obj.mesh_variation);
  116. obj.obj->mesh()->drawShadow(obj.matrix);
  117. }
  118. }
  119. }
  120. // grass objects
  121. if(D.grassShadow() && D.grassRange()>EPS_GRASS_RANGE)
  122. {
  123. C Memc<Data::GrassObj> &fo=_data->foliage_objs;
  124. if(fo.elms() && Frustum(_data->foliage_objs_box, fully_inside))
  125. {
  126. UInt density=RoundPos(D.grassDensity()*256);
  127. REPA(fo)
  128. {
  129. C Data::GrassObj &obj=fo[i];
  130. if(obj.mesh)
  131. {
  132. Ball ball=obj.mesh->ext;
  133. SetVariation(obj.mesh_variation);
  134. REP((obj.instances.elms()*density)>>8)
  135. {
  136. C Data::GrassObj::Instance &instance=obj.instances[i];
  137. if(Dist2(instance.matrix.pos, ActiveCam.matrix.pos)<D._grass_range_sqr)
  138. if(fully_inside || Frustum(ball*instance.matrix))obj.mesh->drawShadow(instance.matrix);
  139. }
  140. }
  141. }
  142. }
  143. }
  144. SetVariation();
  145. // terrain mesh
  146. data()->mesh.drawShadow(MatrixIdentity);
  147. // custom
  148. data()->customDrawShadow();
  149. }
  150. }
  151. inline void Area::drawObjShadow()
  152. {
  153. REPAO(_objs)->drawShadow();
  154. }
  155. /******************************************************************************/
  156. inline void Area::drawOverlay()
  157. {
  158. if(_data)
  159. {
  160. // mesh overlays
  161. Memc<MeshOverlay> &mesh_overlays=_data->mesh_overlays;
  162. if(mesh_overlays.elms()){SetOneMatrix(); FREPA(mesh_overlays){MeshOverlay &mo=mesh_overlays[i]; if(Frustum(mo._ext))mo.draw();}}
  163. // decals
  164. Memc<Decal> &decals=_data->decals;
  165. FREPAO(decals).drawStatic();
  166. }
  167. }
  168. /******************************************************************************/
  169. void WorldManager::draw()
  170. {
  171. switch(Renderer())
  172. {
  173. case RM_PREPARE:
  174. {
  175. // objects and terrain
  176. if(Renderer.firstPass() || CurrentLight.type==LIGHT_DIR)
  177. { // '_area_draw' were calculated in MODE_UNDERWATER
  178. FREPAO(_area_draw)->drawObjAndTerrain(); // draw in order
  179. }else
  180. { // recalculate visible areas for secondary local lights because usually there will be fewer of them
  181. areaSetVisibility(_area_draw_secondary, false); FREPAO(_area_draw_secondary)->drawObjAndTerrain(); // draw in order
  182. }
  183. }break;
  184. case RM_SHADOW:
  185. {
  186. // set areas for drawing, call this first
  187. areaSetVisibility(_area_draw_shadow, false);
  188. // objects
  189. FREPAO(_area_draw_shadow)->drawObjShadow(); // draw in order
  190. // terrain
  191. Flt lod_factor_shadow=D.lodFactorShadow(); D.lodFactorShadow(1); // disable lod shadow factors
  192. FREPAO(_area_draw_shadow)->drawTerrainShadow(); // draw in order
  193. D.lodFactorShadow(lod_factor_shadow); // restore lod shadow factors
  194. }break;
  195. // overlays and decals
  196. case RM_OVERLAY:
  197. {
  198. FREPAO(_area_draw)->drawOverlay(); // draw in order
  199. // mesh overlays
  200. if(_mesh_overlays.elms()){SetOneMatrix(); FREPA(_mesh_overlays){MeshOverlay2 &mo=_mesh_overlays[i]; if(Frustum(mo._ext))mo.draw(Sat(mo.time));}}
  201. // decals
  202. FREPA(_decals){Decal2 &d=_decals[i]; d.drawStatic(Sat(d.time));}
  203. }break;
  204. // water
  205. case RM_WATER: switch(Water._mode)
  206. {
  207. case WaterClass::MODE_DRAW:
  208. {
  209. FREPA(_area_draw) // draw in order
  210. {
  211. if(Area::Data *data=_area_draw[i]->_data)REPAO(data->waters).draw();
  212. }
  213. }break;
  214. case WaterClass::MODE_REFLECTION:
  215. {
  216. FREPA(_area_draw) // draw in order
  217. {
  218. if(Renderer._mirror_want && Renderer._mirror_priority>=0)break; // if already found requested reflection then stop searching
  219. if(Area::Data *data=_area_draw[i]->_data)REPAO(data->waters).draw();
  220. }
  221. }break;
  222. case WaterClass::MODE_UNDERWATER: // when testing if underwater use only water areas from the area where camera is located
  223. {
  224. areaSetVisibility(_area_draw, true); // !! this assumes that RM_WATER+MODE_UNDERWATER are called as the first thing during rendering, we call it only once and ignore for reflections, assuming they will always give the same areas !!
  225. if(Area *area=areaActive(worldToArea(ActiveCam.matrix.pos)))
  226. if(Area::Data *data=area->data())REPAO(data->waters).draw();
  227. }break;
  228. }break;
  229. }
  230. }
  231. void WorldManager::drawDrawnAreas(C Color &color, C Color &color_shd)
  232. {
  233. Flt scale=0.003f;
  234. if(color .a){VI.color(color ); REPA(_area_draw )VI.rect(Rect_LD(_area_draw [i]->xz(), 1, 1).extend(-0.03f)*areaSize()*scale); VI.end();}
  235. if(color_shd.a){VI.color(color_shd); REPA(_area_draw_shadow)VI.rect(Rect_LD(_area_draw_shadow[i]->xz(), 1, 1).extend(-0.03f)*areaSize()*scale); VI.end();}
  236. (ActiveCam.matrix.pos.xz()*scale).draw(WHITE);
  237. REP(Frustum.edges)D.line(WHITE, Frustum.point[Frustum.edge[i].x].xz()*scale, Frustum.point[Frustum.edge[i].y].xz()*scale);
  238. }
  239. /******************************************************************************/
  240. }}
  241. /******************************************************************************/