Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
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 //------------------------------------------------------------------------------------------------
12 static float GetTerrainY(vector pos, BaseWorld world = null, bool noUnderwater = false, TraceParam trace = null)
13 {
14 if (!world)
15 {
16 world = GetGame().GetWorld();
17 if (!world)
18 return 0;
19 }
20
21 float surfaceY;
22 if (trace)
23 {
24 trace.Start = pos;
25 trace.End = { 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 && surfaceY < 0)
39 surfaceY = 0;
40
41 return surfaceY;
42 }
43
44 //------------------------------------------------------------------------------------------------
51 static float GetHeightAboveTerrain(vector pos, BaseWorld world = null, bool noUnderwater = false, TraceParam trace = null)
52 {
53 // world is checked in GetTerrainY
54
55 return pos[1] - GetTerrainY(pos, world, noUnderwater, trace);
56 }
57
58 //------------------------------------------------------------------------------------------------
65 static vector GetTerrainNormal(inout vector pos, BaseWorld world = null, bool noUnderwater = false, TraceParam trace = null)
66 {
67 //--- Get world
68 if (!world)
69 {
70 world = GetGame().GetWorld();
71 if (!world)
72 return vector.Zero;
73 }
74
75 //--- Trace defined, use it to calculate intersection
76 if (trace)
77 {
78 //--- Make sure that trace does not start underground
79 pos[1] = Math.Max(pos[1], world.GetSurfaceY(pos[0], pos[2]) + 0.01);
80
81 trace.Start = pos;
82 trace.End = { pos[0], pos[1] - MAX_TRACE_LENGTH, pos[2] };
83
84 if (trace.Flags == 0)
85 trace.Flags = TraceFlags.WORLD | TraceFlags.ENTS;
86
87 float traceCoef = world.TraceMove(trace, null);
88 if (traceCoef < 1)
89 {
90 pos[1] = trace.Start[1] - (trace.Start[1] - trace.End[1]) * traceCoef;
91 if (noUnderwater && pos[1] < world.GetOceanBaseHeight())
92 {
93 //--- Underwater, use ocean surface normal (always up)
94 pos[1] = Math.Max(pos[1], world.GetOceanBaseHeight());
95 return vector.Up;
96 }
97 return trace.TraceNorm;
98 }
99 return vector.Up; //--- Default is up, not zero, as that could break calculations like vector.Dot
100 }
101
102 //--- Simplified calculation without custom trace
103 float surfaceY = world.GetSurfaceY(pos[0], pos[2]);
104 if (noUnderwater && surfaceY < world.GetOceanBaseHeight())
105 {
106 pos[1] = Math.Max(surfaceY, world.GetOceanBaseHeight());
107 return vector.Up;
108 }
109
110 //--- Get surface normal
111 pos[1] = surfaceY;
112 TraceParam traceRef = new TraceParam();
113 traceRef.Start = pos + vector.Up;
114 traceRef.End = pos - vector.Up;
115 traceRef.Flags = TraceFlags.WORLD;
116 world.TraceMove(traceRef, null);
117
118 return traceRef.TraceNorm;
119 }
120
121 //------------------------------------------------------------------------------------------------
129 static bool GetTerrainBasis(vector pos, out vector result[4], BaseWorld world = null, bool noUnderwater = false, TraceParam trace = null)
130 {
131 // world is checked in GetTerrainNormal
132
133 vector normal = GetTerrainNormal(pos, world, noUnderwater, trace);
134 if (normal == vector.Zero)
135 return false;
136
137 //--- Get basis matrix
138 vector perpend = normal.Perpend();
139 Math3D.DirectionAndUpMatrix(perpend, normal, result);
140
141 //--- Rotate the matrix to always point North
142 vector basis[4];
143 Math3D.AnglesToMatrix({ -perpend.VectorToAngles()[0], 0, 0 }, basis);
144 Math3D.MatrixMultiply3(result, basis, result);
145
146 //--- Set terrain position
147 result[3] = pos;
148
149 return true;
150 }
151
152 //------------------------------------------------------------------------------------------------
160 static void SnapToGeometry(out vector newPosition, vector currentPosition, array<IEntity> excludedEntities, BaseWorld world = null, TraceParam traceParam = null, out vector surfaceNormal = vector.Zero)
161 {
162 //--- Get world
163 if (!world)
164 {
165 world = GetGame().GetWorld();
166 if (!world)
167 return;
168 }
169
170 TraceParam trace = new TraceParam();
171 //If traceParam is provided, we use that instead
172 if (!traceParam)
173 {
174 trace.Start = currentPosition;
175
176 currentPosition[1] = world.GetSurfaceY(currentPosition[0], currentPosition[2]);
177 currentPosition[1] = SCR_TerrainHelper.GetTerrainY(currentPosition, world, true);
178 trace.End = currentPosition;
179
180 trace.ExcludeArray = excludedEntities;
181 trace.TargetLayers = EPhysicsLayerDefs.FireGeometry;
182 trace.Flags = TraceFlags.ENTS | TraceFlags.WORLD;
183 }
184 else
185 {
186 trace = traceParam;
187 }
188
189 float traceDistPercentage = world.TraceMove(trace, null);
190
191 //If geometry was found along the way, new Y position is set
192 if (traceDistPercentage > 0)
193 currentPosition[1] = trace.Start[1] + (trace.End[1] - trace.Start[1]) * traceDistPercentage;
194
195 newPosition = currentPosition;
196 surfaceNormal = trace.TraceNorm;
197 }
198
199 //------------------------------------------------------------------------------------------------
206 static bool SnapToTerrain(out vector transform[4], BaseWorld world = null, bool noUnderwater = false, TraceParam trace = null)
207 {
208 // world is checked in GetTerrainBasis > GetTerrainNormal
209
210 //--- Get surface basis
211 vector surfaceBasis[4];
212 if (!GetTerrainBasis(transform[3], surfaceBasis, world, noUnderwater, trace))
213 return false;
214
215 //--- Set position to surface
216 transform[3] = surfaceBasis[3];
217 return true;
218 }
219
220 //------------------------------------------------------------------------------------------------
227 static bool OrientToTerrain(out vector transform[4], BaseWorld world = null, bool noUnderwater = false, TraceParam trace = null)
228 {
229 // world is checked in GetTerrainBasis > GetTerrainNormal
230
231 //--- Get surface basis
232 vector surfaceBasis[4];
233 if (!GetTerrainBasis(transform[3], surfaceBasis, world, noUnderwater, trace))
234 return false;
235
236 //--- Reset pitch and roll, but preserve yaw
237 //vector angles = Math3D.MatrixToAngles(transform);
238 //Math3D.AnglesToMatrix({ angles[0], 0, 0 }, transform);
239
240 //--- Combine surface and entity transformations
241 Math3D.MatrixMultiply3(surfaceBasis, transform, transform);
242
243 return true;
244 }
245
246 //------------------------------------------------------------------------------------------------
253 static bool SnapAndOrientToTerrain(out vector transform[4], BaseWorld world = null, bool noUnderwater = false, TraceParam trace = null)
254 {
255 // world is checked in GetTerrainBasis > GetTerrainNormal
256
257 //--- Get surface basis
258 vector surfaceBasis[4];
259 if (!GetTerrainBasis(transform[3], surfaceBasis, world, noUnderwater, trace))
260 return false;
261
262 //--- Set position to surface
263 transform[3] = surfaceBasis[3];
264
265 //--- Reset pitch and roll, but preserve yaw
266 //vector angles = Math3D.MatrixToAngles(transform);
267 //Math3D.AnglesToMatrix({ angles[0], 0, 0 }, transform);
268
269 //--- Combine surface and entity transformations
270 Math3D.MatrixMultiply3(surfaceBasis, transform, transform);
271
272 return true;
273 }
274}
ArmaReforgerScripted GetGame()
Definition game.c:1398
Definition Math.c:13
static const float MAX_TRACE_LENGTH
static float GetHeightAboveTerrain(vector pos, BaseWorld world=null, bool noUnderwater=false, TraceParam trace=null)
static bool SnapToTerrain(out vector transform[4], BaseWorld world=null, bool noUnderwater=false, TraceParam trace=null)
static bool GetTerrainBasis(vector pos, out vector result[4], BaseWorld world=null, bool noUnderwater=false, TraceParam trace=null)
static float GetTerrainY(vector pos, BaseWorld world=null, bool noUnderwater=false, TraceParam trace=null)
static bool OrientToTerrain(out vector transform[4], BaseWorld world=null, bool noUnderwater=false, TraceParam trace=null)
static vector GetTerrainNormal(inout vector pos, BaseWorld world=null, bool noUnderwater=false, TraceParam trace=null)
static void SnapToGeometry(out vector newPosition, vector currentPosition, array< IEntity > excludedEntities, BaseWorld world=null, TraceParam traceParam=null, out vector surfaceNormal=vector.Zero)
static bool SnapAndOrientToTerrain(out vector transform[4], BaseWorld world=null, bool noUnderwater=false, TraceParam trace=null)
TraceFlags
Definition TraceFlags.c:13