Nilorea Library
C utilities for networking, threading, graphics
Loading...
Searching...
No Matches
n_dead_reckoning.h
Go to the documentation of this file.
1/*
2 * Nilorea Library
3 * Copyright (C) 2005-2026 Castagnier Mickael
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
14 * implied. See the License for the specific language governing
15 * permissions and limitations under the License.
16 *
17 * SPDX-License-Identifier: Apache-2.0
18 */
19
82#ifndef N_DEAD_RECKONING_H
83#define N_DEAD_RECKONING_H
84
85#ifdef __cplusplus
86extern "C" {
87#endif
88
94#include <stdbool.h>
95#include <math.h>
96
97/* 3D Vector type for dead reckoning */
98
100typedef struct DR_VEC3 {
101 double x;
102 double y;
103 double z;
104} DR_VEC3;
105
106/* Enumerations */
107
116
125
126/* Kinematic state snapshot */
127
135
136/* Dead reckoning entity */
137
142typedef struct DR_ENTITY {
143 /* Configuration */
147 double blend_time;
149 /* Last known authoritative state (received from network) */
152 /* State at the moment we received the last update */
155 /* Convergence tracking */
156 double blend_start;
157 bool blending;
159 /* Cubic Bezier control points (computed on update) */
165 /* Output */
169 /* Statistics */
171} DR_ENTITY;
172
173/* Vector operations (inline helpers) */
174
176static inline DR_VEC3 dr_vec3(double x, double y, double z) {
177 DR_VEC3 v = {x, y, z};
178 return v;
179}
180
182static inline DR_VEC3 dr_vec3_zero(void) {
183 DR_VEC3 v = {0.0, 0.0, 0.0};
184 return v;
185}
186
188static inline DR_VEC3 dr_vec3_add(DR_VEC3 a, DR_VEC3 b) {
189 DR_VEC3 v = {a.x + b.x, a.y + b.y, a.z + b.z};
190 return v;
191}
192
194static inline DR_VEC3 dr_vec3_sub(DR_VEC3 a, DR_VEC3 b) {
195 DR_VEC3 v = {a.x - b.x, a.y - b.y, a.z - b.z};
196 return v;
197}
198
200static inline DR_VEC3 dr_vec3_scale(DR_VEC3 v, double s) {
201 DR_VEC3 r = {v.x * s, v.y * s, v.z * s};
202 return r;
203}
204
206static inline DR_VEC3 dr_vec3_lerp(DR_VEC3 a, DR_VEC3 b, double t) {
207 DR_VEC3 r = {
208 a.x + (b.x - a.x) * t,
209 a.y + (b.y - a.y) * t,
210 a.z + (b.z - a.z) * t};
211 return r;
212}
213
215static inline double dr_vec3_length_sq(DR_VEC3 v) {
216 return v.x * v.x + v.y * v.y + v.z * v.z;
217}
218
220static inline double dr_vec3_length(DR_VEC3 v) {
221 return sqrt(dr_vec3_length_sq(v));
222}
223
225static inline double dr_vec3_distance(DR_VEC3 a, DR_VEC3 b) {
226 return dr_vec3_length(dr_vec3_sub(a, b));
227}
228
229/* API Functions */
230
232DR_ENTITY* dr_entity_create(DR_ALGO algo, DR_BLEND blend_mode, double pos_threshold, double blend_time);
234void dr_entity_destroy(DR_ENTITY** entity_ptr);
237 const DR_VEC3* pos,
238 const DR_VEC3* vel,
239 const DR_VEC3* acc,
240 double time);
242void dr_entity_compute(DR_ENTITY* entity, double time, DR_VEC3* out_pos);
244DR_VEC3 dr_entity_extrapolate(const DR_ENTITY* entity, const DR_STATE* state, double dt);
246bool dr_entity_check_threshold(const DR_ENTITY* entity,
247 const DR_VEC3* true_pos,
248 const DR_VEC3* true_vel,
249 const DR_VEC3* true_acc,
250 double time);
252void dr_entity_set_algo(DR_ENTITY* entity, DR_ALGO algo);
254void dr_entity_set_blend_mode(DR_ENTITY* entity, DR_BLEND blend_mode);
256void dr_entity_set_threshold(DR_ENTITY* entity, double threshold);
258void dr_entity_set_blend_time(DR_ENTITY* entity, double blend_time);
261 const DR_VEC3* pos,
262 const DR_VEC3* vel,
263 const DR_VEC3* acc,
264 double time);
265
270#ifdef __cplusplus
271}
272#endif
273
274#endif /* N_DEAD_RECKONING_H */
DR_VEC3 pos
Position.
double blend_start
Timestamp when blending started.
double x
X component.
DR_VEC3 bezier_p2
Control point 2.
DR_VEC3 bezier_p3
End point (extrapolated last_known at blend_time)
double y
Y component.
DR_ALGO algo
Extrapolation algorithm.
DR_VEC3 bezier_p1
Control point 1.
double blend_time
Duration of convergence blend in seconds.
double z
Z component.
DR_STATE prev_predicted
Where we THOUGHT entity was when update arrived (P0, V0)
DR_VEC3 vel
Velocity.
DR_VEC3 acc
Acceleration.
double time
Timestamp (seconds) when this state was captured.
bool blending
True if currently blending toward last_known.
DR_VEC3 display_vel
Current blended/rendered velocity.
DR_VEC3 bezier_p0
Start point (previous predicted position)
DR_STATE last_known
Most recent authoritative state (P0', V0', A0')
DR_BLEND blend_mode
Convergence blending mode.
double pos_threshold
Position error threshold for sending updates (distance)
DR_VEC3 display_pos
Current blended/rendered position.
int update_count
Number of state updates received.
static DR_VEC3 dr_vec3_scale(DR_VEC3 v, double s)
Scalar multiplication: v * s.
void dr_entity_destroy(DR_ENTITY **entity_ptr)
destroy a dead reckoning entity and free its memory
static DR_VEC3 dr_vec3_lerp(DR_VEC3 a, DR_VEC3 b, double t)
Linear interpolation: a + (b - a) * t.
static DR_VEC3 dr_vec3(double x, double y, double z)
Create a DR_VEC3 from components.
void dr_entity_set_threshold(DR_ENTITY *entity, double threshold)
set the position error threshold
void dr_entity_compute(DR_ENTITY *entity, double time, DR_VEC3 *out_pos)
compute the dead reckoned display position at a given time
DR_ENTITY * dr_entity_create(DR_ALGO algo, DR_BLEND blend_mode, double pos_threshold, double blend_time)
create a new dead reckoning entity
void dr_entity_set_blend_time(DR_ENTITY *entity, double blend_time)
set the convergence blend duration
DR_BLEND
Dead reckoning convergence/blending mode.
void dr_entity_set_blend_mode(DR_ENTITY *entity, DR_BLEND blend_mode)
set the convergence blending mode
static DR_VEC3 dr_vec3_sub(DR_VEC3 a, DR_VEC3 b)
Vector subtraction: a - b.
bool dr_entity_check_threshold(const DR_ENTITY *entity, const DR_VEC3 *true_pos, const DR_VEC3 *true_vel, const DR_VEC3 *true_acc, double time)
check if the owner's true state has diverged beyond the threshold
DR_ALGO
Dead reckoning extrapolation algorithm.
void dr_entity_set_algo(DR_ENTITY *entity, DR_ALGO algo)
set the extrapolation algorithm
static double dr_vec3_length_sq(DR_VEC3 v)
Squared length of vector.
static DR_VEC3 dr_vec3_zero(void)
Zero vector.
static DR_VEC3 dr_vec3_add(DR_VEC3 a, DR_VEC3 b)
Vector addition: a + b.
static double dr_vec3_distance(DR_VEC3 a, DR_VEC3 b)
Distance between two points.
static double dr_vec3_length(DR_VEC3 v)
Length of vector.
void dr_entity_receive_state(DR_ENTITY *entity, const DR_VEC3 *pos, const DR_VEC3 *vel, const DR_VEC3 *acc, double time)
receive a new authoritative state update from the network
void dr_entity_set_position(DR_ENTITY *entity, const DR_VEC3 *pos, const DR_VEC3 *vel, const DR_VEC3 *acc, double time)
force-set entity position without blending
DR_VEC3 dr_entity_extrapolate(const DR_ENTITY *entity, const DR_STATE *state, double dt)
extrapolate a kinematic state forward by dt seconds
@ DR_BLEND_CUBIC
Cubic Bezier spline convergence.
@ DR_BLEND_PVB
Projective Velocity Blending (recommended)
@ DR_BLEND_SNAP
Snap instantly to new state (no smoothing)
@ DR_ALGO_VEL_ACC
Velocity + acceleration: P(t) = P0 + V0*t + 0.5*A0*t^2.
@ DR_ALGO_VEL
Velocity only: P(t) = P0 + V0*t.
@ DR_ALGO_STATIC
No extrapolation; entity stays at last position.
Dead reckoned entity with extrapolation and convergence state.
A snapshot of entity kinematic state at a point in time.
3D vector used for position, velocity, and acceleration