shapes.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654
  1. /*
  2. BobToolz plugin for GtkRadiant
  3. Copyright (C) 2001 Gordon Biggans
  4. This library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Lesser General Public
  6. License as published by the Free Software Foundation; either
  7. version 2.1 of the License, or (at your option) any later version.
  8. This library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with this library; if not, write to the Free Software
  14. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  15. */
  16. #include "StdAfx.h"
  17. #include "shapes.h"
  18. #include "gtkr_list.h"
  19. #include "DPoint.h"
  20. #include "DPlane.h"
  21. #include "str.h"
  22. #include "misc.h"
  23. #include "funchandlers.h"
  24. #include "iundo.h"
  25. #include "refcounted_ptr.h"
  26. #include <vector>
  27. #include <list>
  28. #include <map>
  29. #include <algorithm>
  30. #include "scenelib.h"
  31. //#include "dialogs-gtk.h"
  32. /************************
  33. Cube Diagram
  34. ************************/
  35. /*
  36. 7 ----- 5
  37. /| /|
  38. / | / |
  39. / | / |
  40. 4 ----- 6 |
  41. | 2|_|___|8
  42. | / | /
  43. | / | / ----> WEST, definitely
  44. |/ | /
  45. 1|_____|/3
  46. */
  47. /************************
  48. Global Variables
  49. ************************/
  50. vec3_t g_Origin = {0.0f, 0.0f, 0.0f};
  51. extern bool bFacesAll[];
  52. /************************
  53. Helper Functions
  54. ************************/
  55. float Deg2Rad(float angle)
  56. {
  57. return (float)(angle*Q_PI/180);
  58. }
  59. void AddFaceWithTexture(scene::Node* brush, vec3_t va, vec3_t vb, vec3_t vc, const char* texture, bool detail)
  60. {
  61. _QERFaceData faceData;
  62. FillDefaultTexture(&faceData, va, vb, vc, texture);
  63. if(detail)
  64. faceData.m_texdef.contents |= FACE_DETAIL;
  65. #if 0
  66. brush->m_brush->addPlane(faceData.m_p0, faceData.m_p1, faceData.m_p2, faceData.m_texdef);
  67. #endif
  68. }
  69. void AddFaceWithTextureScaled(scene::Node* brush, vec3_t va, vec3_t vb, vec3_t vc,
  70. const char* texture, bool bVertScale, bool bHorScale,
  71. float minX, float minY, float maxX, float maxY)
  72. {
  73. qtexture_t* pqtTexInfo;
  74. // TTimo: there used to be a call to pfnHasShader here
  75. // this was not necessary. In Radiant everything is shader.
  76. // If a texture doesn't have a shader script, a default shader object is used.
  77. // The IShader object was leaking also
  78. // collect texture info: sizes, etc
  79. IShader* i = QERApp_Shader_ForName(texture);
  80. pqtTexInfo = i->getTexture(); // shader width/height doesn't come out properly
  81. if(pqtTexInfo)
  82. {
  83. float scale[2] = {0.5f, 0.5f};
  84. float shift[2] = {0, 0};
  85. if(bHorScale)
  86. {
  87. int texWidth = pqtTexInfo->width;
  88. float width = maxX - minX;
  89. scale[0] = width/texWidth;
  90. shift[0] = -(float)((int)maxX%(int)width)/scale[0];
  91. }
  92. if(bVertScale)
  93. {
  94. int texHeight = pqtTexInfo->height;
  95. float height = maxY - minY;
  96. scale[1] = height/texHeight;
  97. shift[1] = (float)((int)minY%(int)height)/scale[1];
  98. }
  99. _QERFaceData addFace;
  100. FillDefaultTexture(&addFace, va, vb, vc, texture);
  101. addFace.m_texdef.scale[0] = scale[0];
  102. addFace.m_texdef.scale[1] = scale[1];
  103. addFace.m_texdef.shift[0] = shift[0];
  104. addFace.m_texdef.shift[1] = shift[1];
  105. #if 0
  106. brush->m_brush->addPlane(addFace.m_p0, addFace.m_p1, addFace.m_p2, addFace.m_texdef);
  107. #endif
  108. }
  109. else
  110. {
  111. // shouldn't even get here, as default missing texture should be returned if
  112. // texture doesn't exist, but just in case
  113. AddFaceWithTexture(brush, va, vb, vc, texture, FALSE);
  114. Sys_ERROR("BobToolz::Invalid Texture Name-> %s", texture);
  115. }
  116. // the IShader is not kept referenced, DecRef it
  117. i->DecRef();
  118. }
  119. /************************
  120. --Main Functions--
  121. ************************/
  122. void Build_Wedge(int dir, vec3_t min, vec3_t max, bool bUp)
  123. {
  124. scene::Node* newBrush = Brush_AllocNode();
  125. vec3_t v1, v2, v3, v5, v6, v7, v8;
  126. VectorCopy(min, v1);
  127. VectorCopy(min, v2);
  128. VectorCopy(min, v3);
  129. VectorCopy(max, v5);
  130. VectorCopy(max, v6);
  131. VectorCopy(max, v7);
  132. VectorCopy(max, v8);
  133. v2[0] = max[0];
  134. v3[1] = max[1];
  135. v6[0] = min[0];
  136. v7[1] = min[1];
  137. v8[2] = min[2];
  138. if(bUp)
  139. {
  140. if(dir != MOVE_EAST)
  141. AddFaceWithTexture(newBrush, v1, v3, v6, "textures/common/caulk", FALSE);
  142. if(dir != MOVE_WEST)
  143. AddFaceWithTexture(newBrush, v7, v5, v8, "textures/common/caulk", FALSE);
  144. if(dir != MOVE_NORTH)
  145. AddFaceWithTexture(newBrush, v1, v7, v2, "textures/common/caulk", FALSE);
  146. if(dir != MOVE_SOUTH)
  147. AddFaceWithTexture(newBrush, v3, v8, v6, "textures/common/caulk", FALSE);
  148. AddFaceWithTexture(newBrush, v1, v2, v3, "textures/common/caulk", FALSE);
  149. if(dir == MOVE_EAST)
  150. AddFaceWithTexture(newBrush, v1, v3, v5, "textures/common/caulk", FALSE);
  151. if(dir == MOVE_WEST)
  152. AddFaceWithTexture(newBrush, v2, v6, v8, "textures/common/caulk", FALSE);
  153. if(dir == MOVE_NORTH)
  154. AddFaceWithTexture(newBrush, v1, v6, v5, "textures/common/caulk", FALSE);
  155. if(dir == MOVE_SOUTH)
  156. AddFaceWithTexture(newBrush, v7, v3, v8, "textures/common/caulk", FALSE);
  157. }
  158. else
  159. {
  160. if(dir != MOVE_WEST)
  161. AddFaceWithTexture(newBrush, v7, v5, v8, "textures/common/caulk", FALSE);
  162. if(dir != MOVE_EAST)
  163. AddFaceWithTexture(newBrush, v1, v3, v6, "textures/common/caulk", FALSE);
  164. if(dir != MOVE_NORTH)
  165. AddFaceWithTexture(newBrush, v3, v8, v6, "textures/common/caulk", FALSE);
  166. if(dir != MOVE_SOUTH)
  167. AddFaceWithTexture(newBrush, v1, v7, v2, "textures/common/caulk", FALSE);
  168. AddFaceWithTexture(newBrush, v6, v5, v7, "textures/common/caulk", FALSE);
  169. if(dir == MOVE_WEST)
  170. AddFaceWithTexture(newBrush, v1, v5, v3, "textures/common/caulk", FALSE);
  171. if(dir == MOVE_EAST)
  172. AddFaceWithTexture(newBrush, v2, v8, v6, "textures/common/caulk", FALSE);
  173. if(dir == MOVE_NORTH)
  174. AddFaceWithTexture(newBrush, v1, v5, v6, "textures/common/caulk", FALSE);
  175. if(dir == MOVE_SOUTH)
  176. AddFaceWithTexture(newBrush, v7, v8, v3, "textures/common/caulk", FALSE);
  177. }
  178. GetWorldspawn()->m_traverse->insert(newBrush);
  179. }
  180. //-----------------------------------------------------------------------------------
  181. //-----------------------------------------------------------------------------------
  182. void Build_StairStep_Wedge(int dir, vec3_t min, vec3_t max, const char* mainTexture, const char* riserTexture, bool detail)
  183. {
  184. scene::Node* newBrush = Brush_AllocNode();
  185. //----- Build Outer Bounds ---------
  186. vec3_t v1, v2, v3, v5, v6, v7, v8;
  187. VectorCopy(min, v1);
  188. VectorCopy(min, v2);
  189. VectorCopy(min, v3);
  190. VectorCopy(max, v5);
  191. VectorCopy(max, v6);
  192. VectorCopy(max, v7);
  193. VectorCopy(max, v8);
  194. v2[0] = max[0];
  195. v3[1] = max[1];
  196. v6[0] = min[0];
  197. v7[1] = min[1];
  198. v8[2] = min[2];
  199. //v8 needed this time, becoz of sloping faces (2-4-6-8)
  200. //----------------------------------
  201. AddFaceWithTexture(newBrush, v6, v5, v7, mainTexture, detail);
  202. if(dir != MOVE_EAST)
  203. {
  204. if(dir == MOVE_WEST)
  205. AddFaceWithTexture(newBrush, v5, v2, v7, riserTexture, detail);
  206. else
  207. AddFaceWithTexture(newBrush, v5, v2, v7, "textures/common/caulk", detail);
  208. }
  209. if(dir != MOVE_WEST)
  210. {
  211. if(dir == MOVE_EAST)
  212. AddFaceWithTexture(newBrush, v1, v3, v6, riserTexture, detail);
  213. else
  214. AddFaceWithTexture(newBrush, v1, v3, v6, "textures/common/caulk", detail);
  215. }
  216. if(dir != MOVE_NORTH)
  217. {
  218. if(dir == MOVE_SOUTH)
  219. AddFaceWithTexture(newBrush, v3, v5, v6, riserTexture, detail);
  220. else
  221. AddFaceWithTexture(newBrush, v3, v5, v6, "textures/common/caulk", detail);
  222. }
  223. if(dir != MOVE_SOUTH)
  224. {
  225. if(dir == MOVE_NORTH)
  226. AddFaceWithTexture(newBrush, v1, v7, v2, riserTexture, detail);
  227. else
  228. AddFaceWithTexture(newBrush, v1, v7, v2, "textures/common/caulk", detail);
  229. }
  230. if(dir == MOVE_EAST)
  231. AddFaceWithTexture(newBrush, v1, v5, v3, "textures/common/caulk", detail);
  232. if(dir == MOVE_WEST)
  233. AddFaceWithTexture(newBrush, v2, v8, v6, "textures/common/caulk", detail);
  234. if(dir == MOVE_NORTH)
  235. AddFaceWithTexture(newBrush, v1, v5, v6, "textures/common/caulk", detail);
  236. if(dir == MOVE_SOUTH)
  237. AddFaceWithTexture(newBrush, v7, v8, v3, "textures/common/caulk", detail);
  238. GetWorldspawn()->m_traverse->insert(newBrush);
  239. }
  240. //-----------------------------------------------------------------------------------
  241. //-----------------------------------------------------------------------------------
  242. // internal use only, to get a box without finishing construction
  243. scene::Node* Build_Get_BoundingCube_Selective(vec3_t min, vec3_t max, char* texture, bool* useFaces)
  244. {
  245. scene::Node* newBrush = Brush_AllocNode();
  246. //----- Build Outer Bounds ---------
  247. vec3_t v1, v2, v3, v5, v6, v7;
  248. VectorCopy(min, v1);
  249. VectorCopy(min, v2);
  250. VectorCopy(min, v3);
  251. VectorCopy(max, v5);
  252. VectorCopy(max, v6);
  253. VectorCopy(max, v7);
  254. v2[0] = max[0];
  255. v3[1] = max[1];
  256. v6[0] = min[0];
  257. v7[1] = min[1];
  258. //----------------------------------
  259. //----- Add Six Cube Faces ---------
  260. if(useFaces[0])
  261. AddFaceWithTexture(newBrush, v1, v2, v3, texture, FALSE);
  262. if(useFaces[1])
  263. AddFaceWithTexture(newBrush, v1, v3, v6, texture, FALSE);
  264. if(useFaces[2])
  265. AddFaceWithTexture(newBrush, v1, v7, v2, texture, FALSE);
  266. if(useFaces[3])
  267. AddFaceWithTexture(newBrush, v5, v6, v3, texture, FALSE);
  268. if(useFaces[4])
  269. AddFaceWithTexture(newBrush, v5, v2, v7, texture, FALSE);
  270. if(useFaces[5])
  271. AddFaceWithTexture(newBrush, v5, v7, v6, texture, FALSE);
  272. //----------------------------------
  273. return newBrush;
  274. }
  275. scene::Node* Build_Get_BoundingCube(vec3_t min, vec3_t max, char* texture)
  276. {
  277. return Build_Get_BoundingCube_Selective(min, max, texture, bFacesAll);
  278. }
  279. //-----------------------------------------------------------------------------------
  280. //-----------------------------------------------------------------------------------
  281. void Build_StairStep(vec3_t min, vec3_t max, const char* mainTexture, const char* riserTexture, int direction)
  282. {
  283. scene::Node* newBrush = Brush_AllocNode();
  284. //----- Build Outer Bounds ---------
  285. vec3_t v1, v2, v3, v5, v6, v7;
  286. VectorCopy(min, v1);
  287. VectorCopy(min, v2);
  288. VectorCopy(min, v3);
  289. VectorCopy(max, v5);
  290. VectorCopy(max, v6);
  291. VectorCopy(max, v7);
  292. v2[0] = max[0];
  293. v3[1] = max[1];
  294. v6[0] = min[0];
  295. v7[1] = min[1];
  296. //----------------------------------
  297. AddFaceWithTexture(newBrush, v6, v5, v7, mainTexture, FALSE);
  298. // top gets current texture
  299. if(direction == MOVE_EAST)
  300. AddFaceWithTexture(newBrush, v1, v3, v6, riserTexture, FALSE);
  301. else
  302. AddFaceWithTexture(newBrush, v1, v3, v6, "textures/common/caulk", FALSE);
  303. // west facing side, etc...
  304. if(direction == MOVE_NORTH)
  305. AddFaceWithTexture(newBrush, v1, v7, v2, riserTexture, FALSE);
  306. else
  307. AddFaceWithTexture(newBrush, v1, v7, v2, "textures/common/caulk", FALSE);
  308. if(direction == MOVE_SOUTH)
  309. AddFaceWithTexture(newBrush, v3, v5, v6, riserTexture, FALSE);
  310. else
  311. AddFaceWithTexture(newBrush, v3, v5, v6, "textures/common/caulk", FALSE);
  312. if(direction == MOVE_WEST)
  313. AddFaceWithTexture(newBrush, v7, v5, v2, riserTexture, FALSE);
  314. else
  315. AddFaceWithTexture(newBrush, v7, v5, v2, "textures/common/caulk", FALSE);
  316. AddFaceWithTexture(newBrush, v1, v2, v3, "textures/common/caulk", FALSE);
  317. // base is caulked
  318. GetWorldspawn()->m_traverse->insert(newBrush);
  319. // finish brush
  320. }
  321. //-----------------------------------------------------------------------------------
  322. //-----------------------------------------------------------------------------------
  323. void BuildDoorsX2(vec3_t min, vec3_t max,
  324. bool bSclMainHor, bool bSclMainVert,
  325. bool bSclTrimHor, bool bSclTrimVert,
  326. const char* mainTexture, const char* trimTexture,
  327. int direction)
  328. {
  329. int xy;
  330. if(direction == 0)
  331. xy = 0;
  332. else
  333. xy = 1;
  334. //----- Build Outer Bounds ---------
  335. vec3_t v1, v2, v3, v5, v6, v7, ve_1, ve_2, ve_3;
  336. VectorCopy(min, v1);
  337. VectorCopy(min, v2);
  338. VectorCopy(min, v3);
  339. VectorCopy(max, v5);
  340. VectorCopy(max, v6);
  341. VectorCopy(max, v7);
  342. v2[0] = max[0];
  343. v3[1] = max[1];
  344. v6[0] = min[0];
  345. v7[1] = min[1];
  346. float width = (max[xy] - min[xy])/2;
  347. if(direction == 0)
  348. {
  349. VectorCopy(v1, ve_1);
  350. VectorCopy(v3, ve_2);
  351. VectorCopy(v6, ve_3);
  352. }
  353. else
  354. {
  355. VectorCopy(v7, ve_1);
  356. VectorCopy(v1, ve_2);
  357. VectorCopy(v2, ve_3);
  358. }
  359. ve_1[xy] += width;
  360. ve_2[xy] += width;
  361. ve_3[xy] += width;
  362. //----------------------------------
  363. scene::Node* newBrush1 = Brush_AllocNode();
  364. scene::Node* newBrush2 = Brush_AllocNode();
  365. AddFaceWithTexture(newBrush1, v1, v2, v3, "textures/common/caulk", FALSE);
  366. AddFaceWithTexture(newBrush1, v5, v7, v6, "textures/common/caulk", FALSE);
  367. AddFaceWithTexture(newBrush2, v1, v2, v3, "textures/common/caulk", FALSE);
  368. AddFaceWithTexture(newBrush2, v5, v7, v6, "textures/common/caulk", FALSE);
  369. if(direction == 0)
  370. {
  371. AddFaceWithTexture(newBrush1, v1, v3, v6, "textures/common/caulk", FALSE);
  372. AddFaceWithTexture(newBrush2, v5, v2, v7, "textures/common/caulk", FALSE);
  373. }
  374. else
  375. {
  376. AddFaceWithTexture(newBrush1, v1, v7, v2, "textures/common/caulk", FALSE);
  377. AddFaceWithTexture(newBrush2, v5, v6, v3, "textures/common/caulk", FALSE);
  378. }
  379. if(direction == 0)
  380. {
  381. AddFaceWithTextureScaled(newBrush1, v1, v7, v2, mainTexture, bSclMainVert, bSclMainHor,
  382. min[0], min[2], max[0], max[2]);
  383. AddFaceWithTextureScaled(newBrush1, v5, v6, v3, mainTexture, bSclMainVert, bSclMainHor,
  384. max[0], min[2], min[0], max[2]);
  385. AddFaceWithTextureScaled(newBrush2, v1, v7, v2, mainTexture, bSclMainVert, bSclMainHor,
  386. min[0], min[2], max[0], max[2]);
  387. AddFaceWithTextureScaled(newBrush2, v5, v6, v3, mainTexture, bSclMainVert, bSclMainHor,
  388. max[0], min[2], min[0], max[2]); // flip max/min to reverse tex dir
  389. AddFaceWithTextureScaled(newBrush1, ve_3, ve_2, ve_1, trimTexture, bSclTrimVert, bSclTrimHor,
  390. min[1], min[2], max[1], max[2]);
  391. AddFaceWithTextureScaled(newBrush2, ve_1, ve_2, ve_3, trimTexture, bSclTrimVert, bSclTrimHor,
  392. max[1], min[2], min[1], max[2]);
  393. }
  394. else
  395. {
  396. AddFaceWithTextureScaled(newBrush1, v1, v3, v6, mainTexture, bSclMainVert, bSclMainHor,
  397. min[1], min[2], max[1], max[2]);
  398. AddFaceWithTextureScaled(newBrush1, v5, v2, v7, mainTexture, bSclMainVert, bSclMainHor,
  399. max[1], min[2], min[1], max[2]);
  400. AddFaceWithTextureScaled(newBrush2, v1, v3, v6, mainTexture, bSclMainVert, bSclMainHor,
  401. min[1], min[2], max[1], max[2]);
  402. AddFaceWithTextureScaled(newBrush2, v5, v2, v7, mainTexture, bSclMainVert, bSclMainHor,
  403. max[1], min[2], min[1], max[2]); // flip max/min to reverse tex dir
  404. AddFaceWithTextureScaled(newBrush1, ve_1, ve_2, ve_3, trimTexture, bSclTrimVert, bSclTrimHor,
  405. min[0], min[2], max[0], max[2]);
  406. AddFaceWithTextureScaled(newBrush2, ve_3, ve_2, ve_1, trimTexture, bSclTrimVert, bSclTrimHor,
  407. max[0], min[2], min[0], max[2]);
  408. }
  409. //----------------------------------
  410. scene::Node* pEDoor1 = GlobalEntityCreator().createEntity("func_door");
  411. scene::Node* pEDoor2 = GlobalEntityCreator().createEntity("func_door");
  412. if(direction == 0)
  413. {
  414. pEDoor1->m_entity->setkeyvalue("angle", "180");
  415. pEDoor2->m_entity->setkeyvalue("angle", "360");
  416. }
  417. else
  418. {
  419. pEDoor1->m_entity->setkeyvalue("angle", "270");
  420. pEDoor2->m_entity->setkeyvalue("angle", "90");
  421. }
  422. srand((unsigned)time(NULL));
  423. char teamname[256];
  424. sprintf(teamname, "t%i", rand());
  425. pEDoor1->m_entity->setkeyvalue("team", teamname);
  426. pEDoor2->m_entity->setkeyvalue("team", teamname);
  427. pEDoor1->m_traverse->insert(newBrush1);
  428. pEDoor2->m_traverse->insert(newBrush2);
  429. GlobalSceneGraph().root()->m_traverse->insert(pEDoor1);
  430. GlobalSceneGraph().root()->m_traverse->insert(pEDoor2);
  431. // ResetCurrentTexture();
  432. }
  433. //-----------------------------------------------------------------------------------
  434. //-----------------------------------------------------------------------------------
  435. void MakeBevel(vec3_t vMin, vec3_t vMax)
  436. {
  437. scene::Node* patch = Patch_AllocNode();
  438. aabb_t aabb;
  439. aabb_construct_for_vec3(&aabb, vMin, vMax);
  440. #if 0
  441. patch->m_patch->ConstructPrefab(&aabb, eBevel, 2); // 2 == XY view
  442. #endif
  443. GetWorldspawn()->m_traverse->insert(patch);
  444. }
  445. void BuildCornerStairs(vec3_t vMin, vec3_t vMax, int nSteps, const char* mainTexture, const char* riserTex)
  446. {
  447. vec3_t* topPoints = new vec3_t[nSteps+1];
  448. vec3_t* botPoints = new vec3_t[nSteps+1];
  449. bool bFacesUse[6] = {TRUE, TRUE, FALSE, TRUE, FALSE, FALSE};
  450. vec3_t centre;
  451. VectorCopy(vMin, centre);
  452. centre[0] = vMax[0];
  453. int height = (int)(vMax[2] - vMin[2]) / nSteps;
  454. vec3_t vTop, vBot;
  455. VectorCopy(vMax, vTop);
  456. VectorCopy(vMin, vBot);
  457. vTop[2] = vMin[2] + height;
  458. int i;
  459. for(i = 0; i <= nSteps; i++)
  460. {
  461. VectorCopy(centre, topPoints[i]);
  462. VectorCopy(centre, botPoints[i]);
  463. topPoints[i][2] = vMax[2];
  464. botPoints[i][2] = vMin[2];
  465. topPoints[i][0] -= 10 * sinf( Q_PI * i / ( 2 * nSteps ) );
  466. topPoints[i][1] += 10 * cosf( Q_PI * i / ( 2 * nSteps ) );
  467. botPoints[i][0] = topPoints[i][0];
  468. botPoints[i][1] = topPoints[i][1];
  469. }
  470. vec3_t tp[3];
  471. for(int j = 0; j < 3; j++)
  472. VectorCopy(topPoints[j], tp[j]);
  473. for(i = 0; i < nSteps; i++)
  474. {
  475. scene::Node* brush = Build_Get_BoundingCube_Selective(vBot, vTop, "textures/common/caulk", bFacesUse);
  476. for(int j = 0; j < 3; j++)
  477. tp[j][2] = vTop[2];
  478. AddFaceWithTexture(brush, tp[2], tp[1], tp[0], mainTexture, FALSE);
  479. AddFaceWithTexture(brush, centre, botPoints[i+1], topPoints[i+1], "textures/common/caulk", FALSE);
  480. AddFaceWithTexture(brush, centre, topPoints[i], botPoints[i], riserTex, FALSE);
  481. GetWorldspawn()->m_traverse->insert(brush);
  482. vTop[2] += height;
  483. vBot[2] += height;
  484. }
  485. delete[] topPoints;
  486. delete[] botPoints;
  487. vMin[2] += height;
  488. vMax[2] += height;
  489. MakeBevel(vMin, vMax);
  490. }