Subversion Repositories Games.Descent

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Portions of this file are copyright Rebirth contributors and licensed as
  3.  * described in COPYING.txt.
  4.  * Portions of this file are copyright Parallax Software and licensed
  5.  * according to the Parallax license below.
  6.  * See COPYING.txt for license details.
  7.  
  8. THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
  9. SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
  10. END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
  11. ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
  12. IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
  13. SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
  14. FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
  15. CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
  16. AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
  17. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
  18. */
  19.  
  20. /*
  21.  *
  22.  * Functions for sizing segments
  23.  *
  24.  */
  25.  
  26. #include <stdlib.h>
  27. #include "inferno.h"
  28. #include "editor.h"
  29. #include "editor/esegment.h"
  30. #include "dxxerror.h"
  31. #include "gameseg.h"
  32. #include "kdefs.h"
  33.  
  34. #include "compiler-range_for.h"
  35. #include "d_range.h"
  36.  
  37. #define XDIM    0
  38. #define YDIM    1
  39. #define ZDIM    2
  40.  
  41. #define MAX_MODIFIED_VERTICES   32
  42. static std::array<int, MAX_MODIFIED_VERTICES>           Modified_vertices;
  43. int             Modified_vertex_index = 0;
  44.  
  45. namespace dsx {
  46.  
  47. // ------------------------------------------------------------------------------------------
  48. static void validate_modified_segments(void)
  49. {
  50.         auto &LevelSharedVertexState = LevelSharedSegmentState.get_vertex_state();
  51.         auto &Vertices = LevelSharedVertexState.get_vertices();
  52.         int     v0;
  53.         visited_segment_bitarray_t modified_segments;
  54.         auto &vcvertptr = Vertices.vcptr;
  55.         for (int v=0; v<Modified_vertex_index; v++) {
  56.                 v0 = Modified_vertices[v];
  57.  
  58.                 range_for (const auto &&segp, vmsegptridx)
  59.                 {
  60.                         if (segp->segnum != segment_none)
  61.                         {
  62.                                 if (modified_segments[segp])
  63.                                         continue;
  64.                                 range_for (const auto w, segp->verts)
  65.                                         if (w == v0)
  66.                                         {
  67.                                                 modified_segments[segp] = true;
  68.                                                 validate_segment(vcvertptr, segp);
  69.                                                 for (unsigned s=0; s<MAX_SIDES_PER_SEGMENT; s++) {
  70.                                                         Num_tilings = 1;
  71.                                                         assign_default_uvs_to_side(segp, s);
  72.                                                 }
  73.                                                 break;
  74.                                         }
  75.                         }
  76.                 }
  77.         }
  78. }
  79.  
  80. // ------------------------------------------------------------------------------------------
  81. //      Scale vertex *vertp by vector *vp, scaled by scale factor scale_factor
  82. static void scale_vert_aux(const unsigned vertex_ind, const vms_vector &vp, const fix scale_factor)
  83. {
  84.         auto &LevelSharedVertexState = LevelSharedSegmentState.get_vertex_state();
  85.         auto &Vertices = LevelSharedVertexState.get_vertices();
  86.         auto &vmvertptr = Vertices.vmptr;
  87.         auto &vertp = *vmvertptr(vertex_ind);
  88.  
  89.         vertp.x += fixmul(vp.x,scale_factor)/2;
  90.         vertp.y += fixmul(vp.y,scale_factor)/2;
  91.         vertp.z += fixmul(vp.z,scale_factor)/2;
  92.  
  93.         Assert(Modified_vertex_index < MAX_MODIFIED_VERTICES);
  94.         Modified_vertices[Modified_vertex_index++] = vertex_ind;
  95. }
  96.  
  97. // ------------------------------------------------------------------------------------------
  98. static void scale_vert(const shared_segment &sp, const unsigned vertex_ind, const vms_vector &vp, const fix scale_factor)
  99. {
  100.         auto &verts = sp.verts;
  101.         switch (SegSizeMode) {
  102.                 case SEGSIZEMODE_FREE:
  103.                         if (is_free_vertex(vertex_ind))
  104.                                 scale_vert_aux(vertex_ind, vp, scale_factor);
  105.                         break;
  106.                 case SEGSIZEMODE_ALL:
  107.                         scale_vert_aux(vertex_ind, vp, scale_factor);
  108.                         break;
  109.                 case SEGSIZEMODE_CURSIDE: {
  110.                         range_for (const auto v, Side_to_verts[Curside])
  111.                                 if (verts[v] == vertex_ind)
  112.                                         scale_vert_aux(vertex_ind, vp, scale_factor);
  113.                         break;
  114.                 }
  115.                 case SEGSIZEMODE_EDGE: {
  116.                         range_for (const int v, xrange(2u))
  117.                                 if (verts[Side_to_verts[Curside][(Curedge+v)%4]] == vertex_ind)
  118.                                         scale_vert_aux(vertex_ind, vp, scale_factor);
  119.                         break;
  120.                 }
  121.                 case SEGSIZEMODE_VERTEX:
  122.                         if (verts[Side_to_verts[Curside][Curvert]] == vertex_ind)
  123.                                 scale_vert_aux(vertex_ind, vp, scale_factor);
  124.                         break;
  125.                 default:
  126.                         Error("Unsupported SegSizeMode in ksegsize.c/scale_vert = %i\n", SegSizeMode);
  127.         }
  128.  
  129. }
  130.  
  131. // ------------------------------------------------------------------------------------------
  132. static void scale_free_verts(const vmsegptr_t sp, const vms_vector &vp, int side, fix scale_factor)
  133. {
  134.         int             vertex_ind;
  135.         range_for (auto &v, Side_to_verts[side])
  136.         {
  137.                 vertex_ind = sp->verts[v];
  138.                 if (SegSizeMode || is_free_vertex(vertex_ind))
  139.                         scale_vert(sp, vertex_ind, vp, scale_factor);
  140.         }
  141.  
  142. }
  143.  
  144.  
  145. // -----------------------------------------------------------------------------
  146. //      Make segment *sp bigger in dimension dimension by amount amount.
  147. static void med_scale_segment_new(const vmsegptr_t sp, int dimension, fix amount)
  148. {
  149.         vms_matrix      mat;
  150.  
  151.         Modified_vertex_index = 0;
  152.  
  153.         med_extract_matrix_from_segment(sp, mat);
  154.  
  155.         const vms_vector *vec;
  156.         unsigned side0, side1;
  157.         switch (dimension) {
  158.                 case XDIM:
  159.                         side0 = WLEFT;
  160.                         side1 = WRIGHT;
  161.                         vec = &mat.rvec;
  162.                         break;
  163.                 case YDIM:
  164.                         side0 = WBOTTOM;
  165.                         side1 = WTOP;
  166.                         vec = &mat.uvec;
  167.                         break;
  168.                 case ZDIM:
  169.                         side0 = WFRONT;
  170.                         side1 = WBACK;
  171.                         vec = &mat.fvec;
  172.                         break;
  173.                 default:
  174.                         return;
  175.         }
  176.         scale_free_verts(sp, *vec, side0, -amount);
  177.         scale_free_verts(sp, *vec, side1, +amount);
  178.  
  179.         validate_modified_segments();
  180. }
  181.  
  182. // ------------------------------------------------------------------------------------------
  183. //      Extract a vector from a segment.  The vector goes from the start face to the end face.
  184. //      The point on each face is the average of the four points forming the face.
  185. static void extract_vector_from_segment_side(const vmsegptr_t sp, const unsigned side, vms_vector &vp, const unsigned vla, const unsigned vlb, const unsigned vra, const unsigned vrb)
  186. {
  187.         auto &LevelSharedVertexState = LevelSharedSegmentState.get_vertex_state();
  188.         auto &Vertices = LevelSharedVertexState.get_vertices();
  189.         auto &sv = Side_to_verts[side];
  190.         auto &verts = sp->verts;
  191.         auto &vcvertptr = Vertices.vcptr;
  192.         const auto v1 = vm_vec_sub(vcvertptr(verts[sv[vra]]), vcvertptr(verts[sv[vla]]));
  193.         const auto v2 = vm_vec_sub(vcvertptr(verts[sv[vrb]]), vcvertptr(verts[sv[vlb]]));
  194.         vm_vec_add(vp, v1, v2);
  195.         vm_vec_scale(vp, F1_0/2);
  196. }
  197.  
  198. // ------------------------------------------------------------------------------------------
  199. //      Extract the right vector from segment *sp, return in *vp.
  200. //      The forward vector is defined to be the vector from the the center of the left face of the segment
  201. // to the center of the right face of the segment.
  202. void med_extract_right_vector_from_segment_side(const vmsegptr_t sp, int sidenum, vms_vector &vp)
  203. {
  204.         extract_vector_from_segment_side(sp, sidenum, vp, 3, 2, 0, 1);
  205. }
  206.  
  207. // ------------------------------------------------------------------------------------------
  208. //      Extract the up vector from segment *sp, return in *vp.
  209. //      The forward vector is defined to be the vector from the the center of the bottom face of the segment
  210. // to the center of the top face of the segment.
  211. void med_extract_up_vector_from_segment_side(const vmsegptr_t sp, int sidenum, vms_vector &vp)
  212. {
  213.         extract_vector_from_segment_side(sp, sidenum, vp, 1, 2, 0, 3);
  214. }
  215.  
  216.  
  217. // -----------------------------------------------------------------------------
  218. //      Increase the size of Cursegp in dimension dimension by amount
  219. static int segsize_common(int dimension, fix amount)
  220. {
  221.         auto &LevelSharedVertexState = LevelSharedSegmentState.get_vertex_state();
  222.         auto &Vertices = LevelSharedVertexState.get_vertices();
  223.         vms_vector      uvec, rvec, fvec, scalevec;
  224.  
  225.         Degenerate_segment_found = 0;
  226.  
  227.         med_scale_segment_new(Cursegp, dimension, amount);
  228.  
  229.         med_extract_up_vector_from_segment_side(Cursegp, Curside, uvec);
  230.         med_extract_right_vector_from_segment_side(Cursegp, Curside, rvec);
  231.         auto &vcvertptr = Vertices.vcptr;
  232.         extract_forward_vector_from_segment(vcvertptr, Cursegp, fvec);
  233.  
  234.         scalevec.x = vm_vec_mag(rvec);
  235.         scalevec.y = vm_vec_mag(uvec);
  236.         scalevec.z = vm_vec_mag(fvec);
  237.  
  238.         if (Degenerate_segment_found) {
  239.                 Degenerate_segment_found = 0;
  240.                 editor_status("Applying scale would create degenerate segments.  Aborting scale.");
  241.                 med_scale_segment_new(Cursegp, dimension, -amount);
  242.                 return 1;
  243.         }
  244.  
  245.         med_create_new_segment(scalevec);
  246.  
  247.         //      For all segments to which Cursegp is connected, propagate tmap (uv coordinates) from the connected
  248.         //      segment back to Cursegp.  This will meaningfully propagate uv coordinates to all sides which havve
  249.         //      an incident edge.  It will also do some sides more than once.  And it is probably just not what you want.
  250.         std::array<int, MAX_SIDES_PER_SEGMENT> propagated = {};
  251.         for (int i=0; i<MAX_SIDES_PER_SEGMENT; i++)
  252.         {
  253.                 const auto c = Cursegp->children[i];
  254.                 if (IS_CHILD(c))
  255.                 {
  256.                         range_for (auto &s, propagated)
  257.                                 ++s;
  258.                         propagated[static_cast<int>(Side_opposite[i])]--;
  259.                         med_propagate_tmaps_to_segments(vmsegptridx(c), Cursegp, 1);
  260.                 }
  261.         }
  262.  
  263.         //      Now, for all sides that were not adjacent to another side, and therefore did not get tmaps
  264.         //      propagated to them, treat as a back side.
  265.         for (int i=0; i<MAX_SIDES_PER_SEGMENT; i++)
  266.                 if (!propagated[i]) {
  267.                         med_propagate_tmaps_to_back_side(Cursegp, i, 1);
  268.                 }
  269.  
  270.         //      New stuff, assign default texture to all affected sides.
  271.  
  272.         Update_flags |= UF_WORLD_CHANGED;
  273.         mine_changed = 1;
  274.         return 1;
  275. }
  276.  
  277. // -----------------------------------------------------------------------------
  278. // ---------- segment size control ----------
  279.  
  280. int IncreaseSegLength()
  281. {
  282.         return segsize_common(ZDIM,+F1_0);
  283. }
  284.  
  285. int DecreaseSegLength()
  286. {
  287.         return segsize_common(ZDIM,-F1_0);
  288. }
  289.  
  290. int DecreaseSegWidth()
  291. {
  292.         return segsize_common(XDIM,-F1_0);
  293. }
  294.  
  295. int IncreaseSegWidth()
  296. {
  297.         return segsize_common(XDIM,+F1_0);
  298. }
  299.  
  300. int IncreaseSegHeight()
  301. {
  302.         return segsize_common(YDIM,+F1_0);
  303. }
  304.  
  305. int DecreaseSegHeight()
  306. {
  307.         return segsize_common(YDIM,-F1_0);
  308. }
  309.  
  310.  
  311. int IncreaseSegLengthBig()
  312. {
  313.         return segsize_common(ZDIM,+5 * F1_0);
  314. }
  315.  
  316. int DecreaseSegLengthBig()
  317. {
  318.         return segsize_common(ZDIM,-5 * F1_0);
  319. }
  320.  
  321. int DecreaseSegWidthBig()
  322. {
  323.         return segsize_common(XDIM,-5 * F1_0);
  324. }
  325.  
  326. int IncreaseSegWidthBig()
  327. {
  328.         return segsize_common(XDIM,+5 * F1_0);
  329. }
  330.  
  331. int IncreaseSegHeightBig()
  332. {
  333.         return segsize_common(YDIM,+5 * F1_0);
  334. }
  335.  
  336. int DecreaseSegHeightBig()
  337. {
  338.         return segsize_common(YDIM,-5 * F1_0);
  339. }
  340.  
  341.  
  342. int IncreaseSegLengthDefault()
  343. {
  344.         return segsize_common(ZDIM,+40 *F1_0);
  345. }
  346.  
  347. int DecreaseSegLengthDefault()
  348. {
  349.         return segsize_common(ZDIM,-40*F1_0);
  350. }
  351.  
  352. int IncreaseSegWidthDefault()
  353. {
  354.         return segsize_common(XDIM,+40*F1_0);
  355. }
  356.  
  357. int DecreaseSegWidthDefault()
  358. {
  359.         return segsize_common(XDIM,-40*F1_0);
  360. }
  361.  
  362. int IncreaseSegHeightDefault()
  363. {
  364.         return segsize_common(YDIM,+40 * F1_0);
  365. }
  366.  
  367. int DecreaseSegHeightDefault()
  368. {
  369.         return segsize_common(YDIM,-40 * F1_0);
  370. }
  371.  
  372.  
  373. //      ---------------------------------------------------------------------------
  374. int ToggleSegSizeMode(void)
  375. {
  376.         SegSizeMode++;
  377.         if (SegSizeMode > SEGSIZEMODE_MAX)
  378.                 SegSizeMode = SEGSIZEMODE_MIN;
  379.  
  380.         return 1;
  381. }
  382.  
  383. //      ---------------------------------------------------------------------------
  384. static int      PerturbCursideCommon(fix amount)
  385. {
  386.         auto &LevelSharedVertexState = LevelSharedSegmentState.get_vertex_state();
  387.         auto &Vertices = LevelSharedVertexState.get_vertices();
  388.         int                     saveSegSizeMode = SegSizeMode;
  389.         vms_vector      fvec, rvec, uvec;
  390.         fix                     fmag, rmag, umag;
  391.         SegSizeMode = SEGSIZEMODE_CURSIDE;
  392.  
  393.         Modified_vertex_index = 0;
  394.  
  395.         auto &vcvertptr = Vertices.vcptr;
  396.         extract_forward_vector_from_segment(vcvertptr, Cursegp, fvec);
  397.         extract_right_vector_from_segment(vcvertptr, Cursegp, rvec);
  398.         extract_up_vector_from_segment(vcvertptr, Cursegp, uvec);
  399.  
  400.         fmag = vm_vec_mag(fvec);
  401.         rmag = vm_vec_mag(rvec);
  402.         umag = vm_vec_mag(uvec);
  403.  
  404.         range_for (const auto v, Side_to_verts[Curside])
  405.         {
  406.                 vms_vector perturb_vec;
  407.                 perturb_vec.x = fixmul(rmag, d_rand()*2 - 32767);
  408.                 perturb_vec.y = fixmul(umag, d_rand()*2 - 32767);
  409.                 perturb_vec.z = fixmul(fmag, d_rand()*2 - 32767);
  410.                 scale_vert(Cursegp, Cursegp->verts[v], perturb_vec, amount);
  411.         }
  412.  
  413. //      validate_segment(Cursegp);
  414. //      if (SegSizeMode) {
  415. //              for (i=0; i<MAX_SIDES_PER_SEGMENT; i++)
  416. //                      if (Cursegp->children[i] != -1)
  417. //                              validate_segment(&Segments[Cursegp->children[i]]);
  418. //      }
  419.  
  420.         validate_modified_segments();
  421.         SegSizeMode = saveSegSizeMode;
  422.  
  423.         Update_flags |= UF_WORLD_CHANGED;
  424.         mine_changed = 1;
  425.  
  426.         return 1;
  427. }
  428.  
  429. //      ---------------------------------------------------------------------------
  430. int     PerturbCurside(void)
  431. {
  432.         PerturbCursideCommon(F1_0/10);
  433.  
  434.         return 1;
  435. }
  436.  
  437. //      ---------------------------------------------------------------------------
  438. int     PerturbCursideBig(void)
  439. {
  440.         PerturbCursideCommon(F1_0/2);
  441.  
  442.         return 1;
  443. }
  444.  
  445. }
  446.