1+ namespace HexaEngine . Mathematics
2+ {
3+ using System . Numerics ;
4+ using System . Runtime . InteropServices ;
5+
6+ /// <summary>
7+ /// Represents a structure for computing a Bezier table.
8+ /// </summary>
9+ public unsafe struct BezierTable
10+ {
11+ private readonly int steps ;
12+ private float * c ;
13+ private float * k ;
14+
15+ /// <summary>
16+ /// Initializes a new instance of the <see cref="BezierTable"/> struct with the specified number of steps.
17+ /// </summary>
18+ /// <param name="steps">The number of steps for the Bezier table.</param>
19+ public BezierTable ( int steps )
20+ {
21+ c = ( float * ) Marshal . AllocHGlobal ( ( steps + 1 ) * 4 * sizeof ( float ) ) ;
22+ this . steps = steps ;
23+ }
24+
25+ /// <summary>
26+ /// Gets the Bezier control points array.
27+ /// </summary>
28+ public readonly float * C => C ;
29+
30+ /// <summary>
31+ /// Gets the number of steps in the Bezier table.
32+ /// </summary>
33+ public readonly int Steps => steps ;
34+
35+ /// <summary>
36+ /// Computes the Bezier curve given the control points.
37+ /// </summary>
38+ /// <param name="p">An array of four control points for the Bezier curve.</param>
39+ /// <param name="results">An array to store the computed points on the Bezier curve.</param>
40+ /// <remarks>
41+ /// The <paramref name="p"/> array must be 4 elements long, and the <paramref name="results"/>
42+ /// array must be equal to <see cref="Steps"/> + 1 in length.
43+ /// </remarks>
44+ public void Compute ( Vector2 * p /* must be 4 long */ , Vector2 * results /* must be equals to Steps + 1 long */ )
45+ {
46+ if ( k == null )
47+ {
48+ k = c ;
49+ for ( uint step = 0 ; step <= steps ; ++ step )
50+ {
51+ float t = ( float ) step / steps ;
52+ c [ step * 4 + 0 ] = ( 1 - t ) * ( 1 - t ) * ( 1 - t ) ; // * P0
53+ c [ step * 4 + 1 ] = 3 * ( 1 - t ) * ( 1 - t ) * t ; // * P1
54+ c [ step * 4 + 2 ] = 3 * ( 1 - t ) * t * t ; // * P2
55+ c [ step * 4 + 3 ] = t * t * t ; // * P3
56+ }
57+ }
58+
59+ for ( uint step = 0 ; step <= steps ; ++ step )
60+ {
61+ Vector2 point = new (
62+ k [ step * 4 + 0 ] * p [ 0 ] . X + k [ step * 4 + 1 ] * p [ 1 ] . X + k [ step * 4 + 2 ] * p [ 2 ] . X + k [ step * 4 + 3 ] * p [ 3 ] . X ,
63+ k [ step * 4 + 0 ] * p [ 0 ] . Y + k [ step * 4 + 1 ] * p [ 1 ] . Y + k [ step * 4 + 2 ] * p [ 2 ] . Y + k [ step * 4 + 3 ] * p [ 3 ] . Y ) ;
64+ results [ step ] = point ;
65+ }
66+ }
67+
68+ /// <summary>
69+ /// Computes points on the Bezier curve using the provided <paramref name="curve"/> and stores the results in the specified <paramref name="results"/>.
70+ /// </summary>
71+ /// <param name="curve">The Bezier curve with four control points.</param>
72+ /// <param name="results">The array to store the computed points. Must be equal to <see cref="Steps"/> + 1 in length.</param>
73+ public void Compute ( BezierCurve curve , Vector2 * results /* must be equals to Steps + 1 long */ )
74+ {
75+ if ( k == null )
76+ {
77+ k = c ;
78+ for ( uint step = 0 ; step <= steps ; ++ step )
79+ {
80+ float t = ( float ) step / steps ;
81+ c [ step * 4 + 0 ] = ( 1 - t ) * ( 1 - t ) * ( 1 - t ) ; // * P0
82+ c [ step * 4 + 1 ] = 3 * ( 1 - t ) * ( 1 - t ) * t ; // * P1
83+ c [ step * 4 + 2 ] = 3 * ( 1 - t ) * t * t ; // * P2
84+ c [ step * 4 + 3 ] = t * t * t ; // * P3
85+ }
86+ }
87+
88+ Vector2 * Q = stackalloc Vector2 [ ] { new Vector2 ( 0 , 0 ) , curve [ 0 ] , curve [ 1 ] , new Vector2 ( 1 , 1 ) } ;
89+
90+ for ( uint step = 0 ; step <= steps ; ++ step )
91+ {
92+ Vector2 point = new (
93+ k [ step * 4 + 0 ] * Q [ 0 ] . X + k [ step * 4 + 1 ] * Q [ 1 ] . X + k [ step * 4 + 2 ] * Q [ 2 ] . X + k [ step * 4 + 3 ] * Q [ 3 ] . X ,
94+ k [ step * 4 + 0 ] * Q [ 0 ] . Y + k [ step * 4 + 1 ] * Q [ 1 ] . Y + k [ step * 4 + 2 ] * Q [ 2 ] . Y + k [ step * 4 + 3 ] * Q [ 3 ] . Y ) ;
95+ results [ step ] = point ;
96+ }
97+ }
98+
99+ /// <summary>
100+ /// Computes a single point on the Bezier curve given a parameter <paramref name="t"/>.
101+ /// </summary>
102+ /// <param name="p">Array of control points. It must be 4 long.</param>
103+ /// <param name="t">Parameter value typically ranging from 0 to 1.</param>
104+ /// <returns>The computed point on the Bezier curve.</returns>
105+ public readonly Vector2 ComputePoint ( Vector2 * p , float t )
106+ {
107+ float u = 1 - t ;
108+ float tt = t * t ;
109+ float uu = u * u ;
110+ float uuu = uu * u ;
111+ float ttt = tt * t ;
112+
113+ float p0 = uuu ;
114+ float p1 = 3 * uu * t ;
115+ float p2 = 3 * u * tt ;
116+ float p3 = ttt ;
117+
118+ Vector2 point = new (
119+ p0 * p [ 0 ] . X + p1 * p [ 1 ] . X + p2 * p [ 2 ] . X + p3 * p [ 3 ] . X ,
120+ p0 * p [ 0 ] . Y + p1 * p [ 1 ] . Y + p2 * p [ 2 ] . Y + p3 * p [ 3 ] . Y ) ;
121+
122+ return point ;
123+ }
124+
125+ /// <summary>
126+ /// Releases the resources associated with the Bezier table.
127+ /// </summary>
128+ public void Release ( )
129+ {
130+ Marshal . FreeHGlobal ( ( nint ) c ) ;
131+ c = null ;
132+ k = null ;
133+ }
134+ }
135+ }
0 commit comments