BrushImport.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. /* Copyright (c) 2002-2012 Croteam Ltd.
  2. This program is free software; you can redistribute it and/or modify
  3. it under the terms of version 2 of the GNU General Public License as published by
  4. the Free Software Foundation
  5. This program is distributed in the hope that it will be useful,
  6. but WITHOUT ANY WARRANTY; without even the implied warranty of
  7. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  8. GNU General Public License for more details.
  9. You should have received a copy of the GNU General Public License along
  10. with this program; if not, write to the Free Software Foundation, Inc.,
  11. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
  12. #include "stdh.h"
  13. #include <Engine/Brushes/Brush.h>
  14. #include <Engine/Math/Float.h>
  15. #include <Engine/Math/Object3D.h>
  16. #include <Engine/Templates/StaticArray.cpp>
  17. #include <Engine/Templates/DynamicContainer.cpp>
  18. #include <Engine/Templates/DynamicArray.cpp>
  19. #include <Engine/World/WorldEditingProfile.h>
  20. #include <Engine/Brushes/BrushTransformed.h>
  21. #include <Engine/Graphics/Color.h>
  22. #include <Engine/Math/Projection_DOUBLE.h>
  23. /*
  24. * Add 3d object as new mip brush.
  25. */
  26. void CBrush3D::AddMipBrushFromObject3D_t(CObject3D &ob, FLOAT fSwitchDistance) // throw char *
  27. {
  28. ASSERT(GetFPUPrecision()==FPT_53BIT);
  29. // create one brush mip
  30. CBrushMip *pbmBrushMip = new CBrushMip;
  31. // add it to the brush
  32. br_lhBrushMips.AddTail(pbmBrushMip->bm_lnInBrush);
  33. pbmBrushMip->bm_pbrBrush = this;
  34. pbmBrushMip->bm_fMaxDistance = fSwitchDistance;
  35. // add the object to the brush mip
  36. pbmBrushMip->AddFromObject3D_t(ob);
  37. }
  38. /*
  39. * Fill a brush from 3d object.
  40. */
  41. void CBrush3D::FromObject3D_t(CObject3D &ob) // throw char *
  42. {
  43. ASSERT(GetFPUPrecision()==FPT_53BIT);
  44. // clear this brush in case there is something in it
  45. Clear();
  46. // create one brush mip
  47. CBrushMip *pbmBrushMip = new CBrushMip;
  48. // add it to the brush
  49. br_lhBrushMips.AddTail(pbmBrushMip->bm_lnInBrush);
  50. pbmBrushMip->bm_pbrBrush = this;
  51. // add the object to the brush mip
  52. pbmBrushMip->AddFromObject3D_t(ob);
  53. }
  54. /*
  55. * Add an object3d to brush. (returns pointer to the first created sector)
  56. */
  57. CBrushSector *CBrushMip::AddFromObject3D_t(CObject3D &ob) // throw char *
  58. {
  59. CSetFPUPrecision sfp(FPT_53BIT);
  60. _pfWorldEditingProfile.StartTimer(CWorldEditingProfile::PTI_ADDFROMOBJECT3D);
  61. // optimize the object, to remove replicated and unused elements and find edge inverses
  62. CBrush3D::OptimizeObject3D(ob);
  63. // turn this on to dump result of all CSG operations
  64. #ifndef NDEBUG
  65. // ob.DebugDump();
  66. #endif //NDEBUG
  67. // create as much new sectors in brush mip as there are sectors in object
  68. CBrushSector *pbscSectors = bm_abscSectors.New(ob.ob_aoscSectors.Count());
  69. CBrushSector *pbscFirstSector = pbscSectors;
  70. // for each sector in the object
  71. FOREACHINDYNAMICARRAY(ob.ob_aoscSectors, CObjectSector, itosc) {
  72. // set brush sector's pointer to the brush
  73. pbscSectors->bsc_pbmBrushMip = this;
  74. // fill one brush sector from it
  75. pbscSectors->FromObjectSector_t(*itosc);
  76. pbscSectors++;
  77. }
  78. _pfWorldEditingProfile.StopTimer(CWorldEditingProfile::PTI_ADDFROMOBJECT3D);
  79. // return pointer to first created sector
  80. return pbscFirstSector;
  81. }
  82. /*
  83. * Fill a brush sector from a sector in object3d.
  84. */
  85. void CBrushSector::FromObjectSector_t(CObjectSector &osc) // throw char *
  86. {
  87. // copy sector color
  88. bsc_colColor = osc.osc_colColor;
  89. bsc_colAmbient = osc.osc_colAmbient;
  90. bsc_ulFlags = osc.osc_ulFlags[0] & ~(BSCF_SELECTED|BSCF_SELECTEDFORCSG);
  91. bsc_ulFlags2 = osc.osc_ulFlags[1];
  92. bsc_ulVisFlags = osc.osc_ulFlags[2];
  93. bsc_strName = osc.osc_strName;
  94. // lock the object elements
  95. osc.LockAll();
  96. // lock the brush elements
  97. LockAll();
  98. /* Copy vertices. */
  99. // get the number of vertices in object
  100. INDEX ctVertices = osc.osc_aovxVertices.Count();
  101. // create that much vertices in brush
  102. bsc_abvxVertices.New(ctVertices);
  103. bsc_awvxVertices.New(ctVertices);
  104. // copy all vertices and set their indices
  105. for(INDEX iVertex=0; iVertex<ctVertices; iVertex++) {
  106. bsc_abvxVertices[iVertex].bvx_vdPreciseRelative = osc.osc_aovxVertices[iVertex];
  107. bsc_abvxVertices[iVertex].bvx_pbscSector = this;
  108. osc.osc_aovxVertices[iVertex].ovx_Index = iVertex;
  109. }
  110. /* Copy planes. */
  111. // get the number of planes in object
  112. INDEX ctPlanes = osc.osc_aoplPlanes.Count();
  113. // create that much planes in brush
  114. bsc_abplPlanes.New(ctPlanes);
  115. bsc_awplPlanes.New(ctPlanes);
  116. // copy all planes and set their indices
  117. for(INDEX iPlane=0; iPlane<ctPlanes; iPlane++) {
  118. bsc_abplPlanes[iPlane].bpl_pldPreciseRelative = osc.osc_aoplPlanes[iPlane];
  119. osc.osc_aoplPlanes[iPlane].opl_Index = iPlane;
  120. }
  121. /* Copy edges. */
  122. // get the number of edges in object
  123. INDEX ctEdges = osc.osc_aoedEdges.Count();
  124. // create that much edges in brush
  125. bsc_abedEdges.New(ctEdges);
  126. bsc_awedEdges.New(ctEdges);
  127. // for all edges in object
  128. for(INDEX iEdge=0; iEdge<ctEdges; iEdge++) {
  129. CObjectEdge &oed = osc.osc_aoedEdges[iEdge]; // object edge alias
  130. CBrushEdge &bed = bsc_abedEdges[iEdge]; // brush edge alias
  131. CWorkingEdge &wed = bsc_awedEdges[iEdge];
  132. // set the brush edge
  133. bed.bed_pbvxVertex0 = &bsc_abvxVertices[oed.oed_Vertex0->ovx_Index];
  134. bed.bed_pbvxVertex1 = &bsc_abvxVertices[oed.oed_Vertex1->ovx_Index];
  135. // set the working edge
  136. bed.bed_pwedWorking = &wed;
  137. wed.wed_iwvx0 = oed.oed_Vertex0->ovx_Index;
  138. wed.wed_iwvx1 = oed.oed_Vertex1->ovx_Index;
  139. // set object edge index
  140. oed.oed_Index = iEdge;
  141. }
  142. /* Copy polygons. */
  143. // get the number of polygons in object
  144. INDEX ctPolygons = osc.osc_aopoPolygons.Count();
  145. // create that much polygons in brush
  146. bsc_abpoPolygons.New(ctPolygons);
  147. // copy all polygons and set their indices
  148. for(INDEX iPolygon=0; iPolygon<ctPolygons; iPolygon++) {
  149. CBrushPolygon &bpo = bsc_abpoPolygons[iPolygon]; // brush polygon alias
  150. CObjectPolygon &opo = osc.osc_aopoPolygons[iPolygon]; // object polygon alias
  151. // get plane
  152. bpo.bpo_pbplPlane = &bsc_abplPlanes[opo.opo_Plane->opl_Index];
  153. // get texture from object material
  154. bpo.bpo_abptTextures[0].bpt_toTexture.SetData_t(opo.opo_Material->omt_Name);
  155. bpo.bpo_abptTextures[1].bpt_toTexture.SetData_t(opo.opo_Material->omt_strName2);
  156. bpo.bpo_abptTextures[2].bpt_toTexture.SetData_t(opo.opo_Material->omt_strName3);
  157. // set polygon index
  158. opo.opo_Index = iPolygon;
  159. // set polygon color
  160. bpo.bpo_colColor = opo.opo_colorColor;
  161. // set polygon mapping
  162. bpo.bpo_abptTextures[0].bpt_mdMapping = opo.opo_amdMappings[0];
  163. bpo.bpo_abptTextures[1].bpt_mdMapping = opo.opo_amdMappings[1];
  164. bpo.bpo_abptTextures[2].bpt_mdMapping = opo.opo_amdMappings[2];
  165. bpo.bpo_mdShadow = opo.opo_amdMappings[3];
  166. // set sector pointer
  167. bpo.bpo_pbscSector = this;
  168. // copy polygon properties
  169. const int sizeTextureProperties = sizeof(bpo.bpo_abptTextures[0].bpt_auProperties);
  170. const int sizePolygonProperties = sizeof(CBrushPolygonProperties);
  171. ASSERT(sizeof(opo.opo_ubUserData)>=sizePolygonProperties+3*sizeTextureProperties);
  172. UBYTE *pubUserData = (UBYTE*)&opo.opo_ubUserData;
  173. memcpy(&bpo.bpo_bppProperties, pubUserData, sizePolygonProperties);
  174. memcpy(&bpo.bpo_abptTextures[0].bpt_auProperties,
  175. pubUserData+sizePolygonProperties+0*sizeTextureProperties,
  176. sizeTextureProperties);
  177. memcpy(&bpo.bpo_abptTextures[1].bpt_auProperties,
  178. pubUserData+sizePolygonProperties+1*sizeTextureProperties,
  179. sizeTextureProperties);
  180. memcpy(&bpo.bpo_abptTextures[2].bpt_auProperties,
  181. pubUserData+sizePolygonProperties+2*sizeTextureProperties,
  182. sizeTextureProperties);
  183. bpo.bpo_colShadow = *(ULONG*)(pubUserData+sizePolygonProperties+3*sizeTextureProperties),
  184. // set polygon flags
  185. bpo.bpo_ulFlags = opo.opo_ulFlags & ~(OPOF_IGNOREDBYCSG|BPOF_SELECTED);
  186. // if the polygon was just created
  187. if(!(bpo.bpo_ulFlags&BPOF_WASBRUSHPOLYGON)) {
  188. // initialize its textures and properties properly
  189. bpo.bpo_bppProperties.bpp_ubShadowBlend = 1;
  190. bpo.bpo_colShadow = C_WHITE|CT_OPAQUE;
  191. bpo.bpo_abptTextures[0].s.bpt_colColor = C_WHITE|CT_OPAQUE;
  192. bpo.bpo_abptTextures[0].s.bpt_ubFlags = BPTF_DISCARDABLE;
  193. bpo.bpo_abptTextures[0].s.bpt_ubScroll = 0;
  194. bpo.bpo_abptTextures[0].s.bpt_ubBlend = BPT_BLEND_OPAQUE;
  195. bpo.bpo_abptTextures[1].s.bpt_colColor = C_WHITE|CT_OPAQUE;
  196. bpo.bpo_abptTextures[1].s.bpt_ubFlags = BPTF_DISCARDABLE;
  197. bpo.bpo_abptTextures[1].s.bpt_ubScroll = 0;
  198. bpo.bpo_abptTextures[1].s.bpt_ubBlend = BPT_BLEND_SHADE;
  199. bpo.bpo_abptTextures[2].s.bpt_colColor = C_WHITE|CT_OPAQUE;
  200. bpo.bpo_abptTextures[2].s.bpt_ubFlags = BPTF_DISCARDABLE;
  201. bpo.bpo_abptTextures[2].s.bpt_ubScroll = 0;
  202. bpo.bpo_abptTextures[2].s.bpt_ubBlend = BPT_BLEND_SHADE;
  203. bpo.bpo_ulFlags|=BPOF_WASBRUSHPOLYGON;
  204. }
  205. // if it was a wall, but it became a portal now
  206. if (!(bpo.bpo_ulFlags&BPOF_WASPORTAL) && (bpo.bpo_ulFlags&OPOF_PORTAL)) {
  207. // turn on usual portal flags
  208. bpo.bpo_ulFlags |= (BPOF_PASSABLE|BPOF_PORTAL);
  209. // make its first texture translucent
  210. bpo.bpo_abptTextures[0].s.bpt_ubBlend = BPT_BLEND_BLEND;
  211. // make its shadow additive
  212. bpo.bpo_bppProperties.bpp_ubShadowBlend = BPT_BLEND_ADD;
  213. // if it was a portal, but it became a wall now
  214. } else if ((bpo.bpo_ulFlags&BPOF_WASPORTAL) && !(bpo.bpo_ulFlags&OPOF_PORTAL)) {
  215. // turn off usual portal flags
  216. bpo.bpo_ulFlags &= ~(BPOF_PASSABLE|BPOF_PORTAL);
  217. // make its first texture opaque
  218. bpo.bpo_abptTextures[0].s.bpt_ubBlend = BPT_BLEND_OPAQUE;
  219. // make its shadow shading
  220. bpo.bpo_bppProperties.bpp_ubShadowBlend = BPT_BLEND_SHADE;
  221. }
  222. // get the brush of this sector
  223. CBrush3D *pbr = bsc_pbmBrushMip->bm_pbrBrush;
  224. ASSERT(pbr!=NULL);
  225. // if the brush is field
  226. if (pbr->br_pfsFieldSettings!=NULL) {
  227. // set polygon flags for fields
  228. bpo.bpo_ulFlags|=BPOF_PORTAL|BPOF_PASSABLE;
  229. }
  230. // get the number of edges in object polygon
  231. INDEX ctPolygonEdges = opo.opo_PolygonEdges.Count();
  232. // create that much edges in brush polygon
  233. bpo.bpo_abpePolygonEdges.New(ctPolygonEdges);
  234. // for all edges in object polygon
  235. INDEX iPolygonEdge=0;
  236. FOREACHINDYNAMICARRAY(opo.opo_PolygonEdges, CObjectPolygonEdge, itope) {
  237. // get corresponding polygon edge in brush polygon
  238. CBrushPolygonEdge &bpe = bpo.bpo_abpePolygonEdges[iPolygonEdge];
  239. // set edge reference
  240. bpe.bpe_pbedEdge = &bsc_abedEdges[itope->ope_Edge->oed_Index];
  241. // set backward flag
  242. bpe.bpe_bReverse = itope->ope_Backward;
  243. iPolygonEdge++;
  244. }
  245. }
  246. // unlock the object elements
  247. osc.UnlockAll();
  248. // unlock the brush elements
  249. UnlockAll();
  250. // update changed sector's data after dragging vertices or importing
  251. UpdateSector();
  252. }