Coverage Report

Created: 2025-10-12 06:55

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gpac/include/gpac/maths.h
Line
Count
Source
1
/*
2
 *      GPAC - Multimedia Framework C SDK
3
 *
4
 *      Authors: Jean Le Feuvre
5
 *      Copyright (c) Telecom ParisTech 2000-2023
6
 *          All rights reserved
7
 *
8
 *  This file is part of GPAC / common tools sub-project
9
 *
10
 *  GPAC is free software; you can redistribute it and/or modify
11
 *  it under the terms of the GNU Lesser General Public License as published by
12
 *  the Free Software Foundation; either version 2, or (at your option)
13
 *  any later version.
14
 *
15
 *  GPAC is distributed in the hope that it will be useful,
16
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 *  GNU Lesser General Public License for more details.
19
 *
20
 *  You should have received a copy of the GNU Lesser General Public
21
 *  License along with this library; see the file COPYING.  If not, write to
22
 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23
 *
24
 */
25
26
#ifndef _GF_MATH_H_
27
#define _GF_MATH_H_
28
29
#ifdef __cplusplus
30
extern "C" {
31
#endif
32
33
/*!
34
\file <gpac/maths.h>
35
\brief Mathematics and Trigonometric.
36
 */
37
38
#include <gpac/setup.h>
39
40
#include <math.h>
41
42
43
/*!
44
\addtogroup math_grp
45
\brief Mathematics and Trigonometric
46
47
This section documents the math and trigo functions used in the GPAC framework. GPAC can be compiled with
48
 fixed-point support, representing float values on a 16.16 signed integer, which implies a developer
49
 must take care of float computations when using GPAC.\n
50
 A developer should not need to know in which mode the framework has been compiled as long as (s)he uses
51
 the math functions of GPAC which work in both float and fixed-point mode.\n
52
 Using fixed-point version is decided at compilation time and cannot be changed. The feature is signaled
53
 through the GPAC_FIXED_POINT macro: when defined, GPAC has been compiled in fixed-point mode
54
55
@{
56
 */
57
58
59
/*****************************************************************************************
60
      FIXED-POINT SUPPORT - HARDCODED FOR 16.16 representation
61
  the software rasterizer also use a 16.16 representation even in non-fixed version
62
******************************************************************************************/
63
64
#ifdef GPAC_FIXED_POINT
65
66
/*!
67
Fixed 16.16 number
68
\hideinitializer
69
 \note This documentation has been generated for a fixed-point version of the GPAC framework.
70
 */
71
typedef s32 Fixed;
72
#define FIX_ONE     0x10000L
73
#define INT2FIX(v)    ((Fixed)( ((s32) (v) ) << 16))
74
#define FLT2FIX(v)    ((Fixed) ((v) * FIX_ONE))
75
#define FIX2INT(v)    ((s32)(((v)+((FIX_ONE>>1)))>>16))
76
#define FIX2FLT(v)    ((Float)( ((Float)(v)) / ((Float) FIX_ONE)))
77
#define FIX_EPSILON   2
78
#define FIX_MAX     0x7FFFFFFF
79
#define FIX_MIN     -FIX_MAX
80
#define GF_PI2    102944
81
#define GF_PI   205887
82
#define GF_2PI    411774
83
84
/*!\return 1/a, expressed as fixed number*/
85
Fixed gf_invfix(Fixed a);
86
/*!\return a*b, expressed as fixed number*/
87
Fixed gf_mulfix(Fixed a, Fixed b);
88
/*!\return a*b/c, expressed as fixed number*/
89
Fixed gf_muldiv(Fixed a, Fixed b, Fixed c);
90
/*!\return a/b, expressed as fixed number*/
91
Fixed gf_divfix(Fixed a, Fixed b);
92
/*!\return sqrt(a), expressed as fixed number*/
93
Fixed gf_sqrt(Fixed x);
94
/*!\return ceil(a), expressed as fixed number*/
95
Fixed gf_ceil(Fixed a);
96
/*!\return floor(a), expressed as fixed number*/
97
Fixed gf_floor(Fixed a);
98
/*!\return cos(a), expressed as fixed number*/
99
Fixed gf_cos(Fixed angle);
100
/*!\return sin(a), expressed as fixed number*/
101
Fixed gf_sin(Fixed angle);
102
/*!\return tan(a), expressed as fixed number*/
103
Fixed gf_tan(Fixed angle);
104
/*!\return acos(a), expressed as fixed number*/
105
Fixed gf_acos(Fixed angle);
106
/*!\return asin(a), expressed as fixed number*/
107
Fixed gf_asin(Fixed angle);
108
/*!\return atan(y, x), expressed as fixed number*/
109
Fixed gf_atan2(Fixed y, Fixed x);
110
111
#else
112
113
114
/*!Fixed is 32bit float number
115
 \note This documentation has been generated for a float version of the GPAC framework.
116
*/
117
typedef Float Fixed;
118
399k
#define FIX_ONE     1.0f
119
6.12k
#define INT2FIX(v)    ((Float) (v))
120
744k
#define FLT2FIX(v)    ((Float) (v))
121
212
#define FIX2INT(v)    ((s32)(v))
122
127k
#define FIX2FLT(v)    ((Float) (v))
123
31.7k
#define FIX_EPSILON   GF_EPSILON_FLOAT
124
0
#define FIX_MAX     GF_MAX_FLOAT
125
0
#define FIX_MIN     -GF_MAX_FLOAT
126
0
#define GF_PI2    1.5707963267949f
127
0
#define GF_PI   3.1415926535898f
128
0
#define GF_2PI    6.2831853071796f
129
130
/*!\hideinitializer 1/_a, expressed as fixed number*/
131
0
#define gf_invfix(_a) (FIX_ONE/(_a))
132
/*!\hideinitializer _a*_b, expressed as fixed number*/
133
41.9k
#define gf_mulfix(_a, _b)   ((_a)*(_b))
134
/*!\hideinitializer _a*_b/_c, expressed as fixed number*/
135
0
#define gf_muldiv(_a, _b, _c) (((_c != 0)) ? (_a)*(_b)/(_c) : GF_MAX_FLOAT)
136
/*!\hideinitializer _a/_b, expressed as fixed number*/
137
8.11k
#define gf_divfix(_a, _b)   (((_b != 0)) ? (_a)/(_b) : GF_MAX_FLOAT)
138
/*!\hideinitializer sqrt(_a), expressed as fixed number*/
139
0
#define gf_sqrt(_a) ((Float) sqrt(_a))
140
/*!\hideinitializer ceil(_a), expressed as fixed number*/
141
588
#define gf_ceil(_a) ((Float) ceil(_a))
142
/*!\hideinitializer floor(_a), expressed as fixed number*/
143
0
#define gf_floor(_a) ((Float) floor(_a))
144
/*!\hideinitializer cos(_a), expressed as fixed number*/
145
4.05k
#define gf_cos(_a) ((Float) cos(_a))
146
/*!\hideinitializer sin(_a), expressed as fixed number*/
147
0
#define gf_sin(_a) ((Float) sin(_a))
148
/*!\hideinitializer tan(_a), expressed as fixed number*/
149
0
#define gf_tan(_a) ((Float) tan(_a))
150
/*!\hideinitializer atan2(_y,_x), expressed as fixed number*/
151
10.7k
#define gf_atan2(_y, _x) ((Float) atan2(_y, _x))
152
/*!\hideinitializer acos(_a), expressed as fixed number*/
153
0
#define gf_acos(_a) ((Float) acos(_a))
154
/*!\hideinitializer asin(_a), expressed as fixed number*/
155
0
#define gf_asin(_a) ((Float) asin(_a))
156
157
#endif
158
159
/*!\def FIX_ONE
160
 \hideinitializer
161
 Fixed unit value
162
*/
163
/*!\def INT2FIX(v)
164
 \hideinitializer
165
 Conversion from integer to fixed
166
*/
167
/*!\def FLT2FIX(v)
168
 \hideinitializer
169
 Conversion from float to fixed
170
*/
171
/*!\def FIX2INT(v)
172
 \hideinitializer
173
 Conversion from fixed to integer
174
*/
175
/*!\def FIX2FLT(v)
176
 \hideinitializer
177
 Conversion from fixed to float
178
*/
179
/*!\def FIX_EPSILON
180
 \hideinitializer
181
 Epsilon Fixed (positive value closest to 0)
182
*/
183
/*!\def FIX_MAX
184
 \hideinitializer
185
 Maximum Fixed (maximum representable fixed value)
186
*/
187
/*!\def FIX_MIN
188
 \hideinitializer
189
 Minimum Fixed (minimum representable fixed value)
190
*/
191
/*!\def GF_PI2
192
 \hideinitializer
193
 PI/2 expressed as Fixed
194
*/
195
/*!\def GF_PI
196
 \hideinitializer
197
 PI expressed as Fixed
198
*/
199
/*!\def GF_2PI
200
 \hideinitializer
201
 2*PI expressed as Fixed
202
*/
203
204
/*! compute the difference between two angles, with a result in [-PI, PI]
205
\param a first angle
206
\param b first angle
207
\return angle difference
208
*/
209
Fixed gf_angle_diff(Fixed a, Fixed b);
210
211
/*!
212
\brief Field bit-size
213
214
Gets the number of bits needed to represent the value.
215
\param MaxVal Maximum value to be represented.
216
\return number of bits required to represent the value.
217
 */
218
u32 gf_get_bit_size(u32 MaxVal);
219
220
/*!
221
\brief Get power of 2
222
223
Gets the closest power of 2 greater or equal to the value.
224
\param val value to be used.
225
\return requested power of 2.
226
 */
227
u32 gf_get_next_pow2(u32 val);
228
229
/*!
230
\addtogroup math2d_grp Math 2d
231
\ingroup math_grp
232
\brief 2D Mathematics
233
234
This section documents mathematic tools for 2D geometry and color matrices operations
235
236
@{
237
 */
238
239
/*!\brief 2D point
240
 *
241
 *The 2D point object is used in all the GPAC framework for both point and vector representation.
242
*/
243
typedef struct __vec2f
244
{
245
  Fixed x;
246
  Fixed y;
247
} GF_Point2D;
248
/*!
249
\brief get 2D vector length
250
251
Gets the length of a 2D vector
252
\param vec the target vector
253
\return length of the vector
254
 */
255
Fixed gf_v2d_len(GF_Point2D *vec);
256
/*!
257
\brief get distance between 2 points
258
259
Gets the distance between the 2 points
260
\param a first point
261
\param b second point
262
\return distance
263
 */
264
Fixed gf_v2d_distance(GF_Point2D *a, GF_Point2D *b);
265
/*!
266
\brief 2D vector from polar coordinates
267
268
Constructs a 2D vector from its polar coordinates
269
\param length the length of the vector
270
\param angle the angle of the vector in radians
271
\return the 2D vector
272
 */
273
GF_Point2D gf_v2d_from_polar(Fixed length, Fixed angle);
274
275
/*!
276
\brief rectangle 2D
277
278
The 2D rectangle used in the GPAC project.
279
 */
280
typedef struct
281
{
282
  /*!the left coordinate of the rectangle*/
283
  Fixed x;
284
  /*!the top coordinate of the rectangle, regardless of the canvas orientation. In other words, y is always the
285
  greatest coordinate value,  even if the rectangle is presented bottom-up. This insures proper rectangles testing*/
286
  Fixed y;
287
  /*!the width of the rectangle. Width must be greater than or equal to 0*/
288
  Fixed width;
289
  /*!the height of the rectangle. Height must be greater than or equal to 0*/
290
  Fixed height;
291
} GF_Rect;
292
293
/*!
294
 \brief rectangle union
295
296
Gets the union of two rectangles.
297
\param rc1 first rectangle of the union. Upon return, this rectangle will contain the result of the union
298
\param rc2 second rectangle of the union
299
*/
300
void gf_rect_union(GF_Rect *rc1, GF_Rect *rc2);
301
/*!
302
 \brief centers a rectangle
303
304
Builds a rectangle centered on the origin
305
\param w width of the rectangle
306
\param h height of the rectangle
307
\return centered rectangle object
308
*/
309
GF_Rect gf_rect_center(Fixed w, Fixed h);
310
/*!
311
 \brief rectangle overlap test
312
313
Tests if two rectangles overlap.
314
\param rc1 first rectangle to test
315
\param rc2 second rectangle to test
316
\return 1 if rectangles overlap, 0 otherwise
317
*/
318
Bool gf_rect_overlaps(GF_Rect rc1, GF_Rect rc2);
319
/*!
320
\brief rectangle identity test
321
322
Tests if two rectangles are identical.
323
\param rc1 first rectangle to test
324
\param rc2 second rectangle to test
325
\return 1 if rectangles are identical, 0 otherwise
326
*/
327
Bool gf_rect_equal(GF_Rect *rc1, GF_Rect *rc2);
328
329
/*!
330
\brief rectangle intersection
331
332
Intersects two rectangle.
333
\param rc1 rectangle to use, updated to intersection result
334
\param rc2 second rectangle to use
335
*/
336
void gf_rect_intersect(GF_Rect *rc1, GF_Rect *rc2);
337
338
/*!
339
\brief pixel-aligned rectangle
340
341
Pixel-aligned rectangle used in the GPAC framework. This is usually needed for 2D drawing algorithms.
342
 */
343
typedef struct
344
{
345
  /*!the left coordinate of the rectangle*/
346
  s32 x;
347
  /*!the top coordinate of the rectangle, regardless of the canvas orientation. In other words, y is always the
348
  greatest coordinate value, even if the rectangle is presented bottom-up. This insures proper rectangles operations*/
349
  s32 y;
350
  /*!the width of the rectangle. Width must be greater than or equal to 0*/
351
  s32 width;
352
  /*!the height of the rectangle. Height must be greater than or equal to 0*/
353
  s32 height;
354
} GF_IRect;
355
/*!
356
\brief gets the pixelized version of a rectangle
357
358
Gets the smallest pixel-aligned rectangle completely containing a rectangle
359
\param r the rectangle to transform
360
\return the pixel-aligned transformed rectangle
361
*/
362
GF_IRect gf_rect_pixelize(GF_Rect *r);
363
364
/*! add adds rc2 to rc1 - the new rc1 contains the old rc1 and rc2
365
 \param rc1 target rectangle
366
 \param rc2 rectangle to add
367
*/
368
void gf_irect_union(GF_IRect *rc1, GF_IRect *rc2);
369
370
371
372
/*!
373
\brief 2D matrix
374
375
The 2D affine matrix object usied in GPAC. The transformation of P(x,y) in P'(X, Y) is:
376
 \code
377
  X = m[0]*x + m[1]*y + m[2];
378
  Y = m[3]*x + m[4]*y + m[5];
379
 \endcode
380
*/
381
typedef struct
382
{
383
  Fixed m[6];
384
} GF_Matrix2D;
385
386
/*!\brief matrix initialization
387
\hideinitializer
388
389
Inits the matrix to the identity matrix
390
*/
391
12.1k
#define gf_mx2d_init(_obj) { memset((_obj).m, 0, sizeof(Fixed)*6); (_obj).m[0] = (_obj).m[4] = FIX_ONE; }
392
/*!\brief matrix copy
393
\hideinitializer
394
395
Copies the matrix _from to the matrix _obj
396
*/
397
0
#define gf_mx2d_copy(_obj, from) memcpy((_obj).m, (from).m, sizeof(Fixed)*6)
398
/*!\brief matrix identity testing
399
\hideinitializer
400
401
This macro evaluates to 1 if the matrix _obj is the identity matrix, 0 otherwise
402
*/
403
38.7k
#define gf_mx2d_is_identity(_obj) ((!(_obj).m[1] && !(_obj).m[2] && !(_obj).m[3] && !(_obj).m[5] && ((_obj).m[0]==FIX_ONE) && ((_obj).m[4]==FIX_ONE)) ? 1 : 0)
404
405
/*!\brief 2D matrix multiplication
406
407
Multiplies two 2D matrices from*_this
408
\param _this matrix being transformed. Once the function is called, _this contains the result matrix
409
\param from transformation matrix to add
410
*/
411
void gf_mx2d_add_matrix(GF_Matrix2D *_this, GF_Matrix2D *from);
412
413
/*!\brief 2D matrix pre-multiplication
414
415
Multiplies two 2D matrices _this*from
416
\param _this matrix being transformed. Once the function is called, _this contains the result matrix
417
\param from transformation matrix to add
418
*/
419
void gf_mx2d_pre_multiply(GF_Matrix2D *_this, GF_Matrix2D *from);
420
421
/*!\brief matrix translating
422
423
Translates a 2D matrix
424
\param _this matrix being transformed. Once the function is called, _this contains the result matrix
425
\param cx horizontal translation
426
\param cy vertical translation
427
*/
428
void gf_mx2d_add_translation(GF_Matrix2D *_this, Fixed cx, Fixed cy);
429
/*!\brief matrix rotating
430
431
Rotates a 2D matrix
432
\param _this matrix being transformed. Once the function is called, _this contains the result matrix
433
\param cx horizontal rotation center coordinate
434
\param cy vertical rotation center coordinate
435
\param angle rotation angle in radians
436
*/
437
void gf_mx2d_add_rotation(GF_Matrix2D *_this, Fixed cx, Fixed cy, Fixed angle);
438
/*!\brief matrix scaling
439
440
Scales a 2D matrix
441
\param _this matrix being transformed. Once the function is called, _this contains the result matrix
442
\param scale_x horizontal scaling factor
443
\param scale_y vertical scaling factor
444
*/
445
void gf_mx2d_add_scale(GF_Matrix2D *_this, Fixed scale_x, Fixed scale_y);
446
/*!\brief matrix uncentered scaling
447
448
Scales a 2D matrix with a non-centered scale
449
\param _this matrix being transformed. Once the function is called, _this contains the result matrix
450
\param scale_x horizontal scaling factor
451
\param scale_y vertical scaling factor
452
\param cx horizontal scaling center coordinate
453
\param cy vertical scaling center coordinate
454
\param angle scale orienttion angle in radians
455
*/
456
void gf_mx2d_add_scale_at(GF_Matrix2D *_this, Fixed scale_x, Fixed scale_y, Fixed cx, Fixed cy, Fixed angle);
457
/*!\brief matrix skewing
458
459
Skews a 2D matrix
460
\param _this matrix being transformed. Once the function is called, _this contains the result matrix
461
\param skew_x horizontal skew factor
462
\param skew_y vertical skew factor
463
*/
464
void gf_mx2d_add_skew(GF_Matrix2D *_this, Fixed skew_x, Fixed skew_y);
465
/*!\brief matrix horizontal skewing
466
467
Skews a 2D matrix horizontally by a given angle
468
\param _this matrix being transformed. Once the function is called, _this contains the result matrix
469
\param angle horizontal skew angle in radians
470
*/
471
void gf_mx2d_add_skew_x(GF_Matrix2D *_this, Fixed angle);
472
/*!\brief matrix vertical skewing
473
474
Skews a 2D matrix vertically by a given angle
475
\param _this matrix being transformed. Once the function is called, _this contains the result matrix
476
\param angle vertical skew angle in radians
477
*/
478
void gf_mx2d_add_skew_y(GF_Matrix2D *_this, Fixed angle);
479
/*!\brief matrix inversing
480
481
Inverses a 2D matrix
482
\param _this matrix being transformed. Once the function is called, _this contains the result matrix
483
*/
484
void gf_mx2d_inverse(GF_Matrix2D *_this);
485
/*!\brief matrix coordinate transformation
486
487
Applies a 2D matrix transformation to coordinates
488
\param _this transformation matrix
489
\param x pointer to horizontal coordinate. Once the function is called, x contains the transformed horizontal coordinate
490
\param y pointer to vertical coordinate. Once the function is called, y contains the transformed vertical coordinate
491
*/
492
void gf_mx2d_apply_coords(GF_Matrix2D *_this, Fixed *x, Fixed *y);
493
/*!\brief matrix point transformation
494
495
Applies a 2D matrix transformation to a 2D point
496
\param _this transformation matrix
497
\param pt pointer to 2D point. Once the function is called, pt contains the transformed point
498
*/
499
void gf_mx2d_apply_point(GF_Matrix2D *_this, GF_Point2D *pt);
500
/*!\brief matrix rectangle transformation
501
502
Applies a 2D matrix transformation to a rectangle, giving the enclosing rectangle of the transformed one
503
\param _this transformation matrix
504
\param rc pointer to rectangle. Once the function is called, rc contains the transformed rectangle
505
*/
506
void gf_mx2d_apply_rect(GF_Matrix2D *_this, GF_Rect *rc);
507
508
/*!\brief matrix decomposition
509
510
Decomposes a 2D matrix M as M=Scale x Rotation x Translation if possible
511
\param _this transformation matrix
512
\param scale resulting scale part
513
\param rotate resulting rotation part
514
\param translate resulting translation part
515
\return 0 if matrix cannot be decomposed, 1 otherwise
516
*/
517
Bool gf_mx2d_decompose(GF_Matrix2D *_this, GF_Point2D *scale, Fixed *rotate, GF_Point2D *translate);
518
519
/*! @} */
520
521
522
/*!
523
\addtogroup math3d_grp Math 3d
524
\ingroup math_grp
525
\brief 3D Mathematics
526
527
This section documents mathematic tools for 3D geometry operations
528
529
@{
530
 */
531
532
/*!\brief 3D point or vector
533
534
The 3D point object is used in all the GPAC framework for both point and vector representation.
535
*/
536
typedef struct __vec3f
537
{
538
  Fixed x;
539
  Fixed y;
540
  Fixed z;
541
} GF_Vec;
542
543
/*base vector operations are MACROs for faster access*/
544
/*!\hideinitializer macro evaluating to 1 if vectors are equal, 0 otherwise*/
545
0
#define gf_vec_equal(v1, v2) (((v1).x == (v2).x) && ((v1).y == (v2).y) && ((v1).z == (v2).z))
546
/*!\hideinitializer macro reversing a vector v = v*/
547
0
#define gf_vec_rev(v) { (v).x = -(v).x; (v).y = -(v).y; (v).z = -(v).z; }
548
/*!\hideinitializer macro performing the minus operation res = v1 - v2*/
549
0
#define gf_vec_diff(res, v1, v2) { (res).x = (v1).x - (v2).x; (res).y = (v1).y - (v2).y; (res).z = (v1).z - (v2).z; }
550
/*!\hideinitializer macro performing the add operation res = v1 + v2*/
551
0
#define gf_vec_add(res, v1, v2) { (res).x = (v1).x + (v2).x; (res).y = (v1).y + (v2).y; (res).z = (v1).z + (v2).z; }
552
553
/*!
554
\brief get 3D vector length
555
556
Gets the length of a 3D vector
557
\param v the target vector
558
\return length of the vector
559
 */
560
Fixed gf_vec_len(GF_Vec v);
561
562
/*!
563
\brief get 3D vector length
564
565
Gets the length of a 3D vector
566
\param v the target vector
567
\return length of the vector
568
 */
569
Fixed gf_vec_len_p(GF_Vec *v);
570
571
/*!
572
\brief get 3D vector square length
573
574
Gets the square length of a 3D vector
575
\param v the target vector
576
\return square length of the vector
577
 */
578
Fixed gf_vec_lensq(GF_Vec v);
579
580
/*!
581
\brief get 3D vector square length
582
583
Gets the square length of a 3D vector
584
\param v the target vector
585
\return square length of the vector
586
 */
587
Fixed gf_vec_lensq_p(GF_Vec *v);
588
/*!
589
\brief get 3D vector dot product
590
591
Gets the dot product of two vectors
592
\param v1 first vector
593
\param v2 second vector
594
\return dot product of the vectors
595
 */
596
Fixed gf_vec_dot(GF_Vec v1, GF_Vec v2);
597
/*!
598
\brief get 3D vector dot product
599
600
Gets the dot product of two vectors
601
\param v1 first vector
602
\param v2 second vector
603
\return dot product of the vectors
604
 */
605
Fixed gf_vec_dot_p(GF_Vec *v1, GF_Vec *v2);
606
/*!
607
\brief vector normalization
608
609
Normalize the vector, eg make its length equal to \ref FIX_ONE
610
\param v vector to normalize
611
 */
612
void gf_vec_norm(GF_Vec *v);
613
/*!
614
\brief vector scaling
615
616
Scales a vector by a given amount
617
\param v vector to scale
618
\param f scale factor
619
\return scaled vector
620
 */
621
GF_Vec gf_vec_scale(GF_Vec v, Fixed f);
622
/*!
623
\brief vector scaling
624
625
Scales a vector by a given amount
626
\param v vector to scale
627
\param f scale factor
628
\return scaled vector
629
 */
630
GF_Vec gf_vec_scale_p(GF_Vec *v, Fixed f);
631
/*!
632
\brief vector cross product
633
634
Gets the cross product of two vectors
635
\param v1 first vector
636
\param v2 second vector
637
\return cross-product vector
638
 */
639
GF_Vec gf_vec_cross(GF_Vec v1, GF_Vec v2);
640
/*!
641
\brief vector cross product
642
643
Gets the cross product of two vectors
644
\param v1 first vector
645
\param v2 second vector
646
\return cross-product vector
647
 */
648
GF_Vec gf_vec_cross_p(GF_Vec *v1, GF_Vec *v2);
649
650
/*!\brief 4D vector
651
652
The 4D vector object is used in all the GPAC framework for 4 dimension vectors, VRML Rotations and quaternions representation.
653
*/
654
typedef struct __vec4f
655
{
656
  Fixed x;
657
  Fixed y;
658
  Fixed z;
659
  Fixed q;
660
} GF_Vec4;
661
662
663
/*!\brief 3D matrix
664
665
The 3D matrix object used in GPAC. The matrix is oriented like OpenGL matrices (column-major ordering), with
666
 the translation part at the end of the coefficients list.
667
 \note Unless specified otherwise, the matrix object is always expected to represent an affine transformation.
668
 */
669
typedef struct __matrix
670
{
671
  Fixed m[16];
672
} GF_Matrix;
673
674
675
/*!\hideinitializer gets the len of a quaternion*/
676
0
#define gf_quat_len(v) gf_sqrt(gf_mulfix((v).q,(v).q) + gf_mulfix((v).x,(v).x) + gf_mulfix((v).y,(v).y) + gf_mulfix((v).z,(v).z))
677
/*!\hideinitializer normalizes a quaternion*/
678
0
#define gf_quat_norm(v) { \
679
0
  Fixed __mag = gf_quat_len(v);  \
680
0
  (v).x = gf_divfix((v).x, __mag); (v).y = gf_divfix((v).y, __mag); (v).z = gf_divfix((v).z, __mag); (v).q = gf_divfix((v).q, __mag); \
681
0
  }  \
682
 
683
/*!\brief quaternion to rotation
684
685
Transforms a quaternion to a Rotation, expressed as a 4 dimension vector with x,y,z for axis and q for rotation angle
686
\param quat the quaternion to transform
687
\return the rotation value
688
 */
689
GF_Vec4 gf_quat_to_rotation(GF_Vec4 *quat);
690
/*!\brief quaternion from rotation
691
692
Transforms a Rotation to a quaternion
693
\param rot the rotation to transform
694
\return the quaternion value
695
 */
696
GF_Vec4 gf_quat_from_rotation(GF_Vec4 rot);
697
/*! Inverses a quaternion
698
\param quat the quaternion to inverse
699
\return the inverted quaternion
700
*/
701
GF_Vec4 gf_quat_get_inv(GF_Vec4 *quat);
702
/*!\brief quaternion multiplication
703
704
Multiplies two quaternions
705
\param q1 the first quaternion
706
\param q2 the second quaternion
707
\return the resulting quaternion
708
 */
709
GF_Vec4 gf_quat_multiply(GF_Vec4 *q1, GF_Vec4 *q2);
710
/*!\brief quaternion vector rotating
711
712
Rotates a vector with a quaternion
713
\param quat the quaternion modelizing the rotation
714
\param vec the vector to rotate
715
\return the resulting vector
716
 */
717
GF_Vec gf_quat_rotate(GF_Vec4 *quat, GF_Vec *vec);
718
/*!\brief quaternion from axis and cos
719
720
Constructs a quaternion from an axis and a cosinus value (shortcut to \ref gf_quat_from_rotation)
721
\param axis the rotation axis
722
\param cos_a the rotation cosinus value
723
\return the resulting quaternion
724
 */
725
GF_Vec4 gf_quat_from_axis_cos(GF_Vec axis, Fixed cos_a);
726
/*!\brief quaternion interpolation
727
728
Interpolates two quaternions using spherical linear interpolation
729
\param q1 the first quaternion
730
\param q2 the second quaternion
731
\param frac the fraction of the interpolation, between 0 and \ref FIX_ONE
732
\return the interpolated quaternion
733
 */
734
GF_Vec4 gf_quat_slerp(GF_Vec4 q1, GF_Vec4 q2, Fixed frac);
735
736
/*!\brief 3D Bounding Box
737
738
The 3D Bounding Box is a 3D Axis-Aligned Bounding Box used to in various tools of the GPAC framework for bounds
739
 estimation of a 3D object. It features an axis-aligned box and a sphere bounding volume for fast intersection tests.
740
 */
741
typedef struct
742
{
743
  /*!minimum x, y, and z of the object*/
744
  GF_Vec min_edge;
745
  /*!maximum x, y, and z of the object*/
746
  GF_Vec max_edge;
747
748
  /*!center of the bounding box.\note this is computed from min_edge and max_edge*/
749
  GF_Vec center;
750
  /*!radius of the bounding sphere for this box.\note this is computed from min_edge and max_edge*/
751
  Fixed radius;
752
  /*!the bbox center and radius are valid*/
753
  Bool is_set;
754
} GF_BBox;
755
/*! updates information of the bounding box based on the edge information
756
\param b the target bounding box
757
*/
758
void gf_bbox_refresh(GF_BBox *b);
759
/*!builds a bounding box from a 2D rectangle
760
\param box the bounding box to build
761
\param rc the source rectangle
762
*/
763
void gf_bbox_from_rect(GF_BBox *box, GF_Rect *rc);
764
/*!builds a rectangle from a 3D bounding box.
765
\note The z dimension is lost and no projection is performed
766
\param rc the destination rectangle
767
\param box the source bounding box
768
*/
769
void gf_rect_from_bbox(GF_Rect *rc, GF_BBox *box);
770
/*!\brief bounding box expansion
771
772
Checks if a point is inside a bounding box and updates the bounding box to include it if not the case
773
\param box the bounding box object
774
\param pt the 3D point to check
775
*/
776
void gf_bbox_grow_point(GF_BBox *box, GF_Vec pt);
777
/*!performs the union of two bounding boxes
778
\param b1 the first bounding box
779
\param b2 the bounding box to add
780
*/
781
void gf_bbox_union(GF_BBox *b1, GF_BBox *b2);
782
/*!checks if two bounding boxes are equal or not
783
\param b1 the first bounding box
784
\param b2 the second bounding box
785
\return GF_TRUE if equal
786
*/
787
Bool gf_bbox_equal(GF_BBox *b1, GF_BBox *b2);
788
/*!checks if a point is inside a bounding box or not
789
\param box the bounding box
790
\param p the point to check
791
\return GF_TRUE if point is inside
792
*/
793
Bool gf_bbox_point_inside(GF_BBox *box, GF_Vec *p);
794
/*!\brief get box vertices
795
796
Returns the 8 bounding box vertices given the minimum and maximum edge. Vertices are ordered to respect
797
 "p-vertex indexes", (vertex from a box closest to plane) and so that n-vertex (vertex from a box farthest from plane)
798
 is 7-p_vx_idx
799
\param bmin minimum edge of the box
800
\param bmax maximum edge of the box
801
\param vecs list of 8 3D points used to store the vertices.
802
*/
803
void gf_bbox_get_vertices(GF_Vec bmin, GF_Vec bmax, GF_Vec *vecs);
804
805
806
/*!\brief matrix initialization
807
 \hideinitializer
808
809
Inits the matrix to the identity matrix
810
*/
811
0
#define gf_mx_init(_obj) { memset((_obj).m, 0, sizeof(Fixed)*16); (_obj).m[0] = (_obj).m[5] = (_obj).m[10] = (_obj).m[15] = FIX_ONE; }
812
813
/*! macro to check if a matrix is the identity matrix*/
814
0
#define gf_mx_is_identity(_obj) ((!(_obj).m[1] && !(_obj).m[2] && !(_obj).m[3] && !(_obj).m[4] && !(_obj).m[6] && !(_obj).m[7] && !(_obj).m[8] && !(_obj).m[9] && !(_obj).m[11] && !(_obj).m[12] && !(_obj).m[13] && !(_obj).m[14] && ((_obj).m[0]==FIX_ONE) && ((_obj).m[5]==FIX_ONE)&& ((_obj).m[10]==FIX_ONE)&& ((_obj).m[15]==FIX_ONE)) ? 1 : 0)
815
816
/*!\brief matrix copy
817
 \hideinitializer
818
819
 Copies the matrix _from to the matrix _obj
820
*/
821
0
#define gf_mx_copy(_obj, from) memcpy(&(_obj), &(from), sizeof(GF_Matrix));
822
/*!\brief matrix constructor from 2D
823
824
Initializes a 3D matrix from a 2D matrix.\note all z-related coefficients will be set to default.
825
\param mx the target matrix to initialize
826
\param mat2D the source 2D matrix
827
*/
828
void gf_mx_from_mx2d(GF_Matrix *mx, GF_Matrix2D *mat2D);
829
/*!\brief matrix equality testing
830
831
Tests if two matrices are equal or not.
832
\param mx1 the first matrix
833
\param mx2 the first matrix
834
\return GF_TRUE if matrices are same, GF_FALSE otherwise
835
*/
836
Bool gf_mx_equal(GF_Matrix *mx1, GF_Matrix *mx2);
837
/*!\brief matrix translation
838
839
Translates a matrix
840
\param mx the matrix being transformed. Once the function is called, contains the result matrix
841
\param tx horizontal translation
842
\param ty vertical translation
843
\param tz depth translation
844
*/
845
void gf_mx_add_translation(GF_Matrix *mx, Fixed tx, Fixed ty, Fixed tz);
846
/*!\brief matrix scaling
847
848
Scales a matrix
849
\param mx the matrix being transformed. Once the function is called, contains the result matrix
850
\param sx horizontal translation scaling
851
\param sy vertical translation scaling
852
\param sz depth translation scaling
853
*/
854
void gf_mx_add_scale(GF_Matrix *mx, Fixed sx, Fixed sy, Fixed sz);
855
/*!\brief matrix rotating
856
857
Rotates a matrix
858
\param mx the matrix being transformed. Once the function is called, contains the result matrix
859
\param angle rotation angle in radians
860
\param x horizontal coordinate of rotation axis
861
\param y vertical coordinate of rotation axis
862
\param z depth coordinate of rotation axis
863
*/
864
void gf_mx_add_rotation(GF_Matrix *mx, Fixed angle, Fixed x, Fixed y, Fixed z);
865
/*!\brief matrices multiplication
866
867
Multiplies a matrix with another one mx = mx*mul
868
\param mx the matrix being transformed. Once the function is called, contains the result matrix
869
\param mul the matrix to add
870
*/
871
void gf_mx_add_matrix(GF_Matrix *mx, GF_Matrix *mul);
872
/*!\brief 2D matrix multiplication
873
874
Adds a 2D affine matrix to a matrix
875
\param mx the matrix
876
\param mat2D the matrix to premultiply
877
 */
878
void gf_mx_add_matrix_2d(GF_Matrix *mx, GF_Matrix2D *mat2D);
879
880
/*!\brief affine matrix inversion
881
882
Inverses an affine matrix.\warning Results are undefined if the matrix is not an affine one
883
\param mx the matrix to inverse
884
 */
885
void gf_mx_inverse(GF_Matrix *mx);
886
/*!\brief transpose 4x4 matrix
887
888
Transposes a 4x4 matrix
889
\param mx the matrix to transpose
890
 */
891
void gf_mx_transpose(GF_Matrix *mx);
892
/*!\brief matrix point transformation
893
894
Applies a 3D matrix transformation to a 3D point
895
\param mx transformation matrix
896
\param pt pointer to 3D point. Once the function is called, pt contains the transformed point
897
*/
898
void gf_mx_apply_vec(GF_Matrix *mx, GF_Vec *pt);
899
/*!\brief matrix rectangle transformation
900
901
Applies a 3D matrix transformation to a rectangle, giving the enclosing rectangle of the transformed one.\note all depth information are discarded.
902
\param _this transformation matrix
903
\param rc pointer to rectangle. Once the function is called, rc contains the transformed rectangle
904
*/
905
void gf_mx_apply_rect(GF_Matrix *_this, GF_Rect *rc);
906
/*!\brief ortho matrix construction
907
908
Creates an orthogonal projection matrix. This assume the NDC Z lies in [-1,1]
909
\param mx matrix to initialize
910
\param left min horizontal coordinate of viewport
911
\param right max horizontal coordinate of viewport
912
\param bottom min vertical coordinate of viewport
913
\param top max vertical coordinate of viewport
914
\param z_near min depth coordinate of viewport
915
\param z_far max depth coordinate of viewport
916
*/
917
void gf_mx_ortho(GF_Matrix *mx, Fixed left, Fixed right, Fixed bottom, Fixed top, Fixed z_near, Fixed z_far);
918
919
/*!\brief ortho matrix with reverse Z construction
920
921
Creates an orthogonal projection matrix with reverse Z. This assume the NDC Z lies in [0,1], not [-1,1]
922
\param mx matrix to initialize
923
\param left min horizontal coordinate of viewport
924
\param right max horizontal coordinate of viewport
925
\param bottom min vertical coordinate of viewport
926
\param top max vertical coordinate of viewport
927
\param z_near min depth coordinate of viewport
928
\param z_far max depth coordinate of viewport
929
*/
930
void gf_mx_ortho_reverse_z(GF_Matrix *mx, Fixed left, Fixed right, Fixed bottom, Fixed top, Fixed z_near, Fixed z_far);
931
932
/*!\brief perspective matrix construction
933
934
Creates a perspective projection matrix. This assume the NDC Z lies in [-1,1]
935
\param mx matrix to initialize
936
\param fov camera field of view angle in radian
937
\param aspect_ratio viewport aspect ratio
938
\param z_near min depth coordinate of viewport
939
\param z_far max depth coordinate of viewport
940
*/
941
void gf_mx_perspective(GF_Matrix *mx, Fixed fov, Fixed aspect_ratio, Fixed z_near, Fixed z_far);
942
943
/*!\brief perspective matrix with reverse Z  construction
944
945
Creates a perspective projection matrix with reverse Z. This assume the NDC Z lies in [0,1]
946
\param mx matrix to initialize
947
\param fov camera field of view angle in radian
948
\param aspect_ratio viewport aspect ratio
949
\param z_near min depth coordinate of viewport
950
\param z_far max depth coordinate of viewport
951
*/
952
void gf_mx_perspective_reverse_z(GF_Matrix *mx, Fixed fov, Fixed aspect_ratio, Fixed z_near, Fixed z_far);
953
954
/*!\brief creates look matrix
955
956
Creates a transformation matrix looking at a given direction from a given point (camera matrix).
957
\param mx matrix to initialize
958
\param position position
959
\param target look direction
960
\param up_vector vector describing the up direction
961
*/
962
void gf_mx_lookat(GF_Matrix *mx, GF_Vec position, GF_Vec target, GF_Vec up_vector);
963
/*!\brief matrix box transformation
964
965
Applies a 3D matrix transformation to a bounding box, giving the enclosing box of the transformed one
966
\param mx transformation matrix
967
\param b pointer to bounding box. Once the function is called, contains the transformed bounding box
968
*/
969
void gf_mx_apply_bbox(GF_Matrix *mx, GF_BBox *b);
970
971
/*!\brief matrix box transformation
972
973
Applies a 3D matrix transformation using perspective division to a bounding box, giving the enclosing box of the transformed one
974
\param mx transformation matrix
975
\param b pointer to bounding box. Once the function is called, contains the transformed bounding box
976
*/
977
void gf_mx_apply_bbox_4x4(GF_Matrix *mx, GF_BBox *b);
978
979
/*!\brief matrix box sphere transformation
980
981
Applies a 3D matrix transformation to a bounding box, computing only the enclosing sphere of the transformed one.
982
\param mx transformation matrix
983
\param box pointer to bounding box. Once the function is called, contains the transformed bounding sphere
984
*/
985
void gf_mx_apply_bbox_sphere(GF_Matrix *mx, GF_BBox *box);
986
/*!\brief non-affine matrix multiplication
987
988
Multiplies two non-affine matrices mx = mx*mul
989
\param mat the target matrix
990
\param mul the matrix we multiply with
991
*/
992
void gf_mx_add_matrix_4x4(GF_Matrix *mat, GF_Matrix *mul);
993
/*!\brief non-affine matrix inversion
994
995
Inverses a non-affine matrices
996
\param mx the target matrix
997
\return 1 if inversion was done, 0 if inversion not possible.
998
*/
999
Bool gf_mx_inverse_4x4(GF_Matrix *mx);
1000
/*!\brief matrix 4D vector transformation
1001
1002
Applies a 3D non-affine matrix transformation to a 4 dimension vector
1003
\param mx transformation matrix
1004
\param vec pointer to the vector. Once the function is called, contains the transformed vector
1005
*/
1006
void gf_mx_apply_vec_4x4(GF_Matrix *mx, GF_Vec4 *vec);
1007
1008
/*!\brief matrix yaw pitch roll decomposition
1009
1010
Extracts yaw, pitch and roll info from a matrix
1011
\param mx the matrix to decompose
1012
\param yaw the extracted yaw angle in radians
1013
\param pitch the extracted pitch angle in radians
1014
\param roll the extracted roll angle in radians
1015
*/
1016
void gf_mx_get_yaw_pitch_roll(GF_Matrix *mx, Fixed *yaw, Fixed *pitch, Fixed *roll);
1017
1018
/*!\brief matrix decomposition
1019
1020
Decomposes a matrix into translation, scale, shear and rotate
1021
\param mx the matrix to decompose
1022
\param translate the decomposed translation part
1023
\param scale the decomposed scaling part
1024
\param rotate the decomposed rotation part, expressed as a Rotataion (axis + angle)
1025
\param shear the decomposed shear part
1026
 */
1027
void gf_mx_decompose(GF_Matrix *mx, GF_Vec *translate, GF_Vec *scale, GF_Vec4 *rotate, GF_Vec *shear);
1028
/*!\brief matrix vector rotation
1029
1030
Rotates a vector with a given matrix, ignoring any translation.
1031
\param mx transformation matrix
1032
\param pt pointer to 3D vector. Once the function is called, pt contains the transformed vector
1033
 */
1034
void gf_mx_rotate_vector(GF_Matrix *mx, GF_Vec *pt);
1035
/*!\brief matrix initialization from vectors
1036
1037
Inits a matrix to rotate the local axis in the given vectors
1038
\param mx matrix to initialize
1039
\param x_axis target normalized X axis
1040
\param y_axis target normalized Y axis
1041
\param z_axis target normalized Z axis
1042
*/
1043
void gf_mx_rotation_matrix_from_vectors(GF_Matrix *mx, GF_Vec x_axis, GF_Vec y_axis, GF_Vec z_axis);
1044
/*!\brief matrix to 2D matrix
1045
1046
Inits a 2D matrix by removing all depth info from a 3D matrix
1047
\param mx2d 2D matrix to initialize
1048
\param mx 3D matrix to use
1049
*/
1050
void gf_mx2d_from_mx(GF_Matrix2D *mx2d, GF_Matrix *mx);
1051
1052
/*!\brief Plane object*/
1053
typedef struct
1054
{
1055
  /*!normal vector to the plane*/
1056
  GF_Vec normal;
1057
  /*!distance from origin of the plane*/
1058
  Fixed d;
1059
} GF_Plane;
1060
/*!\brief matrix plane transformation
1061
1062
Transorms a plane by a given matrix
1063
\param mx the matrix to use
1064
\param plane pointer to 3D plane. Once the function is called, plane contains the transformed plane
1065
 */
1066
void gf_mx_apply_plane(GF_Matrix *mx, GF_Plane *plane);
1067
/*!\brief point to plane distance
1068
1069
Gets the distance between a point and a plne
1070
\param plane the plane to use
1071
\param p pointer to ^point to check
1072
\return the distance between the place and the point
1073
 */
1074
Fixed gf_plane_get_distance(GF_Plane *plane, GF_Vec *p);
1075
/*!\brief closest point on a line
1076
1077
Gets the closest point on a line from a given point in space
1078
\param line_pt a point of the line to test
1079
\param line_vec the normalized direction vector of the line
1080
\param pt the point to check
1081
\return the closest point on the line to the desired point
1082
 */
1083
GF_Vec gf_closest_point_to_line(GF_Vec line_pt, GF_Vec line_vec, GF_Vec pt);
1084
/*!\brief box p-vertex index
1085
1086
Gets the p-vertex index for a given plane. The p-vertex index is the index of the closest vertex of a bounding box to the plane. The vertices of a box are always
1087
 *ordered in GPAC? cf \ref gf_bbox_get_vertices
1088
\param p the plane to check
1089
\return the p-vertex index value, ranging from 0 to 7
1090
*/
1091
u32 gf_plane_get_p_vertex_idx(GF_Plane *p);
1092
/*!\brief plane line intersection
1093
1094
Checks for the intersection of a plane and a line
1095
\param plane plane to test
1096
\param linepoint a point on the line to test
1097
\param linevec normalized direction vector of the line to test
1098
\param outPoint optional pointer to retrieve the intersection point, NULL otherwise
1099
\return 1 if line and plane intersect, 0 otherwise
1100
*/
1101
Bool gf_plane_intersect_line(GF_Plane *plane, GF_Vec *linepoint, GF_Vec *linevec, GF_Vec *outPoint);
1102
1103
/*!Classification types for box/plane position used in \ref gf_bbox_plane_relation*/
1104
enum
1105
{
1106
  /*!box is in front of the plane*/
1107
  GF_BBOX_FRONT,
1108
  /*!box intersects the plane*/
1109
  GF_BBOX_INTER,
1110
  /*!box is back of the plane*/
1111
  GF_BBOX_BACK
1112
};
1113
/*!\brief box-plane relation
1114
1115
Gets the spatial relation between a box and a plane
1116
\param box the box to check
1117
\param p the plane to check
1118
\return the relation type
1119
 */
1120
u32 gf_bbox_plane_relation(GF_BBox *box, GF_Plane *p);
1121
1122
/*!\brief 3D Ray
1123
1124
The 3D ray object is used in GPAC for all collision and mouse interaction tests
1125
*/
1126
typedef struct
1127
{
1128
  /*!origin point of the ray*/
1129
  GF_Vec orig;
1130
  /*!normalized direction vector of the ray*/
1131
  GF_Vec dir;
1132
} GF_Ray;
1133
1134
/*!\brief ray constructor
1135
1136
Constructs a ray object
1137
\param start starting point of the ray
1138
\param end end point of the ray, or any point on the ray
1139
\return the ray object
1140
*/
1141
GF_Ray gf_ray(GF_Vec start, GF_Vec end);
1142
/*!\brief matrix ray transformation
1143
1144
Transforms a ray by a given transformation matrix
1145
\param mx the matrix to use
1146
\param r pointer to the ray. Once the function is called, contains the transformed ray
1147
*/
1148
void gf_mx_apply_ray(GF_Matrix *mx, GF_Ray *r);
1149
/*!\brief ray box intersection test
1150
1151
Checks if a ray intersects a box or not
1152
\param ray the ray to check
1153
\param min_edge the minimum edge of the box to check
1154
\param max_edge the maximum edge of the box to check
1155
\param out_point optional location of a 3D point to store the intersection, NULL otherwise.
1156
\return retuns 1 if the ray intersects the box, 0 otherwise
1157
*/
1158
Bool gf_ray_hit_box(GF_Ray *ray, GF_Vec min_edge, GF_Vec max_edge, GF_Vec *out_point);
1159
/*!\brief ray sphere intersection test
1160
1161
Checks if a ray intersects a box or not
1162
\param ray the ray to check
1163
\param center the center of the sphere to check. If NULL, the origin (0,0,0)is used
1164
\param radius the radius of the sphere to check
1165
\param out_point optional location of a 3D point to store the intersection, NULL otherwise
1166
\return retuns 1 if the ray intersects the sphere, 0 otherwise
1167
*/
1168
Bool gf_ray_hit_sphere(GF_Ray *ray, GF_Vec *center, Fixed radius, GF_Vec *out_point);
1169
/*!\brief ray triangle intersection test
1170
1171
Checks if a ray intersects a triangle or not
1172
\param ray the ray to check
1173
\param v0 first vertex of the triangle
1174
\param v1 second vertex of the triangle
1175
\param v2 third vertex of the triangle
1176
\param dist optional location of a fixed number to store the intersection distance from ray origin if any, NULL otherwise
1177
\return retuns 1 if the ray intersects the triangle, 0 otherwise
1178
*/
1179
Bool gf_ray_hit_triangle(GF_Ray *ray, GF_Vec *v0, GF_Vec *v1, GF_Vec *v2, Fixed *dist);
1180
1181
/*! @} */
1182
1183
/*! @} */
1184
1185
#ifdef __cplusplus
1186
}
1187
#endif
1188
1189
1190
#endif    /*_GF_MATH_H_*/
1191