Arma Reforger Explorer  1.1.0.42
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
SCR_TerrainHelper.c
Go to the documentation of this file.
2 {
3  protected static const float MAX_TRACE_LENGTH = 100; //--- How far to search for geometry below given position
4 
5  //------------------------------------------------------------------------------------------------
14  static float GetTerrainY(vector pos, BaseWorld world = null, bool noUnderwater = false, TraceParam trace = null)
15  {
16  if (!world)
17  world = GetGame().GetWorld();
18  if (!world)
19  return 0;
20 
21  float surfaceY;
22  if (trace)
23  {
24  trace.Start = pos;
25  trace.End = Vector(pos[0], pos[1] - MAX_TRACE_LENGTH, pos[2]);
26 
27  if (trace.Flags == 0)
28  trace.Flags = TraceFlags.WORLD | TraceFlags.ENTS;
29 
30  float traceCoef = world.TraceMove(trace, null);
31  if (traceCoef < 1)
32  surfaceY = trace.Start[1] - (trace.Start[1] - trace.End[1]) * traceCoef;
33  }
34 
35  if (surfaceY == 0)
36  surfaceY = world.GetSurfaceY(pos[0], pos[2]);
37 
38  if (noUnderwater)
39  surfaceY = Math.Max(surfaceY, 0);
40 
41  return surfaceY;
42  }
43 
44  //------------------------------------------------------------------------------------------------
53  static float GetHeightAboveTerrain(vector pos, BaseWorld world = null, bool noUnderwater = false, TraceParam trace = null)
54  {
55  return pos[1] - GetTerrainY(pos, world, noUnderwater, trace);
56  }
57 
58  //------------------------------------------------------------------------------------------------
67  static vector GetTerrainNormal(inout vector pos, BaseWorld world = null, bool noUnderwater = false, TraceParam trace = null)
68  {
69  //--- Get world
70  if (!world)
71  world = GetGame().GetWorld();
72 
73  if (!world)
74  return vector.Zero;
75 
76  //--- Trace defined, use it to calculate intersection
77  if (trace)
78  {
79  //--- Make sure that trace does not start underground
80  pos[1] = Math.Max(pos[1], world.GetSurfaceY(pos[0], pos[2]) + 0.01);
81 
82  trace.Start = pos;
83  trace.End = Vector(pos[0], pos[1] - MAX_TRACE_LENGTH, pos[2]);
84 
85  if (trace.Flags == 0)
86  trace.Flags = TraceFlags.WORLD | TraceFlags.ENTS;
87 
88  float traceCoef = world.TraceMove(trace, null);
89  if (traceCoef < 1)
90  {
91  pos[1] = trace.Start[1] - (trace.Start[1] - trace.End[1]) * traceCoef;
92  if (noUnderwater && pos[1] < world.GetOceanBaseHeight())
93  {
94  //--- Underwater, use ocean surface normal (always up)
95  pos[1] = Math.Max(pos[1], world.GetOceanBaseHeight());
96  return vector.Up;
97  }
98  return trace.TraceNorm;
99  }
100  return vector.Up; //--- Default is up, not zero, as that could break calculations like vector.Dot
101  }
102 
103  //--- Simplified calculation without custom trace
104  float surfaceY = world.GetSurfaceY(pos[0], pos[2]);
105  if (noUnderwater && surfaceY < world.GetOceanBaseHeight())
106  {
107  pos[1] = Math.Max(surfaceY, world.GetOceanBaseHeight());
108  return vector.Up;
109  }
110 
111  //--- Get surface normal
112  pos[1] = surfaceY;
113  TraceParam traceRef = new TraceParam();
114  traceRef.Start = pos + vector.Up;
115  traceRef.End = pos - vector.Up;
116  traceRef.Flags = TraceFlags.WORLD;
117  world.TraceMove(traceRef, null);
118 
119  return traceRef.TraceNorm;
120  }
121 
122  //------------------------------------------------------------------------------------------------
132  static bool GetTerrainBasis(vector pos, out vector result[4], BaseWorld world = null, bool noUnderwater = false, TraceParam trace = null)
133  {
134  vector normal = GetTerrainNormal(pos, world, noUnderwater, trace);
135  if (normal == vector.Zero)
136  return false;
137 
138  //--- Get basis matrix
139  vector perpend = normal.Perpend();
140  Math3D.DirectionAndUpMatrix(perpend, normal, result);
141 
142  //--- Rotate the matrix to always point North
143  vector basis[4];
144  Math3D.AnglesToMatrix(Vector(-perpend.VectorToAngles()[0], 0, 0), basis);
145  Math3D.MatrixMultiply3(result, basis, result);
146 
147  //--- Set terrain position
148  result[3] = pos;
149 
150  return true;
151  }
152 
153  //------------------------------------------------------------------------------------------------
162  static bool SnapToTerrain(out vector transform[4], BaseWorld world = null, bool noUnderwater = false, TraceParam trace = null)
163  {
164  //--- Get world
165  if (!world)
166  world = GetGame().GetWorld();
167 
168  if (!world)
169  return false;
170 
171  //--- Get surface basis
172  vector surfaceBasis[4];
173  if (!GetTerrainBasis(transform[3], surfaceBasis, world, noUnderwater, trace))
174  return false;
175 
176  //--- Set position to surface
177  transform[3] = surfaceBasis[3];
178  return true;
179  }
180 
181  //------------------------------------------------------------------------------------------------
190  static bool OrientToTerrain(out vector transform[4], BaseWorld world = null, bool noUnderwater = false, TraceParam trace = null)
191  {
192  //--- Get world
193  if (!world)
194  world = GetGame().GetWorld();
195 
196  if (!world)
197  return false;
198 
199  //--- Get surface basis
200  vector surfaceBasis[4];
201  if (!GetTerrainBasis(transform[3], surfaceBasis, world, noUnderwater, trace))
202  return false;
203 
204  //--- Reset pitch and roll, but preserve yaw
205  //vector angles = Math3D.MatrixToAngles(transform);
206  //Math3D.AnglesToMatrix(Vector(angles[0], 0, 0), transform);
207 
208  //--- Combine surface and entity transformations
209  Math3D.MatrixMultiply3(surfaceBasis, transform, transform);
210 
211  return true;
212  }
213 
214  //------------------------------------------------------------------------------------------------
223  static bool SnapAndOrientToTerrain(out vector transform[4], BaseWorld world = null, bool noUnderwater = false, TraceParam trace = null)
224  {
225  //--- Get world
226  if (!world)
227  world = GetGame().GetWorld();
228 
229  if (!world)
230  return false;
231 
232  //--- Get surface basis
233  vector surfaceBasis[4];
234  if (!GetTerrainBasis(transform[3], surfaceBasis, world, noUnderwater, trace))
235  return false;
236 
237  //--- Set position to surface
238  transform[3] = surfaceBasis[3];
239 
240  //--- Reset pitch and roll, but preserve yaw
241  //vector angles = Math3D.MatrixToAngles(transform);
242  //Math3D.AnglesToMatrix(Vector(angles[0], 0, 0), transform);
243 
244  //--- Combine surface and entity transformations
245  Math3D.MatrixMultiply3(surfaceBasis, transform, transform);
246 
247  return true;
248  }
249 };
SCR_TerrainHelper
Definition: SCR_TerrainHelper.c:1
GetGame
ArmaReforgerScripted GetGame()
Definition: game.c:1424