1- import { ArrayType , IndexingType } from "../../math/types" ;
1+ import { identity , rotate , translate } from "../../math/transformations" ;
2+ import { ArrayType , IndexingType , mat4 , vec3 , vec4 } from "../../math/types" ;
3+ import { transform_vertex_mutate } from "../clip_space/vertex" ;
24import { Geometry } from "../types/geometry" ;
35
46export function create_sphere ( radius : number , rings : number , slices : number ) :Geometry {
@@ -41,4 +43,198 @@ export function create_sphere(radius: number, rings: number, slices: number):Geo
4143 }
4244 }
4345 return new Geometry ( vertices , indices ) ;
46+ }
47+
48+
49+ export function create_flat_ngon ( n :number , side_length :number , axis :vec3 | null = null , angle :number | null = null , translate_vec :vec3 | null = null ) : Geometry {
50+ if ( n <= 2 ) {
51+ console . warn ( "Invalid n - There are no polygons of dimension 2 or less." ) ;
52+ throw new Error ( "Cannot create a polygon with less than 3 sides." ) ;
53+ }
54+
55+ const vertice_count = n + 1 ;
56+ const triangle_count = n * 3 ;
57+
58+ const vertices = new ArrayType ( vertice_count * 3 ) ;
59+ const indices = new IndexingType ( triangle_count ) ;
60+
61+ vertices [ 0 ] = 0 ;
62+ vertices [ 1 ] = 0 ;
63+ vertices [ 2 ] = 0 ;
64+
65+ const radius = side_length / ( 2 * Math . sin ( Math . PI / n ) ) ;
66+ const theta_step = ( Math . PI * 2 ) / n
67+
68+ let vert_i = 3 ;
69+
70+ for ( let i = 0 ; i < n ; ++ i ) {
71+ const theta = theta_step * i ;
72+ vertices [ vert_i ++ ] = Math . cos ( theta ) * radius ;
73+ vertices [ vert_i ++ ] = Math . sin ( theta ) * radius ;
74+ vertices [ vert_i ++ ] = 0 ;
75+ }
76+
77+ let ind_i = 0 ;
78+
79+ for ( let i = 1 ; i <= n ; ++ i ) {
80+ indices [ ind_i ++ ] = 0 ;
81+ indices [ ind_i ++ ] = i ;
82+ indices [ ind_i ++ ] = ( i === n ) ? 1 : i + 1 ;
83+ }
84+ let transform :mat4 = identity ( ) ;
85+
86+ if ( angle && axis )
87+ transform = rotate ( transform , angle , axis ) ;
88+ if ( translate_vec )
89+ transform = translate ( transform , translate_vec ) ;
90+
91+ let vert = vec3 ( 0 , 0 , 0 ) ;
92+ let out = vec4 ( 0 , 0 , 0 , 0 ) ;
93+ for ( let i = 0 ; i < vertices . length ; i += 3 ) {
94+ vert [ 0 ] = vertices [ i ] ; vert [ 1 ] = vertices [ i + 1 ] ; vert [ 2 ] = vertices [ i + 2 ] ;
95+ transform_vertex_mutate ( transform , vert , out ) ;
96+ vertices [ i ] = out [ 0 ] ; vertices [ i + 1 ] = out [ 1 ] ; vertices [ i + 2 ] = out [ 2 ] ;
97+ }
98+ return new Geometry ( vertices , indices ) ;
99+ }
100+
101+ export function create_3d_ngon (
102+ n : number ,
103+ side_length : number ,
104+ depth_length : number | null ,
105+ axis : vec3 | null = null ,
106+ angle : number | null = null ,
107+ translate_vec : vec3 | null = null
108+ ) : Geometry {
109+ if ( n <= 2 ) {
110+ console . warn ( "Invalid n - There are no polygons of dimension 2 or less." ) ;
111+ throw new Error ( "Cannot create a polygon with less than 3 sides." ) ;
112+ }
113+ let depth = side_length ;
114+ if ( depth_length )
115+ depth = depth_length ;
116+
117+ const vertice_count = 2 + ( 2 * n ) ;
118+
119+ const triangle_count = n * 4 ;
120+
121+ const vertices = new ArrayType ( vertice_count * 3 ) ;
122+ const indices = new IndexingType ( triangle_count * 3 ) ;
123+
124+ const radius = side_length / ( 2 * Math . sin ( Math . PI / n ) ) ;
125+ const theta_step = ( Math . PI * 2 ) / n ;
126+
127+ vertices [ 0 ] = 0 ; vertices [ 1 ] = 0 ; vertices [ 2 ] = - depth / 2 ;
128+ vertices [ 3 ] = 0 ; vertices [ 4 ] = 0 ; vertices [ 5 ] = depth / 2 ;
129+
130+ let vert_i = 6 ;
131+
132+ for ( let i = 0 ; i < n ; i ++ ) {
133+ const theta = theta_step * i ;
134+ vertices [ vert_i ++ ] = Math . cos ( theta ) * radius ;
135+ vertices [ vert_i ++ ] = Math . sin ( theta ) * radius ;
136+ vertices [ vert_i ++ ] = - depth / 2 ;
137+ }
138+
139+ for ( let i = 0 ; i < n ; i ++ ) {
140+ const theta = theta_step * i ;
141+ vertices [ vert_i ++ ] = Math . cos ( theta ) * radius ;
142+ vertices [ vert_i ++ ] = Math . sin ( theta ) * radius ;
143+ vertices [ vert_i ++ ] = depth / 2 ;
144+ }
145+
146+ let ind_i = 0 ;
147+
148+ for ( let i = 0 ; i < n ; i ++ ) {
149+ const bottom_current = 2 + i ;
150+ const bottom_next = 2 + ( ( i + 1 ) % n ) ;
151+ const top_current = 2 + n + i ;
152+ const top_next = 2 + n + ( ( i + 1 ) % n ) ;
153+
154+ indices [ ind_i ++ ] = 0 ;
155+ indices [ ind_i ++ ] = bottom_next ;
156+ indices [ ind_i ++ ] = bottom_current ;
157+
158+ indices [ ind_i ++ ] = 1 ;
159+ indices [ ind_i ++ ] = top_current ;
160+ indices [ ind_i ++ ] = top_next ;
161+
162+ indices [ ind_i ++ ] = bottom_current ;
163+ indices [ ind_i ++ ] = bottom_next ;
164+ indices [ ind_i ++ ] = top_current ;
165+
166+ indices [ ind_i ++ ] = bottom_next ;
167+ indices [ ind_i ++ ] = top_next ;
168+ indices [ ind_i ++ ] = top_current ;
169+ }
170+
171+ let transform : mat4 = identity ( ) ;
172+
173+ if ( angle && axis ) transform = rotate ( transform , angle , axis ) ;
174+ if ( translate_vec ) transform = translate ( transform , translate_vec ) ;
175+
176+ let vert = vec3 ( 0 , 0 , 0 ) ;
177+ let out = vec4 ( 0 , 0 , 0 , 0 ) ;
178+ for ( let i = 0 ; i < vertices . length ; i += 3 ) {
179+ vert [ 0 ] = vertices [ i ] ; vert [ 1 ] = vertices [ i + 1 ] ; vert [ 2 ] = vertices [ i + 2 ] ;
180+ transform_vertex_mutate ( transform , vert , out ) ;
181+ vertices [ i ] = out [ 0 ] ; vertices [ i + 1 ] = out [ 1 ] ; vertices [ i + 2 ] = out [ 2 ] ;
182+ }
183+
184+ return new Geometry ( vertices , indices ) ;
185+ }
186+
187+
188+
189+ export function create_torus (
190+ inner_radius : number ,
191+ outer_radius : number ,
192+ rings : number ,
193+ slices : number ,
194+ ) : Geometry {
195+ const vertice_count = ( rings + 1 ) * ( slices + 1 ) * 3 ;
196+ const vertices = new ArrayType ( vertice_count ) ;
197+
198+ const indices = new IndexingType ( rings * slices * 6 ) ;
199+
200+ let vert_i = 0 ;
201+ let ind_i = 0 ;
202+
203+ for ( let ring = 0 ; ring <= rings ; ring ++ ) {
204+ const phi = ( ring * 2 * Math . PI ) / rings ;
205+ const sinPhi = Math . sin ( phi ) ;
206+ const cosPhi = Math . cos ( phi ) ;
207+
208+ for ( let slice = 0 ; slice <= slices ; slice ++ ) {
209+ const theta = ( slice * 2 * Math . PI ) / slices ;
210+ const sinTheta = Math . sin ( theta ) ;
211+ const cosTheta = Math . cos ( theta ) ;
212+
213+ const x = ( outer_radius + inner_radius * cosPhi ) * cosTheta ;
214+ const y = inner_radius * sinPhi ;
215+ const z = ( outer_radius + inner_radius * cosPhi ) * sinTheta ;
216+
217+ vertices [ vert_i ++ ] = x ;
218+ vertices [ vert_i ++ ] = y ;
219+ vertices [ vert_i ++ ] = z ;
220+ }
221+ }
222+
223+ for ( let ring = 0 ; ring < rings ; ring ++ ) {
224+ for ( let slice = 0 ; slice < slices ; slice ++ ) {
225+ const first = ( ring * ( slices + 1 ) ) + slice ;
226+ const second = first + slices + 1 ;
227+
228+ indices [ ind_i ++ ] = first ;
229+ indices [ ind_i ++ ] = second ;
230+ indices [ ind_i ++ ] = first + 1 ;
231+
232+ indices [ ind_i ++ ] = second ;
233+ indices [ ind_i ++ ] = second + 1 ;
234+ indices [ ind_i ++ ] = first + 1 ;
235+ }
236+ }
237+
238+
239+ return new Geometry ( vertices , indices ) ;
44240}
0 commit comments