hotline_rs/
primitives.rs

1use crate::prelude::*;
2use maths_rs::prelude::*;
3
4/// Generic structure for 3D lit geometry meshes
5#[derive(Clone)]
6#[repr(C)]
7pub struct Vertex3D {
8    pub position: Vec3f,
9    pub texcoord: Vec2f,
10    pub normal: Vec3f,
11    pub tangent: Vec3f,
12    pub bitangent: Vec3f,
13}
14
15/// Generic structure for simple 2D textured meshes
16#[derive(Clone)]
17#[repr(C)]
18pub struct Vertex2D {
19    pub position: Vec2f,
20    pub texcoord: Vec2f,
21}
22
23/// Inverse golden ratio
24const INV_PHI : f32 = 0.618034;
25
26/// Returns an orthonormal basis given the axis returning (right, up, at)
27fn basis_from_axis(axis: Vec3f) -> (Vec3f, Vec3f, Vec3f) {
28    // right
29    let mut right = cross(axis, Vec3f::unit_y());
30    if mag(right) < 0.1 {
31        right = cross(axis, Vec3f::unit_z());
32    }
33    if mag(right) < 0.1 {
34        right = cross(axis, Vec3f::unit_x());
35    }
36    right = normalize(right);
37    
38    // up + re-adjust right
39    let up = normalize(cross(axis, right));
40    right = normalize(cross(axis, up));
41    
42    // at
43    let at = cross(right, up);
44
45    (right, up, at)
46}
47
48/// Subdivides a single quad into 4 evenly distributed smaller quads, adjusting uv's and maintaining normals and tangents
49pub fn subdivide_quad(q0: &Vertex3D, q1: &Vertex3D, q2: &Vertex3D, q3: &Vertex3D, order: u32, max_order: u32) -> Vec<Vertex3D> {
50    if order == max_order {
51        vec![q0.clone(), q1.clone(), q2.clone(), q3.clone()]
52    }
53    else {
54        //  __      ___
55        // |  | -> |_|_|
56        // |__|    |_|_|
57        // 
58        //  q1  s1  q2w
59        //  s0  s4  s2
60        //  q0  s3  q3
61
62        let lerp_half = |a: &Vertex3D, b: &Vertex3D| -> Vertex3D {
63            Vertex3D {
64                position: a.position + (b.position - a.position) * 0.5,
65                texcoord: a.texcoord + (b.texcoord - a.texcoord) * 0.5,
66                tangent: a.tangent,
67                normal: a.normal,
68                bitangent: a.bitangent
69            }
70        };
71
72        let s0 = lerp_half(q0, q1);
73        let s1 = lerp_half(q1, q2);
74        let s2 = lerp_half(q2, q3);
75        let s3 = lerp_half(q3, q0);
76        let s4 = lerp_half(&s3, &s1);
77
78        let mut sub = subdivide_quad(q0, &s0, &s4, &s3, order + 1, max_order);
79        sub.extend(subdivide_quad(&s0, q1, &s1, &s4, order + 1, max_order));
80        sub.extend(subdivide_quad(&s4, &s1, q2, &s2, order + 1, max_order));
81        sub.extend(subdivide_quad(&s3, &s4, &s2, q3, order + 1, max_order));
82        sub
83    }
84}
85
86/// Subdivides a single triangle vertex into 4 evenly distributed smaller triangles, adjusting uv's and maintaining normals and tangents
87pub fn subdivide_triangle(t0: &Vertex3D, t1: &Vertex3D, t2: &Vertex3D, order: u32, max_order: u32) -> Vec<Vertex3D> {
88    if order == max_order {
89        vec![t0.clone(), t1.clone(), t2.clone()]
90    }
91    else {
92        //  /\      /\
93        // /__\ -> /\/\
94        // 
95        //      t1
96        //    s0  s2
97        //  t0  s1  t2
98
99        let lerp_half = |a: &Vertex3D, b: &Vertex3D| -> Vertex3D {
100            Vertex3D {
101                position: a.position + (b.position - a.position) * 0.5,
102                texcoord: a.texcoord + (b.texcoord - a.texcoord) * 0.5,
103                tangent: a.tangent,
104                normal: a.normal,
105                bitangent: a.bitangent
106            }
107        };
108
109        let s0 = lerp_half(t0, t1);
110        let s1 = lerp_half(t0, t2);
111        let s2 = lerp_half(t2, t1);
112
113        let mut sub = subdivide_triangle(t0, &s0, &s1, order + 1, max_order);
114        sub.extend(subdivide_triangle(&s0,  t1, &s2, order + 1, max_order));
115        sub.extend(subdivide_triangle(&s1, &s0, &s2, order + 1, max_order));
116        sub.extend(subdivide_triangle(&s1, &s2, t2, order + 1, max_order));
117        sub
118    }
119}
120
121/// Utility to create faceted meshes with varying index sizes depending on the index requirements
122fn create_mesh_3d<D: gfx::Device>(dev: &mut D, vertices: Vec<Vertex3D>, indices: Vec<usize>) -> pmfx::Mesh<D> {
123    let max_index = vertices.len();
124    let index_buffer = if max_index > 65535 {
125        let mut indices32 : Vec<u32> = Vec::new();
126        for i in &indices {
127            indices32.push(*i as u32);
128        }
129
130        dev.create_buffer(&gfx::BufferInfo {
131            usage: gfx::BufferUsage::INDEX,
132            cpu_access: gfx::CpuAccessFlags::NONE,
133            num_elements: indices32.len(),
134            format: gfx::Format::R32u,
135            stride: 4,
136            initial_state: gfx::ResourceState::IndexBuffer
137            },
138            Some(indices32.as_slice())
139        ).unwrap()
140    }
141    else {
142        let mut indices16 : Vec<u16> = Vec::new();
143        for i in &indices {
144            indices16.push(*i as u16);
145        }
146
147        dev.create_buffer(&gfx::BufferInfo {
148            usage: gfx::BufferUsage::INDEX,
149            cpu_access: gfx::CpuAccessFlags::NONE,
150            num_elements: indices16.len(),
151            format: gfx::Format::R16u,
152            stride: 2,
153            initial_state: gfx::ResourceState::IndexBuffer
154            },
155            Some(indices16.as_slice())
156        ).unwrap()
157    };
158
159    let (aabb_min, aabb_max) =
160        indices.iter().fold((Vec3f::max_value(), -Vec3f::max_value()), |acc, i| min_max(vertices[*i].position, acc));
161
162    pmfx::Mesh {
163        vb: dev.create_buffer(&gfx::BufferInfo {
164                usage: gfx::BufferUsage::VERTEX,
165                cpu_access: gfx::CpuAccessFlags::NONE,
166                num_elements: vertices.len(),
167                format: gfx::Format::Unknown,
168                stride: std::mem::size_of::<Vertex3D>(),
169                initial_state: gfx::ResourceState::VertexConstantBuffer
170            }, 
171            Some(vertices.as_slice())
172        ).unwrap(),
173        ib: index_buffer,
174        num_indices: indices.len() as u32,
175        aabb_min,
176        aabb_max
177    }
178}
179
180/// Utility to create a facent mesh which will have hard edged normals and automatically generate and index buffer from vertices
181fn create_faceted_mesh_3d<D: gfx::Device>(dev: &mut D, vertices: Vec<Vertex3D>) -> pmfx::Mesh<D> {
182    let mut indices = Vec::new();
183    for i in 0..vertices.len() {
184        indices.push(i);
185    }
186    create_mesh_3d(dev, vertices, indices)
187}
188
189fn create_sphere_vertices(segments: usize, hemi_start: usize, hemi_end: usize, cap: bool) -> (Vec<Vertex3D>, Vec<usize>) {
190    let vertex_segments = segments + 1;
191
192    let angle_step = f32::two_pi() / segments as f32;
193    let height_step = 2.0 / (segments - 1) as f32;
194
195    let mut vertices = Vec::new();
196    let mut indices = Vec::new();
197    let mut angle = 0.0;
198    let mut y = -1.0;
199
200    for _ in 0..vertex_segments {
201        angle = -f32::pi();
202        for i in 0..vertex_segments {
203            let x = cos(angle);
204            let z = -sin(angle);
205
206            let u = 0.5 + atan2(z, x) / f32::two_pi();
207
208            let radius = 1.0 - abs(y);
209            let xz = vec3f(x, 0.0, z) * radius;
210            let p = vec3f(xz.x, y, xz.z);
211
212            // tangent
213            angle += angle_step;
214
215            let x = cos(angle);
216            let z = -sin(angle);
217            let xz = vec3f(x, 0.0, z) * radius;
218
219            let p_next = vec3f(xz.x, y, xz.z);
220            let p_next = normalize(p_next);
221
222            let p = normalize(p);
223
224            let mut t = p_next - p;
225
226            // handle case of small p_next - p
227            if mag2(t) < 0.001 {
228                t = Vec3f::unit_x();
229            }
230
231            let bt = cross(p, t);
232
233            let v = 0.5 + asin(p.y) / f32::pi();
234
235            // clamps the UV's in the last segment to prevent interpolation artifacts            
236            let u = if i == segments { 0.0 } else { u };
237            let u = if i == 0 { 1.0 } else { u };
238
239            vertices.push(Vertex3D{
240                position: p,
241                normal: p,
242                tangent: t,
243                bitangent: bt,
244                texcoord: vec2f(1.0 - u, 1.0 - v) * 3.0
245            });
246        }
247
248        y += height_step;
249    }
250
251    //
252    // Indices
253    //
254
255    let hemi_start = if hemi_start > 0 {
256        hemi_start - 1
257    }
258    else {
259        hemi_start
260    };
261
262    let hemi_start = min(hemi_start, segments);
263    let hemi_end = max(min(hemi_end, segments-1), 1);
264
265    for r in hemi_start..hemi_end {
266        for i in 0..segments {
267            let i_next = i + 1;
268            let v_index = r * vertex_segments;
269            let v_next_index = (r + 1) * vertex_segments + i;
270            let v_next_next_index = (r + 1) * vertex_segments + i_next;
271
272            indices.extend(vec![
273                v_index + i,
274                v_next_index,
275                v_index + i_next,
276                v_next_index,
277                v_next_next_index,
278                v_index + i_next,
279            ]);
280        }
281    }
282
283    if cap {
284        // basis
285        let n = Vec3f::unit_y();
286        let t = Vec3f::unit_x();
287        let bt = Vec3f::unit_z();
288        let y = -1.0 + (hemi_end as f32 * height_step); // - height_step;
289
290        let centre_cap = vertices.len();
291        vertices.push(Vertex3D{
292            position: Vec3f::unit_y() * y,
293            normal: n,
294            tangent: t,
295            bitangent: bt,
296            texcoord: Vec2f::point_five()
297        });
298
299        let loop_start = centre_cap + 1;
300
301        for _ in 0..vertex_segments {
302            let x = cos(angle);
303            let z = -sin(angle);
304            let radius = 1.0 - abs(y);
305            let xz = vec3f(x, 0.0, z) * radius;
306            let p = vec3f(xz.x, y, xz.z);
307            let p = normalize(p);
308
309            vertices.push(Vertex3D{
310                position: p,
311                normal: n,
312                tangent: t,
313                bitangent: bt,
314                texcoord: vec2f(p.x, p.z) * 0.5 + 0.5
315            });
316
317            angle += angle_step;
318        }
319
320        // triangle per cap segmnent
321        for i in 0..segments {
322            indices.extend(vec![
323                loop_start + i,
324                centre_cap,
325                loop_start + i + 1
326            ]);
327        }
328    }
329    (vertices, indices)
330}
331
332/// Create an `segments` sided prism, if `smooth` the prism is a cylinder with smooth normals
333pub fn create_prism_vertices(segments: usize, smooth: bool, cap: bool) -> (Vec<Vertex3D>, Vec<usize>) {
334    let axis = Vec3f::unit_y();
335    let right = Vec3f::unit_x();
336    let up = cross(axis, right);
337    let right = cross(axis, up);
338
339    let mut vertices = Vec::new();
340    let mut points = Vec::new();
341    let mut bottom_points = Vec::new();
342    let mut top_points = Vec::new();
343    let mut tangents = Vec::new();
344    let mut indices = Vec::new();
345
346    // add an extra segment at the end to make uv's wrap nicely
347    let vertex_segments = segments + 1;
348
349    // rotate around up axis and extract some data we can lookup to build vb and ib
350    let mut angle = 0.0;
351    let angle_step = f32::two_pi() / segments as f32;
352    for i in 0..vertex_segments {
353        // current
354        let mut x = cos(angle);
355        let mut y = -sin(angle);
356        let v1 = right * x + up * y;
357
358        // next
359        angle += angle_step;
360        x = cos(angle);
361        y = -sin(angle);
362        let v2 = right * x + up * y;
363
364        points.push(v1);
365        tangents.push(v2 - v1);
366        bottom_points.push(points[i] - Vec3f::unit_y());
367        top_points.push(points[i] + Vec3f::unit_y());
368    }
369
370    //
371    // Vertices
372    //
373
374    // bottom ring
375    for i in 0..vertex_segments {
376        let u = 0.5 + atan2(bottom_points[i].z, bottom_points[i].x) / f32::two_pi();
377        let u = if i == segments { 0.0 } else { u };
378        let bt = cross(tangents[i], points[i]);
379        vertices.push(Vertex3D{
380            position: bottom_points[i],
381            normal: points[i],
382            tangent: tangents[i],
383            bitangent: bt,
384            texcoord: Vec2f::new(u * 3.0, 0.0)
385        });
386    }
387
388    // top ring
389    for i in 0..vertex_segments {
390        let u = 0.5 + atan2(top_points[i].z, top_points[i].x) / f32::two_pi();
391        let u = if i == segments { 0.0 } else { u };
392        let bt = cross(tangents[i], points[i]);
393        vertices.push(Vertex3D{
394            position: top_points[i],
395            normal: points[i],
396            tangent: tangents[i],
397            bitangent: bt,
398            texcoord: Vec2f::new(u * 3.0, 1.0)
399        });
400    }
401        
402    // bottom face
403    for point in bottom_points.iter().take(segments) {
404        vertices.push(Vertex3D{
405            position: *point,
406            normal: -Vec3f::unit_y(),
407            tangent: Vec3f::unit_x(),
408            bitangent: Vec3f::unit_z(),
409            texcoord: Vec2f::new(point.x, point.z) * 0.5 + 0.5
410        });
411    }
412
413    // top face
414    for point in top_points.iter().take(segments) {
415        vertices.push(Vertex3D{
416            position: *point,
417            normal: Vec3f::unit_y(),
418            tangent: Vec3f::unit_x(),
419            bitangent: Vec3f::unit_z(),
420            texcoord: Vec2f::new(point.x, point.z) * 0.5 + 0.5
421        });
422    }
423
424    // centre points
425    vertices.push(Vertex3D{
426        position: -Vec3f::unit_y(),
427        normal: -Vec3f::unit_y(),
428        tangent: Vec3f::unit_x(),
429        bitangent: Vec3f::unit_z(),
430        texcoord: Vec2f::point_five()
431    });
432    let centre_bottom = vertices.len()-1;
433
434    vertices.push(Vertex3D{
435        position: Vec3f::unit_y(),
436        normal: Vec3f::unit_y(),
437        tangent: Vec3f::unit_x(),
438        bitangent: Vec3f::unit_z(),
439        texcoord: Vec2f::point_five()
440    });
441    let centre_top = vertices.len()-1;
442
443    if smooth {
444
445        //
446        // Smooth Indices
447        //
448
449        // sides
450        for i in 0..segments {
451            let bottom = i;
452            let top = i + vertex_segments;
453            let next = i + 1;
454            let top_next = i + 1 + vertex_segments;
455            indices.extend(vec![
456                bottom,
457                top,
458                next,
459                top,
460                top_next,
461                next
462            ]);
463        }
464
465        if cap {
466            // bottom face - tri fan
467            for i in 0..segments {
468                let face_offset = vertex_segments * 2;
469                let face_current = face_offset + i;
470                let face_next = face_offset + (i + 1);
471                indices.extend(vec![
472                    centre_bottom,
473                    face_current,
474                    face_next
475                ]);
476            }
477
478            // top face - tri fan
479            for i in 0..segments {
480                let face_offset = vertex_segments * 3;
481                let face_current = face_offset + i;
482                let face_next = face_offset + (i + 1);
483                indices.extend(vec![
484                    centre_top,
485                    face_next,
486                    face_current
487                ]);
488            }
489        }
490
491        (vertices, indices)
492    }
493    else {
494        // 2 tris per segment
495        let mut triangle_vertices = Vec::new();
496        for i in 0..segments {
497            let bottom = i;
498            let top = i + vertex_segments;
499            let next = i + 1;
500            let top_next = i + 1 + vertex_segments;
501
502            let face_index = triangle_vertices.len();
503            triangle_vertices.extend(vec![
504                vertices[bottom].clone(),
505                vertices[top].clone(),
506                vertices[next].clone(),
507                vertices[top].clone(),
508                vertices[top_next].clone(),
509                vertices[next].clone()
510            ]);
511
512            let v = face_index;
513            let n = get_triangle_normal(
514                triangle_vertices[v].position, 
515                triangle_vertices[v+2].position, 
516                triangle_vertices[v+1].position
517            );
518
519            // set hard face normals
520            for vertex in triangle_vertices.iter_mut().skip(face_index) {
521                vertex.normal = n;
522            }
523        }
524
525        if cap {
526            // bottom face - tri fan
527            for i in 0..segments {
528                let face_offset = vertex_segments * 2;
529                let face_current = face_offset + i;
530                let face_next = face_offset + (i + 1);
531                triangle_vertices.extend(vec![
532                    vertices[centre_bottom].clone(),
533                    vertices[face_current].clone(),
534                    vertices[face_next].clone(),
535                ]);
536            }
537    
538            // top face - tri fan
539            for i in 0..segments {
540                let face_offset = vertex_segments * 3;
541                let face_current = face_offset + i;
542                let face_next = face_offset + (i + 1);
543                triangle_vertices.extend(vec![
544                    vertices[centre_top].clone(),
545                    vertices[face_next].clone(),
546                    vertices[face_current].clone(),
547                ]);
548            }
549        }
550
551        (vertices, Vec::new())
552    }
553}
554
555/// Create an indexed unit quad mesh instance
556pub fn create_unit_quad_mesh<D: gfx::Device>(dev: &mut D) -> pmfx::Mesh<D> {
557    // front face
558    let vertices: Vec<Vertex2D> = vec![
559        Vertex2D {
560            position: vec2f(-1.0, -1.0),
561            texcoord: vec2f(0.0, 1.0),
562        },
563        Vertex2D {
564            position: vec2f(1.0, -1.0),
565            texcoord: vec2f(1.0, 1.0),
566        },
567        Vertex2D {
568            position: vec2f(1.0, 1.0),
569            texcoord: vec2f(1.0, 0.0),
570        },
571        Vertex2D {
572            position: vec2f(-1.0, 1.0),
573            texcoord: vec2f(0.0, 0.0),
574        }
575    ];
576
577    let indices: Vec<u16> = vec![
578        0,  2,  1,  2,  0,  3
579    ];
580
581    pmfx::Mesh {
582        vb: dev.create_buffer(&gfx::BufferInfo {
583                usage: gfx::BufferUsage::VERTEX,
584                cpu_access: gfx::CpuAccessFlags::NONE,
585                num_elements: 4,
586                format: gfx::Format::Unknown,
587                stride: std::mem::size_of::<Vertex2D>(),
588                initial_state: gfx::ResourceState::VertexConstantBuffer
589            }, 
590            Some(vertices.as_slice())
591        ).unwrap(),
592        ib: dev.create_buffer(&gfx::BufferInfo {
593            usage: gfx::BufferUsage::INDEX,
594            cpu_access: gfx::CpuAccessFlags::NONE,
595            num_elements: 6,
596            format: gfx::Format::R16u,
597            stride: std::mem::size_of::<u16>(),
598            initial_state: gfx::ResourceState::IndexBuffer
599            },
600            Some(indices.as_slice())
601        ).unwrap(),
602        num_indices: 6,
603        aabb_min: vec3f(-1.0, -1.0, 0.0),
604        aabb_max: vec3f( 1.0,  1.0, 0.0)
605    } 
606}
607
608/// Create an indexed unit billboard quad mesh instance with the front face pointing +z 
609pub fn create_billboard_mesh<D: gfx::Device>(dev: &mut D) -> pmfx::Mesh<D> {
610    // quad veritces
611    let vertices: Vec<Vertex3D> = vec![
612        // front face
613        Vertex3D {
614            position: vec3f(-1.0, -1.0, 0.0),
615            texcoord: vec2f(0.0, 1.0),
616            normal: vec3f(0.0, 0.0, 1.0),
617            tangent: vec3f(1.0, 0.0, 0.0),
618            bitangent: vec3f(0.0, 1.0, 0.0),
619        },
620        Vertex3D {
621            position: vec3f(1.0, -1.0, 0.0),
622            texcoord: vec2f(1.0, 1.0),
623            normal: vec3f(0.0, 0.0, 1.0),
624            tangent: vec3f(1.0, 0.0, 0.0),
625            bitangent: vec3f(0.0, 1.0, 0.0),
626        },
627        Vertex3D {
628            position: vec3f(1.0, 1.0, 0.0),
629            texcoord: vec2f(1.0, 0.0),
630            normal: vec3f(0.0, 0.0, 1.0),
631            tangent: vec3f(1.0, 0.0, 0.0),
632            bitangent: vec3f(0.0, 1.0, 0.0),
633        },
634        Vertex3D {
635            position: vec3f(-1.0, 1.0, 0.0),
636            texcoord: vec2f(0.0, 0.0),
637            normal: vec3f(0.0, 0.0, 1.0),
638            tangent: vec3f(1.0, 0.0, 0.0),
639            bitangent: vec3f(0.0, 1.0, 0.0),
640        }
641    ];
642
643    let indices: Vec<u16> = vec![
644        0,  2,  1,  2,  0,  3,   // front face
645    ];
646
647    pmfx::Mesh {
648        vb: dev.create_buffer(&gfx::BufferInfo {
649                usage: gfx::BufferUsage::VERTEX,
650                cpu_access: gfx::CpuAccessFlags::NONE,
651                num_elements: 4,
652                format: gfx::Format::Unknown,
653                stride: std::mem::size_of::<Vertex3D>(),
654                initial_state: gfx::ResourceState::VertexConstantBuffer
655            }, 
656            Some(vertices.as_slice())
657        ).unwrap(),
658        ib: dev.create_buffer(&gfx::BufferInfo {
659                usage: gfx::BufferUsage::INDEX,
660                cpu_access: gfx::CpuAccessFlags::NONE,
661                num_elements: 6,
662                format: gfx::Format::R16u,
663                stride: std::mem::size_of::<u16>(),
664                initial_state: gfx::ResourceState::IndexBuffer
665            },
666            Some(indices.as_slice())
667        ).unwrap(),
668        num_indices: 6,
669        aabb_min: vec3f(-1.0, -1.0, 0.0),
670        aabb_max: vec3f( 1.0,  1.0, 0.0)
671    } 
672}
673
674/// Create an indexed unit triangle mesh instance with the front face pointing +z 
675pub fn create_triangle_mesh<D: gfx::Device>(dev: &mut D) -> pmfx::Mesh<D> {
676    // quad veritces
677    let vertices: Vec<Vertex3D> = vec![
678        // front face
679        Vertex3D {
680            position: vec3f(-1.0, -1.0, 0.0),
681            texcoord: vec2f(0.0, 1.0),
682            normal: vec3f(0.0, 0.0, 1.0),
683            tangent: vec3f(1.0, 0.0, 0.0),
684            bitangent: vec3f(0.0, 1.0, 0.0),
685        },
686        Vertex3D {
687            position: vec3f(1.0, -1.0, 0.0),
688            texcoord: vec2f(1.0, 1.0),
689            normal: vec3f(0.0, 0.0, 1.0),
690            tangent: vec3f(1.0, 0.0, 0.0),
691            bitangent: vec3f(0.0, 1.0, 0.0),
692        },
693        Vertex3D {
694            position: vec3f(0.0, 1.0, 0.0),
695            texcoord: vec2f(0.5, 0.0),
696            normal: vec3f(0.0, 0.0, 1.0),
697            tangent: vec3f(1.0, 0.0, 0.0),
698            bitangent: vec3f(0.0, 1.0, 0.0),
699        }
700    ];
701
702    let indices: Vec<u16> = vec![
703        0,  1,  2
704    ];
705
706    let aabb_min = vertices.iter().fold( Vec3f::max_value(), |acc, v| min(acc, v.position));
707    let aabb_max = vertices.iter().fold(-Vec3f::max_value(), |acc, v| max(acc, v.position));
708
709    pmfx::Mesh {
710        vb: dev.create_buffer(&gfx::BufferInfo {
711                usage: gfx::BufferUsage::VERTEX,
712                cpu_access: gfx::CpuAccessFlags::NONE,
713                num_elements: 3,
714                format: gfx::Format::Unknown,
715                stride: std::mem::size_of::<Vertex3D>(),
716                initial_state: gfx::ResourceState::VertexConstantBuffer
717            }, 
718            Some(vertices.as_slice())
719        ).unwrap(),
720        ib: dev.create_buffer(&gfx::BufferInfo {
721                usage: gfx::BufferUsage::INDEX,
722                cpu_access: gfx::CpuAccessFlags::NONE,
723                num_elements: 3,
724                format: gfx::Format::R16u,
725                stride: std::mem::size_of::<u16>(),
726                initial_state: gfx::ResourceState::IndexBuffer
727            },
728            Some(indices.as_slice())
729        ).unwrap(),
730        num_indices: 3,
731        aabb_min,
732        aabb_max
733    } 
734}
735
736/// Create an indexed unit subdivided plane mesh facing +y direction with evenly subdivided quads `subdivisions`
737pub fn create_plane_mesh<D: gfx::Device>(dev: &mut D, subdivisions: u32) -> pmfx::Mesh<D> {
738    let start = vec3f(-1.0, 0.0, -1.0);
739    let increment = 2.0 / subdivisions as f32;
740    
741    let mut pos = start;
742    let mut vertices = Vec::new();
743    let mut indices = Vec::new();
744
745    for _ in 0..subdivisions {
746        pos.x = start.x;
747        for _ in 0..subdivisions {
748            // quad per suub division
749            let quad_base_index = vertices.len();
750
751            vertices.extend(vec![
752                Vertex3D {
753                    position: vec3f(pos.x, 0.0, pos.z),
754                    texcoord: vec2f(0.0, 0.0),
755                    normal: Vec3f::unit_y(),
756                    tangent: vec3f(1.0, 0.0, 0.0),
757                    bitangent: vec3f(0.0, 1.0, 0.0),
758                },
759                Vertex3D {
760                    position: vec3f(pos.x + increment, 0.0, pos.z),
761                    texcoord: vec2f(1.0, 0.0),
762                    normal: Vec3f::unit_y(),
763                    tangent: vec3f(1.0, 0.0, 0.0),
764                    bitangent: vec3f(0.0, 1.0, 0.0),
765                },
766                Vertex3D {
767                    position: vec3f(pos.x + increment, 0.0, pos.z + increment),
768                    texcoord: vec2f(1.0, 1.0),
769                    normal: Vec3f::unit_y(),
770                    tangent: vec3f(1.0, 0.0, 0.0),
771                    bitangent: vec3f(0.0, 1.0, 0.0),
772                },
773                Vertex3D {
774                    position: vec3f(pos.x, 0.0, pos.z + increment),
775                    texcoord: vec2f(0.0, 1.0),
776                    normal: Vec3f::unit_y(),
777                    tangent: vec3f(1.0, 0.0, 0.0),
778                    bitangent: vec3f(0.0, 1.0, 0.0),
779                }
780            ]);
781            
782            indices.extend(vec![
783                quad_base_index,  quad_base_index + 1,  quad_base_index + 2,  
784                quad_base_index,  quad_base_index + 2,  quad_base_index + 3
785            ]);
786
787            pos.x += increment;
788        }
789        pos.z += increment;
790    }
791
792    create_mesh_3d(dev, vertices, indices)
793}
794
795/// Create a an indexed unit tetrahedron mesh instance
796pub fn create_tetrahedron_mesh<D: gfx::Device>(dev: &mut D) -> pmfx::Mesh<D> {
797    let pos = vec3f(0.0, -INV_PHI, 0.0);
798    let right = Vec3f::unit_x();
799    let up = Vec3f::unit_z();
800    let at = Vec3f::unit_y();
801    let angle_step = (f32::pi() * 2.0) / 3.0;
802    let tip = pos + at * sqrt(2.0); // sqrt 2 is pythagoras constant
803
804    // we gather the base vertices and faces as we iterate
805    let mut base_positions = Vec::new();
806    let mut vertices = Vec::new();
807
808    // pos, next pos, top pos
809    let get_face_vertices = |p: Vec3f, np: Vec3f, tp: Vec3f| -> Vec<Vertex3D> {
810        let n = maths_rs::get_triangle_normal(p, np, tp);
811        let b = normalize(p - np);
812        let t = cross(n, b);
813        vec![
814            Vertex3D {
815                position: normalize(tp),
816                texcoord: vec2f(0.5, 0.0),
817                normal: n,
818                tangent: t,
819                bitangent: b,
820            },
821            Vertex3D {
822                position: normalize(np),
823                texcoord: vec2f(1.0, 1.0),
824                normal: n,
825                tangent: t,
826                bitangent: b,
827            },
828            Vertex3D {
829                position: normalize(p),
830                texcoord: vec2f(0.0, 1.0),
831                normal: n,
832                tangent: t,
833                bitangent: b,
834            }
835        ]
836    };    
837
838    // make the sides with y-up
839    let mut a = 0.0;
840    for _ in 0..3 {
841        // current pos
842        let x = f32::sin(a);
843        let y = f32::cos(a);
844        let p = pos + right * x + up * y;
845        
846        // next pos and tip
847        a += angle_step;
848        let x2 = f32::sin(a);
849        let y2 = f32::cos(a);
850        let np = pos + right * x2 + up * y2;
851        let tp = tip;
852        
853        base_positions.push(p);
854        vertices.extend(get_face_vertices(p , np, tp));
855    }
856
857    // make the base face
858    vertices.extend(get_face_vertices(base_positions[0], base_positions[2], base_positions[1]));
859
860    // generate indices
861    create_faceted_mesh_3d(dev, vertices)
862}
863
864pub fn cube_vertices() -> Vec<Vertex3D> {
865    vec![
866        // front face
867        Vertex3D {
868            position: vec3f(-1.0, -1.0, 1.0),
869            texcoord: vec2f(0.0, 1.0),
870            normal: vec3f(0.0, 0.0, 1.0),
871            tangent: vec3f(1.0, 0.0, 0.0),
872            bitangent: vec3f(0.0, 1.0, 0.0),
873        },
874        Vertex3D {
875            position: vec3f(1.0, -1.0,  1.0),
876            texcoord: vec2f(1.0, 1.0),
877            normal: vec3f(0.0, 0.0, 1.0),
878            tangent: vec3f(1.0, 0.0, 0.0),
879            bitangent: vec3f(0.0, 1.0, 0.0),
880        },
881        Vertex3D {
882            position: vec3f(1.0, 1.0, 1.0),
883            texcoord: vec2f(1.0, 0.0),
884            normal: vec3f(0.0, 0.0, 1.0),
885            tangent: vec3f(1.0, 0.0, 0.0),
886            bitangent: vec3f(0.0, 1.0, 0.0),
887        },
888        Vertex3D {
889            position: vec3f(-1.0, 1.0, 1.0),
890            texcoord: vec2f(0.0, 0.0),
891            normal: vec3f(0.0, 0.0, 1.0),
892            tangent: vec3f(1.0, 0.0, 0.0),
893            bitangent: vec3f(0.0, 1.0, 0.0),
894        },
895        // back face
896        Vertex3D {
897            position: vec3f(-1.0, -1.0, -1.0),
898            texcoord: vec2f(1.0, 1.0),
899            normal: vec3f(0.0, 0.0, -1.0),
900            tangent: vec3f(-1.0, 0.0, 0.0),
901            bitangent: vec3f(0.0, 1.0, 0.0),
902        },
903        Vertex3D {
904            position: vec3f(-1.0, 1.0, -1.0),
905            texcoord: vec2f(1.0, 0.0),
906            normal: vec3f(0.0, 0.0, -1.0),
907            tangent: vec3f(-1.0, 0.0, 0.0),
908            bitangent: vec3f(0.0, 1.0, 0.0),
909        },
910        Vertex3D {
911            position: vec3f(1.0, 1.0, -1.0),
912            texcoord: vec2f(0.0, 0.0),
913            normal: vec3f(0.0, 0.0, -1.0),
914            tangent: vec3f(-1.0, 0.0, 0.0),
915            bitangent: vec3f(0.0, 1.0, 0.0),
916        },
917        Vertex3D {
918            position: vec3f(1.0, -1.0, -1.0),
919            texcoord: vec2f(0.0, 1.0),
920            normal: vec3f(0.0, 0.0, -1.0),
921            tangent: vec3f(-1.0, 0.0, 0.0),
922            bitangent: vec3f(0.0, 1.0, 0.0),
923        },
924        // right face
925        Vertex3D {
926            position: vec3f(1.0, -1.0, -1.0),
927            texcoord: vec2f(0.0, 1.0),
928            normal: vec3f(1.0, 0.0, 0.0),
929            tangent: vec3f(0.0, 0.0, 1.0),
930            bitangent: vec3f(0.0, 1.0, 0.0),
931        },
932        Vertex3D {
933            position: vec3f(1.0, 1.0, -1.0),
934            texcoord: vec2f(0.0, 0.0),
935            normal: vec3f(1.0, 0.0, 0.0),
936            tangent: vec3f(0.0, 0.0, 1.0),
937            bitangent: vec3f(0.0, 1.0, 0.0),
938        },
939        Vertex3D {
940            position: vec3f(1.0, 1.0, 1.0),
941            texcoord: vec2f(1.0, 0.0),
942            normal: vec3f(1.0, 0.0, 0.0),
943            tangent: vec3f(0.0, 0.0, 1.0),
944            bitangent: vec3f(0.0, 1.0, 0.0),
945        },
946        Vertex3D {
947            position: vec3f(1.0, -1.0, 1.0),
948            texcoord: vec2f(1.0, 1.0),
949            normal: vec3f(1.0, 0.0, 0.0),
950            tangent: vec3f(0.0, 0.0, 1.0),
951            bitangent: vec3f(0.0, 1.0, 0.0),
952        },
953        // left face
954        Vertex3D {
955            position: vec3f(-1.0, -1.0, -1.0),
956            texcoord: vec2f(1.0, 1.0),
957            normal: vec3f(-1.0, 0.0, 0.0),
958            tangent: vec3f(0.0, 0.0, -1.0),
959            bitangent: vec3f(0.0, 1.0, 0.0),
960        },
961        Vertex3D {
962            position: vec3f(-1.0, -1.0, 1.0),
963            texcoord: vec2f(0.0, 1.0),
964            normal: vec3f(-1.0, 0.0, 0.0),
965            tangent: vec3f(0.0, 0.0, -1.0),
966            bitangent: vec3f(0.0, 1.0, 0.0),
967        },
968        Vertex3D {
969            position: vec3f(-1.0, 1.0, 1.0),
970            texcoord: vec2f(0.0, 0.0),
971            normal: vec3f(-1.0, 0.0, 0.0),
972            tangent: vec3f(0.0, 0.0, -1.0),
973            bitangent: vec3f(0.0, 1.0, 0.0),
974        },
975        Vertex3D {
976            position: vec3f(-1.0, 1.0, -1.0),
977            texcoord: vec2f(1.0, 0.0),
978            normal: vec3f(-1.0, 0.0, 0.0),
979            tangent: vec3f(0.0, 0.0, -1.0),
980            bitangent: vec3f(0.0, 1.0, 0.0),
981        },
982        // top face
983        Vertex3D {
984            position: vec3f(-1.0, 1.0, -1.0),
985            texcoord: vec2f(0.0, 1.0),
986            normal: vec3f(0.0, 1.0, 0.0),
987            tangent: vec3f(1.0, 0.0, 0.0),
988            bitangent: vec3f(0.0, 0.0, 1.0),
989        },
990        Vertex3D {
991            position: vec3f(-1.0, 1.0, 1.0),
992            texcoord: vec2f(0.0, 0.0),
993            normal: vec3f(0.0, 1.0, 0.0),
994            tangent: vec3f(1.0, 0.0, 0.0),
995            bitangent: vec3f(0.0, 0.0, 1.0),
996        },
997        Vertex3D {
998            position: vec3f(1.0, 1.0, 1.0),
999            texcoord: vec2f(1.0, 0.0),
1000            normal: vec3f(0.0, 1.0, 0.0),
1001            tangent: vec3f(1.0, 0.0, 0.0),
1002            bitangent: vec3f(0.0, 0.0, 1.0),
1003        },
1004        Vertex3D {
1005            position: vec3f(1.0, 1.0, -1.0),
1006            texcoord: vec2f(1.0, 1.0),
1007            normal: vec3f(0.0, 1.0, 0.0),
1008            tangent: vec3f(1.0, 0.0, 0.0),
1009            bitangent: vec3f(0.0, 0.0, 1.0),
1010        },
1011        // bottom face
1012        Vertex3D {
1013            position: vec3f(-1.0, -1.0, -1.0),
1014            texcoord: vec2f(1.0, 0.0),
1015            normal: vec3f(0.0, -1.0, 0.0),
1016            tangent: vec3f(-1.0, 0.0, 0.0),
1017            bitangent: vec3f(0.0, 0.0, -1.0),
1018        },
1019        Vertex3D {
1020            position: vec3f(1.0, -1.0, -1.0),
1021            texcoord: vec2f(0.0, 0.0),
1022            normal: vec3f(0.0, -1.0, 0.0),
1023            tangent: vec3f(-1.0, 0.0, 0.0),
1024            bitangent: vec3f(0.0, 0.0, -1.0),
1025        },
1026        Vertex3D {
1027            position: vec3f(1.0, -1.0, 1.0),
1028            texcoord: vec2f(0.0, 1.0),
1029            normal: vec3f(0.0, -1.0, 0.0),
1030            tangent: vec3f(-1.0, 0.0, 0.0),
1031            bitangent: vec3f(0.0, 0.0, -1.0),
1032        },
1033        Vertex3D {
1034            position: vec3f(-1.0, -1.0, 1.0),
1035            texcoord: vec2f(1.0, 1.0),
1036            normal: vec3f(0.0, -1.0, 0.0),
1037            tangent: vec3f(-1.0, 0.0, 0.0),
1038            bitangent: vec3f(0.0, 0.0, -1.0),
1039        },
1040    ]
1041}
1042
1043/// Create an indexed unit cube mesh instance.
1044pub fn create_cube_mesh<D: gfx::Device>(dev: &mut D) -> pmfx::Mesh<D> {
1045    let indices: Vec<usize> = vec![
1046        0,  2,  1,  2,  0,  3,   // front face
1047        4,  6,  5,  6,  4,  7,   // back face
1048        8,  10, 9,  10, 8,  11,  // right face
1049        12, 14, 13, 14, 12, 15,  // left face
1050        16, 18, 17, 18, 16, 19,  // top face
1051        20, 22, 21, 22, 20, 23   // bottom face
1052    ];
1053
1054    create_mesh_3d(dev, cube_vertices(), indices)
1055}
1056
1057/// Creates a unit octahedron mesh aligned y-up
1058pub fn create_octahedron_mesh<D: gfx::Device>(dev: &mut D) -> pmfx::Mesh<D> {
1059    let corner = [
1060        vec3f(-1.0, 0.0, -1.0),
1061        vec3f(-1.0, 0.0,  1.0),
1062        vec3f( 1.0, 0.0,  1.0),
1063        vec3f( 1.0, 0.0, -1.0)
1064    ];
1065
1066    let pc = sqrt(2.0);
1067    let top = vec3f(0.0, pc, 0.0);
1068    let bottom = vec3f(0.0, -pc, 0.0);
1069
1070    // we make it in 2 halfs one points up in y, the other down
1071    let yextent = [
1072        top,
1073        bottom
1074    ];
1075
1076    let mut vertices = Vec::new();
1077
1078    for i in 0..4 {
1079        let n = (i + 1) % 4;
1080                
1081        // 2 tris per-edge 1 up, one down
1082        for (j, yextent) in yextent.iter().enumerate() {
1083            
1084            // vertices
1085            let mut t0 = corner[i];
1086            let t1 = corner[n];
1087            let mut t2 = *yextent;
1088
1089            // tex coords
1090            let mut tc0 = vec2f(1.0, 1.0);
1091            let tc1 = vec2f(0.0, 1.0);
1092            let mut tc2 = vec2f(0.5, 0.0); 
1093
1094            // flip if we are the top
1095            if j == 0 {
1096                std::mem::swap(&mut t0, &mut t2);
1097                std::mem::swap(&mut tc0, &mut tc2);
1098            }
1099
1100            // normals and tangents
1101            let n = get_triangle_normal(t0, t2, t1);
1102            let b = normalize(t0 - t1);
1103            let t = cross(n, b);
1104
1105            let tri: Vec<Vertex3D> = vec![
1106                Vertex3D {
1107                    position: t0,
1108                    texcoord: tc0,
1109                    normal: n,
1110                    tangent: t,
1111                    bitangent: b,
1112                },
1113                Vertex3D {
1114                    position: t1,
1115                    texcoord: tc1,
1116                    normal: n,
1117                    tangent: t,
1118                    bitangent: b,
1119                },
1120                Vertex3D {
1121                    position: t2,
1122                    texcoord: tc2,
1123                    normal: n,
1124                    tangent: t,
1125                    bitangent: b,
1126                }
1127            ];
1128            vertices.extend(tri);
1129        }
1130    }
1131
1132    create_faceted_mesh_3d(dev, vertices)
1133}
1134
1135/// Intenral utility which can regursively build a hemi-dodecahedrin starting with a single pentagonal face with normal `axis`
1136fn dodecahedron_face_in_axis(axis: Vec3f, pos: Vec3f, start_angle: f32, recurse: bool) -> Vec<Vertex3D> {
1137    let (right, up, _) = basis_from_axis(axis);
1138    let angle_step = f32::pi() / 2.5;
1139
1140    let mut a = start_angle;
1141    let mut vertices = Vec::new();
1142
1143    // pos is centreed inthe middle of a pentagonal face
1144    let t2 = pos;
1145
1146    // pentagon with tri per edge, makes a tri with the 2 edge vertices and 1 vertex and t2 in the centre
1147    for _ in 0..5 {
1148        let x = f32::sin(a) * INV_PHI;
1149        let y = f32::cos(a) * INV_PHI;
1150        let t0 = pos + right * x + up * y;
1151        let uv0 = Vec2f::new(f32::sin(a), f32::cos(a));
1152        
1153        a += angle_step;
1154        let x2 = f32::sin(a) * INV_PHI;
1155        let y2 = f32::cos(a) * INV_PHI;
1156        let t1 = pos + right * x2 + up * y2;
1157        let uv1 = Vec2f::new(f32::sin(a), f32::cos(a));
1158
1159        let n = get_triangle_normal(t0, t2, t1);
1160        let b = normalize(t0 - t1);
1161        let t = cross(n, b);
1162                    
1163        let tri = vec![
1164            Vertex3D {
1165                position: t0,
1166                texcoord: uv0 * 0.5 + 0.5,
1167                normal: n,
1168                tangent: t,
1169                bitangent: b,
1170            },
1171            Vertex3D {
1172                position: t1,
1173                texcoord: uv1 * 0.5 + 0.5,
1174                normal: n,
1175                tangent: t,
1176                bitangent: b,
1177            },
1178            Vertex3D {
1179                position: t2,
1180                texcoord: Vec2f::point_five(),
1181                normal: n,
1182                tangent: t,
1183                bitangent: b,
1184            }
1185        ];
1186        vertices.extend(tri);
1187
1188        if recurse {
1189            let half_gr = f32::phi() / 2.0;
1190            let internal_angle = 0.309017 * 1.5;
1191
1192            let ev = normalize(t1 - t0);
1193            let cp = normalize(cross(ev, axis));
1194            let mid = t0 + (t1 - t0) * 0.5;
1195            
1196            let rx = f32::sin((f32::pi() * 2.0) + internal_angle) * INV_PHI;
1197            let ry = f32::cos((f32::pi() * 2.0) + internal_angle) * INV_PHI;
1198            let xp = mid + cp * rx + axis * ry;
1199            let xv = normalize(xp - mid);
1200
1201            let next_axis = normalize(cross(xv, ev));
1202            let face_vertices = dodecahedron_face_in_axis(next_axis, mid + xv * half_gr * INV_PHI, f32::pi() + start_angle, false);
1203            vertices.extend(face_vertices);
1204        }
1205    }
1206    vertices
1207}
1208
1209/// Create an indexed faceted dodecahedron mesh.
1210pub fn create_dodecahedron_mesh<D: gfx::Device>(dev: &mut D) -> pmfx::Mesh<D> {
1211    let h = f32::pi() * 0.8333333 * 0.5 * INV_PHI;
1212    let mut vertices = dodecahedron_face_in_axis(Vec3f::unit_y(), vec3f(0.0, -h, 0.0), 0.0, true);
1213    let bottom_vertices = dodecahedron_face_in_axis(-Vec3f::unit_y(), vec3f(0.0, h, 0.0), f32::pi(), true);
1214    vertices.extend(bottom_vertices);
1215    create_faceted_mesh_3d(dev, vertices)
1216}
1217
1218/// Create a hemi-icosahedron in axis with subdivisions
1219pub fn hemi_icosohedron(axis: Vec3f, pos: Vec3f, start_angle: f32, subdivisions: u32) -> Vec<Vertex3D> {
1220    let (right, up, at) = basis_from_axis(axis);
1221
1222    let tip = pos - at * INV_PHI;
1223    let dip = pos + at * 0.5 * 2.0;
1224
1225    let angle_step = f32::pi() / 2.5;
1226
1227    let mut a = start_angle;
1228    let mut vertices = Vec::new();
1229
1230    for _ in 0..5 {
1231        let x = f32::sin(a);
1232        let y = f32::cos(a);
1233        let p = pos + right * x + up * y;
1234
1235        a += angle_step;
1236        let x2 = f32::sin(a);
1237        let y2 = f32::cos(a);
1238        let np = pos + right * x2 + up * y2;
1239
1240        let n = get_triangle_normal(p, np, tip);
1241        let b = normalize(p - tip);
1242        let t = cross(n, b);
1243
1244        let tri = vec![
1245            Vertex3D {
1246                position: p,
1247                texcoord: Vec2f::new(0.0, 0.0),
1248                normal: n,
1249                tangent: t,
1250                bitangent: b,
1251            },
1252            Vertex3D {
1253                position: tip,
1254                texcoord: Vec2f::new(0.5, 1.0),
1255                normal: n,
1256                tangent: t,
1257                bitangent: b,
1258            },
1259            Vertex3D {
1260                position: np,
1261                texcoord: Vec2f::new(1.0, 0.0),
1262                normal: n,
1263                tangent: t,
1264                bitangent: b,
1265            }
1266        ];
1267        vertices.extend(subdivide_triangle(&tri[0], &tri[1], &tri[2], 0, subdivisions));
1268        
1269        let side_dip = dip + cross(normalize(p-np), at);
1270        
1271        let n = get_triangle_normal(p, side_dip, np);
1272        let b = normalize(p - np);
1273        let t = cross(n, b);
1274        
1275        let tri = vec![
1276            Vertex3D {
1277                position: p,
1278                texcoord: Vec2f::new(0.0, 1.0),
1279                normal: n,
1280                tangent: t,
1281                bitangent: b,
1282            },
1283            Vertex3D {
1284                position: np,
1285                texcoord: Vec2f::new(1.0, 1.0),
1286                normal: n,
1287                tangent: t,
1288                bitangent: b,
1289            },
1290            Vertex3D {
1291                position: side_dip,
1292                texcoord: Vec2f::new(0.5, 0.0),
1293                normal: n,
1294                tangent: t,
1295                bitangent: b,
1296            }
1297        ];
1298        vertices.extend(subdivide_triangle(&tri[0], &tri[1], &tri[2], 0, subdivisions));
1299    }
1300    vertices
1301}
1302
1303/// Create an indexed faceted icosohedron mesh.
1304pub fn create_icosahedron_mesh<D: gfx::Device>(dev: &mut D) -> pmfx::Mesh<D> {
1305    // construct from 2 hemi icosahedrons one in the +y and one in -y axis
1306    let mut vertices = hemi_icosohedron(Vec3f::unit_y(), Vec3f::unit_y() * 0.5, 0.0, 0);
1307    let bottom_vertices = hemi_icosohedron(-Vec3f::unit_y(), Vec3f::unit_y() * -0.5, f32::pi(), 0);
1308    vertices.extend(bottom_vertices);
1309    create_faceted_mesh_3d(dev, vertices)
1310}
1311
1312/// Create an indexed faceted icosahedron mesh
1313pub fn create_icosasphere_mesh<D: gfx::Device>(dev: &mut D, subdivisions: u32) -> pmfx::Mesh<D> {
1314    // we start from an icosahedron with subdivided faces
1315    let mut vertices = hemi_icosohedron(Vec3f::unit_y(), Vec3f::unit_y() * 0.5, 0.0, subdivisions);
1316    let bottom_vertices = hemi_icosohedron(-Vec3f::unit_y(), Vec3f::unit_y() * -0.5, f32::pi(), subdivisions);
1317    vertices.extend(bottom_vertices);
1318
1319    // project the points outwards to make a sphere
1320    for v in &mut vertices {
1321        v.position = normalize(v.position);
1322    }
1323
1324    // keep the facet normals
1325    for i in (0..vertices.len()).step_by(3) {
1326        let n = get_triangle_normal(vertices[i].position, vertices[i + 2].position, vertices[i + 1].position);
1327        let b = normalize(vertices[i].position - vertices[i + 2].position);
1328        let t = cross(n, b);
1329        for v in vertices.iter_mut().skip(i).take(3) {
1330            v.normal = n;
1331            v.bitangent = b;
1332            v.tangent = t;
1333        }
1334    }
1335
1336    create_faceted_mesh_3d(dev, vertices)
1337}
1338
1339/// Create a custom sphere mesh with segments subdivision, hemi_segments can clip the sphere
1340/// in different heights, supply `hemi_segments=segments/2` to create a perfect hemi-sphere
1341/// use cap to cap the cliped sphere or not
1342pub fn create_sphere_mesh_truncated<D: gfx::Device>(dev: &mut D, segments: usize, hemi_segments: usize, cap: bool) -> pmfx::Mesh<D> {
1343    let (vertices, indices) = create_sphere_vertices(segments, 0, hemi_segments, cap);
1344    create_mesh_3d(dev, vertices, indices)
1345}
1346
1347/// Create an indexed smooth sphere with subdivided icosophere vertices and smooth normals
1348pub fn create_sphere_mesh<D: gfx::Device>(dev: &mut D, segments: usize) -> pmfx::Mesh<D> {
1349    create_sphere_mesh_truncated(dev, segments, segments, false)
1350}
1351
1352/// Create an `segments` sided prism, if `smooth` the prism is a cylinder with smooth normals
1353/// convert to a trapezoid using `taper` with a value between 0-1 to taper the top cap inward where 1 is no taper and 0 makes a pyramid
1354pub fn create_prism_mesh<D: gfx::Device>(dev: &mut D, segments: usize, smooth: bool, cap: bool, height: f32, taper: f32) -> pmfx::Mesh<D> {
1355    let axis = Vec3f::unit_y();
1356    let right = Vec3f::unit_x();
1357    let up = cross(axis, right);
1358    let right = cross(axis, up);
1359
1360    let mut vertices = Vec::new();
1361    let mut points = Vec::new();
1362    let mut bottom_points = Vec::new();
1363    let mut top_points = Vec::new();
1364    let mut tangents = Vec::new();
1365    let mut indices = Vec::new();
1366
1367    // add an extra segment at the end to make uv's wrap nicely
1368    let vertex_segments = segments + 1;
1369
1370    // rotate around up axis and extract some data we can lookup to build vb and ib
1371    let mut angle = 0.0;
1372    let angle_step = f32::two_pi() / segments as f32;
1373    for i in 0..vertex_segments {
1374        // current
1375        let mut x = cos(angle);
1376        let mut y = -sin(angle);
1377        let v1 = right * x + up * y;
1378
1379        // next
1380        angle += angle_step;
1381        x = cos(angle);
1382        y = -sin(angle);
1383        let v2 = right * x + up * y;
1384
1385        points.push(v1);
1386        tangents.push(v2 - v1);
1387
1388        bottom_points.push(points[i] - Vec3f::unit_y() * height);
1389        top_points.push(points[i] * taper + Vec3f::unit_y() * height);
1390    }
1391
1392    //
1393    // Vertices
1394    //
1395
1396    // bottom ring
1397    for i in 0..vertex_segments {
1398        let u = 0.5 + atan2(bottom_points[i].z, bottom_points[i].x) / f32::two_pi();
1399        let u = if i == segments { 0.0 } else { u };
1400        let bt = cross(points[i], tangents[i]);
1401        vertices.push(Vertex3D{
1402            position: bottom_points[i],
1403            normal: points[i],
1404            tangent: tangents[i],
1405            bitangent: bt,
1406            texcoord: Vec2f::new((1.0 - u) * 3.0, 1.0)
1407        });
1408    }
1409
1410    // top ring
1411    for i in 0..vertex_segments {
1412        let u = 0.5 + atan2(top_points[i].z, top_points[i].x) / f32::two_pi();
1413        let u = if i == segments { 0.0 } else { u };
1414        let bt = cross(points[i], tangents[i]);
1415        vertices.push(Vertex3D{
1416            position: top_points[i],
1417            normal: points[i],
1418            tangent: tangents[i],
1419            bitangent: bt,
1420            texcoord: Vec2f::new((1.0 - u) * 3.0, 0.0)
1421        });
1422    }
1423        
1424    // bottom face
1425    for point in bottom_points.iter().take(vertex_segments) {
1426        vertices.push(Vertex3D{
1427            position: *point,
1428            normal: -Vec3f::unit_y(),
1429            tangent: Vec3f::unit_x(),
1430            bitangent: Vec3f::unit_z(),
1431            texcoord: Vec2f::new(-point.x, -point.z) * 0.5 + 0.5
1432        });
1433    }
1434
1435    // top face
1436    for point in top_points.iter().take(vertex_segments) {
1437        vertices.push(Vertex3D{
1438            position: *point,
1439            normal: Vec3f::unit_y(),
1440            tangent: Vec3f::unit_x(),
1441            bitangent: Vec3f::unit_z(),
1442            texcoord: Vec2f::new(point.x, -point.z) * 0.5 + 0.5
1443        });
1444    }
1445
1446    // centre points
1447    vertices.push(Vertex3D{
1448        position: -Vec3f::unit_y() * height,
1449        normal: -Vec3f::unit_y(),
1450        tangent: Vec3f::unit_x(),
1451        bitangent: Vec3f::unit_z(),
1452        texcoord: Vec2f::point_five()
1453    });
1454    let centre_bottom = vertices.len()-1;
1455
1456    vertices.push(Vertex3D{
1457        position: Vec3f::unit_y() * height,
1458        normal: Vec3f::unit_y(),
1459        tangent: Vec3f::unit_x(),
1460        bitangent: Vec3f::unit_z(),
1461        texcoord: Vec2f::point_five()
1462    });
1463    let centre_top = vertices.len()-1;
1464
1465    if smooth {
1466
1467        //
1468        // Smooth Indices
1469        //
1470
1471        // sides
1472        for i in 0..segments {
1473            let bottom = i;
1474            let top = i + vertex_segments;
1475            let next = i + 1;
1476            let top_next = i + 1 + vertex_segments;
1477            indices.extend(vec![
1478                bottom,
1479                top,
1480                next,
1481                top,
1482                top_next,
1483                next
1484            ]);
1485        }
1486
1487        if cap {
1488            // bottom face - tri fan
1489            for i in 0..segments {
1490                let face_offset = vertex_segments * 2;
1491                let face_current = face_offset + i;
1492                let face_next = face_offset + (i + 1);
1493                indices.extend(vec![
1494                    centre_bottom,
1495                    face_current,
1496                    face_next
1497                ]);
1498            }
1499
1500            // top face - tri fan
1501            for i in 0..segments {
1502                let face_offset = vertex_segments * 3;
1503                let face_current = face_offset + i;
1504                let face_next = face_offset + (i + 1);
1505                indices.extend(vec![
1506                    centre_top,
1507                    face_next,
1508                    face_current
1509                ]);
1510            }
1511        }
1512
1513        create_mesh_3d(dev, vertices, indices)
1514    }
1515    else {
1516        let mut triangle_vertices = Vec::new();
1517        if taper != 1.0 {
1518            // 4-tris per segment, trapezoid
1519            for i in 0..segments {
1520                let bottom = i;
1521                let top = i + vertex_segments;
1522                let next = i + 1;
1523                let top_next = i + 1 + vertex_segments;
1524
1525                // add a mid vertex to distribute the UV's more nicely
1526                let mut mid = vertices[bottom].clone();
1527                mid.position = (
1528                    vertices[bottom].position +
1529                    vertices[top].position + 
1530                    vertices[next].position +
1531                    vertices[top_next].position
1532                 ) * 0.25;
1533
1534                mid.texcoord = splat2f(0.5);
1535
1536                let face_index = triangle_vertices.len();
1537                triangle_vertices.extend(vec![
1538                    vertices[bottom].clone(),
1539                    vertices[top].clone(),
1540                    mid.clone(),
1541
1542                    vertices[top].clone(),
1543                    vertices[top_next].clone(),
1544                    mid.clone(),
1545
1546                    vertices[bottom].clone(),
1547                    mid.clone(),
1548                    vertices[next].clone(),
1549
1550                    vertices[next].clone(),
1551                    mid,
1552                    vertices[top_next].clone(),
1553                ]);
1554
1555                let v = face_index;
1556                let n = get_triangle_normal(
1557                    triangle_vertices[v].position, 
1558                    triangle_vertices[v+2].position, 
1559                    triangle_vertices[v+1].position
1560                );
1561
1562                // set hard face normals
1563                for vertex in triangle_vertices.iter_mut().skip(face_index) {
1564                    vertex.normal = n;
1565                }
1566
1567                let top_u = 0.0;
1568                let top_next_u = 1.0;
1569
1570                triangle_vertices[face_index].texcoord.x = 0.0;
1571                triangle_vertices[face_index + 1].texcoord.x = top_u;
1572                triangle_vertices[face_index + 3].texcoord.x = top_u;
1573                triangle_vertices[face_index + 4].texcoord.x = top_next_u;
1574                triangle_vertices[face_index + 6].texcoord.x = 0.0;
1575                triangle_vertices[face_index + 8].texcoord.x = 1.0; 
1576                triangle_vertices[face_index + 9].texcoord.x = 1.0;
1577                triangle_vertices[face_index + 11].texcoord.x = top_next_u;
1578            }
1579        }
1580        else {
1581            // 2 tris per segment (prism)
1582            for i in 0..segments {
1583                let bottom = i;
1584                let top = i + vertex_segments;
1585                let next = i + 1;
1586                let top_next = i + 1 + vertex_segments;
1587
1588                let face_index = triangle_vertices.len();
1589                triangle_vertices.extend(vec![
1590                    vertices[bottom].clone(),
1591                    vertices[top].clone(),
1592                    vertices[next].clone(),
1593                    vertices[top].clone(),
1594                    vertices[top_next].clone(),
1595                    vertices[next].clone()
1596                ]);
1597
1598                let v = face_index;
1599                let n = get_triangle_normal(
1600                    triangle_vertices[v].position, 
1601                    triangle_vertices[v+2].position, 
1602                    triangle_vertices[v+1].position
1603                );
1604
1605                // set hard face normals
1606                for vertex in triangle_vertices.iter_mut().skip(face_index) {
1607                    vertex.normal = n;
1608                }
1609            }
1610        }
1611
1612        if cap {
1613            // bottom face - tri fan
1614            for i in 0..segments {
1615                let face_offset = vertex_segments * 2;
1616                let face_current = face_offset + i;
1617                let face_next = face_offset + (i + 1);
1618                triangle_vertices.extend(vec![
1619                    vertices[centre_bottom].clone(),
1620                    vertices[face_current].clone(),
1621                    vertices[face_next].clone(),
1622                ]);
1623            }
1624    
1625            // top face - tri fan
1626            for i in 0..segments {
1627                let face_offset = vertex_segments * 3;
1628                let face_current = face_offset + i;
1629                let face_next = face_offset + (i + 1);
1630                triangle_vertices.extend(vec![
1631                    vertices[centre_top].clone(),
1632                    vertices[face_next].clone(),
1633                    vertices[face_current].clone(),
1634                ]);
1635            }
1636        }
1637
1638        create_faceted_mesh_3d(dev, triangle_vertices)
1639    }
1640}
1641
1642/// Create a smooth unit-cylinder mesh with extents -1 to 1 and radius 1
1643pub fn create_cylinder_mesh<D: gfx::Device>(dev: &mut D, segments: usize) -> pmfx::Mesh<D> {
1644    create_prism_mesh(dev, segments, true, true, 1.0, 1.0)
1645}
1646
1647/// Create an indexed unit cube subdivision mesh instance where the faces are subdivided into 4 smaller quads for `subdivisions` 
1648pub fn create_cube_subdivision_mesh<D: gfx::Device>(dev: &mut D, subdivisions: u32) -> pmfx::Mesh<D> {
1649    let vertices = cube_vertices();
1650
1651    let mut subdiv_vertices = Vec::new();
1652    for i in (0..vertices.len()).step_by(4) {
1653        let sub = subdivide_quad(&vertices[i], &vertices[i+1], &vertices[i+2], &vertices[i+3], 0, subdivisions);
1654        subdiv_vertices.extend(sub);
1655    }
1656
1657    // explode to a sphere
1658    for v in &mut subdiv_vertices {
1659        v.position = normalize(v.position);
1660        v.normal = v.position;
1661    }
1662
1663    // create indices... flip the triangles to create better 
1664
1665    //   ___
1666    //  |/|\|
1667    //  |\|/|
1668    // 
1669
1670    let mut indices = Vec::new();
1671    for i in (0..subdiv_vertices.len()).step_by(4) {
1672        let quad = (i / 4) % 4;
1673        if subdivisions > 0 {
1674            if quad == 0 {
1675                indices.extend(vec![
1676                    i,  i + 3,  i + 1,
1677                    i + 1,  i + 3,  i + 2
1678                ]);
1679            }
1680            else if quad == 3 {
1681                indices.extend(vec![
1682                    i,  i + 3,  i + 2,
1683                    i,  i + 2,  i + 1
1684                ]);
1685            }
1686            else if quad == 2 {
1687                indices.extend(vec![
1688                    i,  i + 3,  i + 1,
1689                    i + 1,  i + 3,  i + 2
1690                ]);
1691            }
1692            else {
1693                indices.extend(vec![
1694                    i,  i + 2,  i + 1,
1695                    i,  i + 3,  i + 2
1696                ]);
1697            }
1698        }
1699        else {
1700            indices.extend(vec![
1701                i,  i + 2,  i + 1,  i + 2,  i,  i + 3
1702            ]);
1703        }
1704    }
1705
1706    create_mesh_3d(dev, subdiv_vertices, indices)
1707}
1708
1709/// creates a pyramid mesh, if smooth this is essentially a low poly cone with smooth normals, 
1710pub fn create_pyramid_mesh<D: gfx::Device>(dev: &mut D, segments: usize, smooth: bool, cap: bool) -> pmfx::Mesh<D> {
1711    let axis = Vec3f::unit_y();
1712    let right = Vec3f::unit_x();
1713    let up = cross(axis, right);
1714    let right = cross(axis, up);
1715    let tip = Vec3f::unit_y();
1716    let base = -Vec3f::unit_y();
1717
1718    let mut segment_vertices = Vec::new();
1719    let mut vertices = Vec::new();
1720
1721    // add an extra segment at the end to make uv's wrap nicely
1722    let vertex_segments = segments + 1;
1723
1724    // rotate around up axis and extract some data we can lookup to build vb and ib
1725    let mut angle = 0.0;
1726    let angle_step = f32::two_pi() / segments as f32;
1727    for i in 0..vertex_segments {
1728        // current
1729        let mut x = cos(angle);
1730        let mut y = -sin(angle);
1731        let v1 = right * x + up * y;
1732
1733        // next
1734        angle += angle_step;
1735        x = cos(angle);
1736        y = -sin(angle);
1737        let v2 = right * x + up * y;
1738
1739        // uv
1740        let u = 0.5 + atan2(v1.z, v2.x) / f32::two_pi();
1741        let u = if i == segments { 0.0 } else { u };
1742
1743        // tbn
1744        let n = cross(normalize(v2 - v1), normalize(tip - v1));
1745        let t = v2 - v1;
1746        let bt = cross(n, t);
1747
1748        segment_vertices.push(
1749            Vertex3D {
1750                position: v1 - Vec3f::unit_y(),
1751                texcoord: vec2f((1.0 - u) * 3.0, 1.0),
1752                normal: n,
1753                tangent: t,
1754                bitangent: bt
1755            });
1756    }
1757
1758    //
1759    // Vertices (traingle faces)
1760    //
1761
1762    // tri per segment connected to the tip
1763    if smooth {
1764        for i in 0..segments {
1765            let mid = segment_vertices[i].texcoord.x + (segment_vertices[i + 1].texcoord.x - segment_vertices[i].texcoord.x) * 0.5;
1766            vertices.extend(vec![
1767                segment_vertices[i].clone(),
1768                Vertex3D {
1769                    position: tip,
1770                    texcoord: vec2f(mid, 0.0),
1771                    normal: segment_vertices[i].normal,
1772                    tangent: segment_vertices[i].tangent,
1773                    bitangent: segment_vertices[i].bitangent,
1774                },
1775                segment_vertices[i + 1].clone(),
1776            ])
1777        }
1778    }
1779    else {
1780        for i in 0..segments {
1781
1782            let t0 = segment_vertices[i].position;
1783            let t1 = tip;
1784            let t2 = segment_vertices[i + 1].position;
1785            let n = get_triangle_normal(t0, t2, t1);
1786    
1787            vertices.extend(vec![
1788                Vertex3D {
1789                    position: t0,
1790                    texcoord: vec2f(0.0, 1.0),
1791                    normal: n,
1792                    tangent: segment_vertices[i].tangent,
1793                    bitangent: segment_vertices[i].bitangent,
1794                },
1795                Vertex3D {
1796                    position: t1,
1797                    texcoord: vec2f(0.5, 0.0),
1798                    normal: n,
1799                    tangent: segment_vertices[i].tangent,
1800                    bitangent: segment_vertices[i].bitangent,
1801                },
1802                Vertex3D {
1803                    position: t2,
1804                    texcoord: vec2f(1.0, 1.0),
1805                    normal: n,
1806                    tangent: segment_vertices[i].tangent,
1807                    bitangent: segment_vertices[i].bitangent,
1808                }
1809            ])
1810        }  
1811    }
1812
1813    // base cap
1814    if cap {
1815        for i in 0..segments {
1816            vertices.extend(vec![
1817                Vertex3D {
1818                    position: segment_vertices[i].position,
1819                    texcoord: segment_vertices[i].position.xz() * 0.5 + 0.5,
1820                    normal: -Vec3f::unit_y(),
1821                    tangent: Vec3f::unit_x(),
1822                    bitangent: Vec3f::unit_z(),
1823                },
1824                Vertex3D {
1825                    position: segment_vertices[i + 1].position,
1826                    texcoord: segment_vertices[i + 1].position.xz() * 0.5 + 0.5,
1827                    normal: -Vec3f::unit_y(),
1828                    tangent: Vec3f::unit_x(),
1829                    bitangent: Vec3f::unit_z(),
1830                },
1831                Vertex3D {
1832                    position: base,
1833                    texcoord: Vec2f::point_five(),
1834                    normal: -Vec3f::unit_y(),
1835                    tangent: Vec3f::unit_x(),
1836                    bitangent: Vec3f::unit_z(),
1837                }
1838            ])
1839        }
1840    }
1841
1842    create_faceted_mesh_3d(dev, vertices)
1843}
1844
1845// create a cone mesh with smooth normals made up of `segments` number of sides
1846pub fn create_cone_mesh<D: gfx::Device>(dev: &mut D, segments: usize) -> pmfx::Mesh<D> {
1847    create_pyramid_mesh(dev, segments, true, true)
1848}
1849
1850// create a capsule mesh with smooth normals made up of `segments` number of sides
1851pub fn create_capsule_mesh<D: gfx::Device>(dev: &mut D, segments: usize) -> pmfx::Mesh<D> {
1852    let mut vertices = Vec::new();
1853    let mut indices = Vec::new();
1854
1855    let offset = 0.5 + (1.0 / segments as f32);
1856
1857    // stick the sphere cap verts into a buffer to weld the cylinder verts
1858    let mut weld_positions = Vec::new(); 
1859    let weld_size = (1.0 / segments as f32) * 0.1;
1860
1861    // bottom sphere
1862    let (mut v0, i0) = create_sphere_vertices(segments, 0, segments/2, false);
1863
1864    for v in &mut v0 {
1865        v.position += vec3f(0.0, -offset, 0.0);
1866        weld_positions.push(v.position);
1867    }
1868
1869    // top sphere
1870    let (mut v1, mut i1) = create_sphere_vertices(segments, segments/2, segments, false);    
1871    for v in &mut v1 {
1872        v.position += vec3f(0.0, offset, 0.0);
1873        weld_positions.push(v.position);
1874    }
1875
1876    // offset the indices
1877    let base = v0.len();
1878    for i in &mut i1 {
1879        *i += base;
1880    }
1881
1882    // cylinder
1883    let (mut v2, mut i2) = create_prism_vertices(segments, true, false);   
1884    for v in &mut v2 {
1885        v.position *= vec3f(1.0, 0.5, 1.0);
1886        v.texcoord.y = 1.0 - v.texcoord.y;
1887
1888        // look in weld positions
1889        for w in &weld_positions {
1890            if dist2(v.position, *w) < weld_size {
1891                v.position = *w;
1892                break;
1893            }
1894        }
1895    } 
1896
1897    // offset the indices
1898    let base = base + v1.len();
1899    for i in &mut i2 {
1900        *i += base;
1901    }
1902
1903    vertices.extend(v0);
1904    indices.extend(i0);
1905    vertices.extend(v1);
1906    indices.extend(i1);
1907    vertices.extend(v2);
1908    indices.extend(i2);
1909
1910    create_mesh_3d(dev, vertices, indices)
1911}
1912
1913/// Create a unit smooth tourus mesh 
1914pub fn create_tourus_mesh<D: gfx::Device>(dev: &mut D, segments: usize) -> pmfx::Mesh<D> {
1915    let mut segment_vertices = Vec::new();
1916    let mut vertices = Vec::new();
1917
1918    // add an extra segment at the end to make uv's wrap nicely
1919    let vertex_segments = segments + 1;
1920    let radius = 0.5;
1921
1922    // rotate around up axis and extract some data we can lookup to build vb and ib
1923    let mut hangle = -f32::pi();
1924    let angle_step = f32::two_pi() / segments as f32;
1925    for i in 0..vertex_segments + 1 {
1926        let x = cos(hangle);
1927        let y = -sin(hangle);
1928        
1929        hangle += angle_step;
1930        let x2 = cos(hangle);
1931        let y2 = -sin(hangle);
1932                
1933        let p = vec3f(x, 0.0, y);
1934        let np = vec3f(x2, 0.0, y2);
1935
1936        let at = normalize(np - p);
1937        let up = Vec3f::unit_y();
1938        let right = cross(up, at);
1939        
1940        let mut vangle = -f32::pi();
1941        for j in 0..vertex_segments {
1942            let vx = cos(vangle) * radius;
1943            let vy = -sin(vangle) * radius;
1944            let vv = p + vx * up + vy * right;
1945              
1946            let n = normalize(vx * up + vy * right);
1947            let t = right;
1948            let bt = up;
1949
1950            let u = 0.5 + atan2(y, x) / f32::two_pi();
1951            let u = if i == 0 { 1.0 } else { u };
1952
1953            let v = 0.5 + atan2(vy, vx) / f32::two_pi();
1954            let v = if j == 0 { 1.0 } else { v };
1955
1956            segment_vertices.extend(vec![
1957                Vertex3D {
1958                    position: vv,
1959                    normal: n,
1960                    tangent: t,
1961                    bitangent: bt,
1962                    texcoord: vec2f(1.0 - u, 1.0 - v) * 3.0
1963                }
1964            ]);
1965
1966            vangle += angle_step;
1967        }
1968    }
1969
1970    for i in 0..segments {
1971        for j in 0..segments {
1972            let base = (i * vertex_segments) + j;
1973            let next_loop = base + 1;
1974            let next_base = ((i + 1) * vertex_segments) + j;
1975            let next_next_loop = next_base + 1;
1976            vertices.extend(vec![
1977                segment_vertices[base].clone(),
1978                segment_vertices[next_base].clone(),
1979                segment_vertices[next_loop].clone(),
1980                segment_vertices[next_base].clone(),
1981                segment_vertices[next_next_loop].clone(),
1982                segment_vertices[next_loop].clone(),
1983            ]);
1984        }
1985    }
1986
1987    create_faceted_mesh_3d(dev, vertices)
1988}
1989
1990/// Create a unit smooth helix mesh 
1991pub fn create_helix_mesh<D: gfx::Device>(dev: &mut D, segments: usize, coils: usize) -> pmfx::Mesh<D> {
1992    let mut segment_vertices = Vec::new();
1993    let mut vertices = Vec::new();
1994
1995    // add an extra segment at the end to make uv's wrap nicely
1996    let vertex_segments = segments + 1;
1997    let radius = 0.5;
1998
1999    // rotate around up axis and extract some data we can lookup to build vb and ib
2000    let mut hangle = -f32::pi();
2001    let angle_step = f32::two_pi() / segments as f32;
2002    let height_step = 1.5 / segments as f32;
2003    let scale = 2.0 / coils as f32;
2004
2005    let mut h = -height_step * (segments * 2) as f32;
2006    for _ in 0..coils {
2007        let mut uv_hangle = -f32::pi();
2008        for i in 0..vertex_segments {
2009            let x = cos(hangle);
2010            let y = -sin(hangle);
2011            
2012            let uvx = cos(uv_hangle);
2013            let uvy = -sin(uv_hangle);
2014            uv_hangle += angle_step;
2015            
2016            hangle += angle_step;
2017            let x2 = cos(hangle);
2018            let y2 = -sin(hangle);
2019            
2020            let p = vec3f(x, h, y);
2021            let np = vec3f(x2, h + angle_step, y2);
2022            
2023            let at = normalize(np - p);
2024            let up = Vec3f::unit_y();
2025            let right = cross(up, at);
2026                
2027            let mut vangle = -f32::pi();
2028            for j in 0..vertex_segments {
2029                let vx = cos(vangle) * radius;
2030                let vy = -sin(vangle) * radius;
2031                let vv = p + vx * up + vy * right;
2032                  
2033                let n = normalize(vx * up + vy * right);
2034                let t = right;
2035                let bt = up;
2036    
2037                let u = 0.5 + atan2(uvy, uvx) / f32::two_pi();
2038                let u = if i == 0 { 1.0 } else { u };
2039
2040                let v = 0.5 + atan2(vy, vx) / f32::two_pi();
2041                let v = if j == 0 { 1.0 } else { v };
2042
2043                segment_vertices.extend(vec![
2044                    Vertex3D {
2045                        position: vv * scale,
2046                        normal: n,
2047                        tangent: t,
2048                        bitangent: bt,
2049                        texcoord: vec2f(u, 1.0 - v) * 3.0
2050                    }
2051                ]);
2052    
2053                vangle += angle_step;
2054            }
2055
2056            h += height_step;
2057
2058            // this adds in an extra (degenerate) loop
2059            if i == segments {
2060                hangle -= angle_step;
2061                h -= height_step;
2062            } 
2063        }
2064    }
2065    
2066    for k in 0..coils {
2067        for i in 0..segments {
2068            for j in 0..segments {
2069                let coil_base = vertex_segments * segments * k;
2070                let base = coil_base + (i * vertex_segments) + j;
2071                let next_loop = base + 1;
2072                let next_base = coil_base + ((i + 1) * vertex_segments) + j;
2073                let next_next_loop = next_base + 1;
2074                vertices.extend(vec![
2075                    segment_vertices[base].clone(),
2076                    segment_vertices[next_base].clone(),
2077                    segment_vertices[next_loop].clone(),
2078                    segment_vertices[next_base].clone(),
2079                    segment_vertices[next_next_loop].clone(),
2080                    segment_vertices[next_loop].clone(),
2081                ]);
2082            }
2083        }
2084    }
2085
2086    // start cap
2087    let mut mid_pos = Vec3f::zero();
2088    for vertex in segment_vertices.iter().take(segments) {
2089        mid_pos += vertex.position;
2090    }
2091    mid_pos /= segments as f32;
2092
2093    for j in 0..segments {
2094        let p0 = segment_vertices[j + 1].position;
2095        let p1 = segment_vertices[j].position;
2096        vertices.extend(vec![
2097            Vertex3D {
2098                position: p0,
2099                normal: -Vec3f::unit_z(),
2100                texcoord: normalize(mid_pos.xy() - p0.xy()) * 0.5 + 0.5,
2101                tangent: Vec3f::unit_x(),
2102                bitangent: Vec3f::unit_y()
2103            },
2104            Vertex3D {
2105                position: mid_pos,
2106                normal: -Vec3f::unit_z(),
2107                texcoord: vec2f(0.5, 0.5),
2108                tangent: Vec3f::unit_x(),
2109                bitangent: Vec3f::unit_y()
2110            },
2111            Vertex3D {
2112                position: p1,
2113                normal: -Vec3f::unit_z(),
2114                texcoord: normalize(mid_pos.xy() - p1.xy()) * 0.5 + 0.5,
2115                tangent: Vec3f::unit_x(),
2116                bitangent: Vec3f::unit_y()
2117            }
2118        ]);
2119    }
2120
2121    // end cap
2122    let offset = vertex_segments * segments * coils;
2123    let mut mid_pos = Vec3f::zero();
2124    for j in 0..segments {
2125        mid_pos += segment_vertices[offset + j].position;
2126    }
2127    mid_pos /= segments as f32;
2128
2129    for j in 0..segments {
2130        let p0 = segment_vertices[offset + j].position;
2131        let p1 = segment_vertices[offset + j + 1].position;
2132        vertices.extend(vec![
2133            Vertex3D {
2134                position: p0,
2135                normal: Vec3f::unit_z(),
2136                texcoord: normalize(mid_pos.xy() - p0.xy()) * 0.5 + 0.5,
2137                tangent: Vec3f::unit_x(),
2138                bitangent: Vec3f::unit_y()
2139            },
2140            Vertex3D {
2141                position: mid_pos,
2142                normal: Vec3f::unit_z(),
2143                texcoord: vec2f(0.5, 0.5),
2144                tangent: Vec3f::unit_x(),
2145                bitangent: Vec3f::unit_y()
2146            },
2147            Vertex3D {
2148                position: p1,
2149                normal: Vec3f::unit_z(),
2150                texcoord: normalize(mid_pos.xy() - p1.xy()) * 0.5 + 0.5,
2151                tangent: Vec3f::unit_x(),
2152                bitangent: Vec3f::unit_y()
2153            }
2154        ]);
2155    }
2156
2157    create_faceted_mesh_3d(dev, vertices)
2158}
2159
2160/// Creates a chamfer cube mesh with curved edges with `radius` size and `segments` subdivisions
2161pub fn create_chamfer_cube_mesh<D: gfx::Device>(dev: &mut D, radius: f32, segments: usize) -> pmfx::Mesh<D> {
2162    let inset = 1.0 - radius;
2163    let edge_uv_scale = radius;
2164
2165    // cube verts with inset
2166    let mut vertices = cube_vertices();
2167
2168    let insets = [
2169        vec3f(inset, inset, 1.0),
2170        vec3f(1.0, inset, inset),
2171        vec3f(inset, 1.0, inset),
2172    ];
2173
2174    for (i, vertex) in vertices.iter_mut().enumerate() {
2175        let face = i / 8;
2176        vertex.position *= insets[face];
2177    }
2178
2179    let mut indices: Vec<usize> = vec![
2180        0,  2,  1,  2,  0,  3,   // front face
2181        4,  6,  5,  6,  4,  7,   // back face
2182        8,  10, 9,  10, 8,  11,  // right face
2183        12, 14, 13, 14, 12, 15,  // left face
2184        16, 18, 17, 18, 16, 19,  // top face
2185        20, 22, 21, 22, 20, 23,  // bottom face
2186    ];
2187
2188    // join edges
2189    let join_edge = |edge_indices: [usize; 4], clamp_axis: usize, vertices: &mut Vec<Vertex3D>, indices: &mut Vec<usize>| {
2190        let bottom_start = vertices[edge_indices[0]].position;
2191        let top_start = vertices[edge_indices[1]].position; 
2192        let top_end = vertices[edge_indices[2]].position;
2193        let bottom_end = vertices[edge_indices[3]].position;   
2194        let fsegments = segments as f32;
2195        let base_index = vertices.len();
2196        
2197        let pivot = bottom_start - vertices[edge_indices[0]].normal * radius;
2198        let top_pivot = top_start - vertices[edge_indices[0]].normal * radius;
2199
2200        for i in 0..segments+1 {
2201            let cur = (1.0 / fsegments) * i as f32;
2202            let v = cur * edge_uv_scale;
2203    
2204            // linear lerp
2205            let lv0 = lerp(bottom_start, bottom_end, cur);
2206            let lv1 = lerp(top_start, top_end, cur);
2207    
2208            // project corner to unit cube (chebyshev_normalize)
2209            let cur = if cur > 0.5 {
2210                1.0 - cur
2211            }
2212            else {
2213                cur
2214            };
2215
2216            // lerp between square corner and cut corner, forming circle
2217            let mut p0 = lerp(chebyshev_normalize(lv0), lv0, cur);
2218            let mut p1 = lerp(chebyshev_normalize(lv1), lv1, cur);
2219    
2220            // ..
2221            p0[clamp_axis] = bottom_start[clamp_axis];
2222            p1[clamp_axis] = top_start[clamp_axis];
2223
2224            let n = normalize(p0 - pivot);
2225            let t = normalize(top_pivot - pivot);
2226            let bt = cross(n, t);
2227    
2228            vertices.extend(
2229                vec![
2230                    Vertex3D {
2231                        position: pivot + normalize(p0 - pivot) * radius,
2232                        normal: n,
2233                        tangent: t,
2234                        bitangent: bt,
2235                        texcoord: vec2f(0.0, v)
2236                    },
2237                    Vertex3D {
2238                        position: top_pivot + normalize(p1 - top_pivot) * radius,
2239                        normal: n,
2240                        tangent: t,
2241                        bitangent: bt,
2242                        texcoord: vec2f(1.0, v)
2243                    }
2244                ]
2245            );
2246        }
2247
2248        for i in 0..segments {
2249            let strip_base = base_index + i * 2;
2250            indices.extend(vec![
2251                strip_base, strip_base + 1, strip_base + 3, 
2252                strip_base, strip_base + 3, strip_base + 2
2253            ]);
2254        }
2255    };
2256
2257    // join sides
2258    join_edge([1, 2, 10, 11], 1, &mut vertices, &mut indices); // front-right
2259    join_edge([8, 9, 6, 7], 1, &mut vertices, &mut indices); // right-back
2260    join_edge([4, 5, 12, 15], 1, &mut vertices, &mut indices); // back-left
2261    join_edge([13, 14, 0, 3], 1, &mut vertices, &mut indices); // left-front
2262
2263    // join top
2264    let ft_loop_start = vertices.len();
2265    join_edge([2, 3, 17, 18], 0, &mut vertices, &mut indices); // front-top
2266
2267    let rt_loop_start = vertices.len();
2268    join_edge([9, 10, 19, 18], 2, &mut vertices, &mut indices); // right-top
2269
2270    let bt_loop_start = vertices.len();
2271    join_edge([5, 6, 16, 19], 0, &mut vertices, &mut indices); // back-top
2272
2273    let lt_loop_start = vertices.len();
2274    join_edge([14, 15, 16, 17], 2, &mut vertices, &mut indices); // left-top
2275
2276    // join bottom
2277    let fb_loop_start = vertices.len();
2278    join_edge([0, 1, 22, 23], 0, &mut vertices, &mut indices); // front-bottom
2279
2280    let rb_loop_start = vertices.len();
2281    join_edge([11, 8, 22, 21], 2, &mut vertices, &mut indices); // right-bottom
2282
2283    let bb_loop_start = vertices.len();
2284    join_edge([7, 4, 21, 20], 0, &mut vertices, &mut indices); // back-bottom
2285
2286    let lb_loop_start = vertices.len();
2287    join_edge([12, 13, 20, 23], 2, &mut vertices, &mut indices); // left-bottom
2288
2289    let join_corner = |start_loop_start: usize, end_loop_start: usize, vertices: &mut Vec<Vertex3D>, indices: &mut Vec<usize>| {
2290        let base_index = vertices.len();        
2291        let fsegments = segments as f32;
2292        let centre = vertices[start_loop_start].position - vertices[start_loop_start].normal * radius;
2293
2294        for j in 0..segments+1 {
2295            let joffset = j * 2;
2296            let start = vertices[start_loop_start + joffset].position;
2297            let end = vertices[end_loop_start + 1 + joffset].position;
2298            let v = (1.0 / fsegments) * j as f32;
2299    
2300            for i in 0..segments+1 {
2301                let u = (1.0 / fsegments) * i as f32;
2302                let next = (1.0 / fsegments) * (i+1) as f32;
2303    
2304                let lv0 = lerp(start, end, u);
2305                let lv1 = lerp(start, end, next);
2306
2307                let p = centre + normalize(lv0 - centre) * radius;
2308                let nextp = centre + normalize(lv1 - centre) * radius;
2309    
2310                let n = normalize(lv0 - centre);
2311                let mut t = normalize(p - nextp);
2312                
2313                if j > segments - 1 {
2314                    t = Vec3f::unit_x();
2315                }
2316                let bt = cross(n, t);
2317
2318                vertices.extend(vec![
2319                    Vertex3D {
2320                        position: p,
2321                        normal: n,
2322                        tangent: t,
2323                        bitangent: bt,
2324                        texcoord: vec2f(u, v) * edge_uv_scale
2325                    },
2326                ]);
2327            }
2328        }
2329    
2330        for j in 0..segments {
2331            let ycur = base_index + j * (segments+1);
2332            let ynext = base_index + (j+1) * (segments+1);
2333            for i in 0..segments {
2334                let xcur = ycur + i;
2335                let xnext = ynext + i;
2336                indices.extend(vec![
2337                    xcur, xnext, xcur + 1,
2338                    xnext, xnext+1, xcur + 1
2339                ]);
2340            }
2341        }
2342    };
2343
2344    join_corner(ft_loop_start, rt_loop_start, &mut vertices, &mut indices);
2345    join_corner(rt_loop_start, bt_loop_start, &mut vertices, &mut indices);
2346    join_corner(bt_loop_start, lt_loop_start, &mut vertices, &mut indices);
2347    join_corner(lt_loop_start, ft_loop_start, &mut vertices, &mut indices);
2348    join_corner(rb_loop_start, fb_loop_start, &mut vertices, &mut indices);
2349    join_corner(bb_loop_start, rb_loop_start, &mut vertices, &mut indices);
2350    join_corner(lb_loop_start, bb_loop_start, &mut vertices, &mut indices);
2351    join_corner(fb_loop_start, lb_loop_start, &mut vertices, &mut indices);
2352
2353    create_mesh_3d(dev, vertices, indices)
2354}
2355
2356/// Create an `segments` sided prism tude, if `smooth` the prism is a cylinder with smooth normals
2357/// convert to a trapezoid using `taper` with a value between 0-1 to taper the top cap inward where 1 is no taper and 0 makes a pyramid
2358/// use thickness to control the size of the inner hole
2359#[allow(clippy::too_many_arguments)]
2360pub fn create_tube_prism_mesh<D: gfx::Device>(
2361    dev: &mut D, segments: usize, trunc_start: usize, trunc_end: usize, smooth: bool, cap: bool, height: f32, thickness: f32, taper: f32) -> pmfx::Mesh<D> {
2362    let axis = Vec3f::unit_y();
2363    let right = Vec3f::unit_x();
2364    let up = cross(axis, right);
2365    let right = cross(axis, up);
2366
2367    // add an extra segment at the end to make uv's wrap nicely
2368    let vertex_segments = segments + 1;
2369
2370    let prism_vertices = |radius: f32, flip: f32| -> (Vec<Vertex3D>, Vec<Vertex3D>) {
2371        let mut vertices = Vec::new();
2372        let mut cap_vertices = Vec::new();
2373        let mut points = Vec::new();
2374        let mut bottom_points = Vec::new();
2375        let mut top_points = Vec::new();
2376        let mut tangents = Vec::new();
2377    
2378        // rotate around up axis and extract some data we can lookup to build vb and ib
2379        let mut angle = 0.0;
2380        let angle_step = f32::two_pi() / segments as f32;
2381        for i in 0..vertex_segments {
2382            // current
2383            let mut x = cos(angle);
2384            let mut y = -sin(angle);
2385            let v1 = right * x + up * y;
2386    
2387            // next
2388            angle += angle_step;
2389            x = cos(angle);
2390            y = -sin(angle);
2391            let v2 = right * x + up * y;
2392    
2393            points.push(v1 * radius);
2394            tangents.push(v2 - v1);
2395    
2396            bottom_points.push(points[i] - Vec3f::unit_y() * height);
2397            top_points.push(points[i] * taper + Vec3f::unit_y() * height);
2398        }
2399    
2400        // bottom ring
2401        for i in 0..vertex_segments {
2402            let u = 0.5 + atan2(bottom_points[i].z, bottom_points[i].x) / f32::two_pi();
2403            let u = if i == segments { 0.0 } else { u };
2404            let bt = cross(tangents[i], points[i]);
2405            vertices.push(Vertex3D{
2406                position: bottom_points[i],
2407                normal: points[i] * flip,
2408                tangent: tangents[i],
2409                bitangent: bt,
2410                texcoord: Vec2f::new(u * 3.0, 0.0)
2411            });
2412        }
2413    
2414        // top ring
2415        for i in 0..vertex_segments {
2416            let u = 0.5 + atan2(top_points[i].z, top_points[i].x) / f32::two_pi();
2417            let u = if i == segments { 0.0 } else { u };
2418            let bt = cross(tangents[i], points[i]);
2419            vertices.push(Vertex3D{
2420                position: top_points[i],
2421                normal: points[i] * flip,
2422                tangent: tangents[i],
2423                bitangent: bt,
2424                texcoord: Vec2f::new(u * 3.0, 1.0)
2425            });
2426        }
2427
2428        // bottom cap
2429        for point in bottom_points.iter().take(vertex_segments) {
2430            cap_vertices.push(Vertex3D{
2431                position: point.xyz(),
2432                normal: -Vec3f::unit_y(),
2433                tangent: Vec3f::unit_x(),
2434                bitangent: Vec3f::unit_z(),
2435                texcoord: point.xz() * 0.5 + 0.5
2436            });
2437        }
2438
2439        // top cap
2440        for point in top_points.iter().take(vertex_segments) {
2441            cap_vertices.push(Vertex3D{
2442                position: point.xyz(),
2443                normal: Vec3f::unit_y(),
2444                tangent: Vec3f::unit_x(),
2445                bitangent: Vec3f::unit_z(),
2446                texcoord: point.xz() * 0.5 + 0.5
2447            });
2448        }
2449
2450        (vertices, cap_vertices)
2451    };
2452
2453    let end_cap = |loop_start: usize, v: &Vec<Vertex3D>, inner_offset: usize, flip: f32| -> Vec<Vertex3D> {
2454        // start
2455        let bottom = loop_start;
2456        let top = loop_start + vertex_segments;
2457        let inner_bottom = bottom + inner_offset;
2458        let inner_top = top + inner_offset;
2459
2460        let mut verts = vec![
2461            v[bottom].clone(),
2462            v[top].clone(),
2463            v[inner_bottom].clone(),
2464            v[inner_top].clone(),
2465        ];
2466
2467        let b = normalize(verts[1].position - verts[0].position);
2468        let t = normalize(verts[2].position - verts[0].position);
2469        let n = cross(b, t) * flip;
2470
2471        for v in &mut verts {
2472            v.normal = n;
2473            v.tangent = t;
2474            v.bitangent = b;
2475        }
2476
2477        verts[0].texcoord = Vec2f::zero();
2478        verts[1].texcoord = vec2f(0.0, 1.0);
2479        verts[2].texcoord = vec2f(1.0 - thickness, 0.0);
2480        verts[3].texcoord = vec2f(1.0 - thickness, 1.0);
2481
2482        verts
2483    };
2484
2485    let (outer_vertices, outer_cap_vertices) = prism_vertices(1.0, 1.0);
2486    let (inner_vertices, inner_cap_vertices) = prism_vertices(thickness, -1.0);
2487
2488    if smooth {
2489        let mut indices = Vec::new();
2490        let mut vertices = Vec::new();
2491    
2492        vertices.extend(outer_vertices);
2493    
2494        let outer_cap_offset = vertices.len();
2495        vertices.extend(outer_cap_vertices);
2496    
2497        let inner_offset = vertices.len();
2498        vertices.extend(inner_vertices);
2499    
2500        let inner_cap_offset = vertices.len();
2501        vertices.extend(inner_cap_vertices);
2502
2503        // sides
2504        for i in trunc_start..trunc_end {
2505            let bottom = i;
2506            let top = i + vertex_segments;
2507            let next = i + 1;
2508            let top_next = i + 1 + vertex_segments;
2509
2510            // outer
2511            indices.extend(vec![
2512                bottom,
2513                top,
2514                next,
2515                top,
2516                top_next,
2517                next
2518            ]);
2519
2520            // inner
2521            indices.extend(vec![
2522                bottom + inner_offset,
2523                next + inner_offset,
2524                top + inner_offset,
2525                top + inner_offset,
2526                next + inner_offset,
2527                top_next + inner_offset,
2528            ]);
2529
2530            // caps
2531            if cap {
2532                let inner_bottom = bottom + inner_cap_offset;
2533                let inner_top = top + inner_cap_offset;
2534                let inner_top_next = top_next + inner_cap_offset;
2535                let inner_bottom_next = next + inner_cap_offset;
2536
2537                let outer_bottom = bottom + outer_cap_offset;
2538                let outer_top = top + outer_cap_offset;
2539                let outer_top_next = top_next + outer_cap_offset;
2540                let outer_bottom_next = next + outer_cap_offset;
2541
2542                indices.extend(vec![
2543                    outer_top,
2544                    inner_top,
2545                    inner_top_next,
2546                    outer_top,
2547                    inner_top_next,
2548                    outer_top_next
2549                ]);
2550
2551                indices.extend(vec![
2552                    inner_bottom,
2553                    outer_bottom,
2554                    outer_bottom_next,
2555                    inner_bottom,
2556                    outer_bottom_next,
2557                    inner_bottom_next
2558                ]);
2559            }
2560        }
2561
2562        // end caps
2563        if trunc_start != 0 || trunc_end != segments {
2564            let start_verts = end_cap(trunc_start, &vertices, inner_offset, 1.0);
2565            let start_offset = vertices.len();
2566            vertices.extend(start_verts);
2567
2568            indices.extend(vec![
2569                start_offset,
2570                start_offset + 3,
2571                start_offset + 1,
2572                start_offset,
2573                start_offset + 2,
2574                start_offset + 3,
2575            ]);
2576
2577            let end_verts = end_cap(trunc_end, &vertices, inner_offset, -1.0);
2578            let end_offset = vertices.len();
2579            vertices.extend(end_verts);
2580
2581            // end
2582            indices.extend(vec![
2583                end_offset,
2584                end_offset + 1,
2585                end_offset + 3,
2586                end_offset,
2587                end_offset + 3,
2588                end_offset + 2,
2589            ]);
2590        }
2591
2592        create_mesh_3d(dev, vertices, indices)
2593    }
2594    else {
2595        // 2 tris per segment
2596        let mut triangle_vertices = Vec::new();
2597        for i in trunc_start..trunc_end {
2598            let bottom = i;
2599            let top = i + vertex_segments;
2600            let next = i + 1;
2601            let top_next = i + 1 + vertex_segments;
2602
2603            let face_index = triangle_vertices.len();
2604            triangle_vertices.extend(vec![
2605                outer_vertices[bottom].clone(),
2606                outer_vertices[top].clone(),
2607                outer_vertices[next].clone(),
2608                outer_vertices[top].clone(),
2609                outer_vertices[top_next].clone(),
2610                outer_vertices[next].clone()
2611            ]);
2612
2613            let v = face_index;
2614            let n = get_triangle_normal(
2615                triangle_vertices[v].position, 
2616                triangle_vertices[v+2].position, 
2617                triangle_vertices[v+1].position
2618            );
2619
2620            // set hard face normals
2621            for vertex in triangle_vertices.iter_mut().skip(face_index) {
2622                vertex.normal = n;
2623            }
2624        }
2625
2626        for i in trunc_start..trunc_end {
2627            let bottom = i;
2628            let top = i + vertex_segments;
2629            let next = i + 1;
2630            let top_next = i + 1 + vertex_segments;
2631
2632            let face_index = triangle_vertices.len();
2633            triangle_vertices.extend(vec![
2634                inner_vertices[bottom].clone(),
2635                inner_vertices[next].clone(),
2636                inner_vertices[top].clone(),
2637                inner_vertices[top].clone(),
2638                inner_vertices[next].clone(),
2639                inner_vertices[top_next].clone()
2640            ]);
2641
2642            let v = face_index;
2643            let n = get_triangle_normal(
2644                triangle_vertices[v].position, 
2645                triangle_vertices[v+2].position,
2646                triangle_vertices[v+1].position,
2647            );
2648
2649            // set hard face normals
2650            for vertex in triangle_vertices.iter_mut().skip(face_index) {
2651                vertex.normal = n;
2652            }
2653        }
2654
2655        // top / bottom cap
2656        if cap {
2657            for i in trunc_start..trunc_end {
2658                let bottom = i;
2659                let top = i + vertex_segments;
2660                let next = i + 1;
2661                let top_next = i + 1 + vertex_segments;
2662
2663                triangle_vertices.extend(vec![
2664                    outer_cap_vertices[top].clone(),
2665                    inner_cap_vertices[top].clone(),
2666                    inner_cap_vertices[top_next].clone(),
2667                    outer_cap_vertices[top].clone(),
2668                    inner_cap_vertices[top_next].clone(),
2669                    outer_cap_vertices[top_next].clone()
2670                ]);
2671
2672                triangle_vertices.extend(vec![
2673                    inner_cap_vertices[bottom].clone(),
2674                    outer_cap_vertices[bottom].clone(),
2675                    outer_cap_vertices[next].clone(),
2676                    inner_cap_vertices[bottom].clone(),
2677                    outer_cap_vertices[next].clone(),
2678                    inner_cap_vertices[next].clone()
2679                ]);
2680            }    
2681        }
2682
2683        // end cap
2684        if trunc_start != 0 || trunc_end != segments {
2685            let mut vertices = outer_vertices.to_vec();
2686            let inner_offset = vertices.len();
2687            vertices.extend(inner_vertices);
2688
2689            let start_verts = end_cap(trunc_start, &vertices, inner_offset, 1.0);
2690            triangle_vertices.extend(vec![
2691                start_verts[0].clone(),
2692                start_verts[3].clone(),
2693                start_verts[1].clone(),
2694                start_verts[0].clone(),
2695                start_verts[2].clone(),
2696                start_verts[3].clone(),
2697            ]);
2698
2699            let end_verts = end_cap(trunc_end, &vertices, inner_offset, -1.0);
2700            triangle_vertices.extend(vec![
2701                end_verts[0].clone(),
2702                end_verts[1].clone(),
2703                end_verts[3].clone(),
2704                end_verts[0].clone(),
2705                end_verts[3].clone(),
2706                end_verts[2].clone(),
2707            ]);
2708        }
2709
2710        create_faceted_mesh_3d(dev, triangle_vertices)
2711    }
2712}
2713
2714fn cubic_interpolate(p1: Vec3f, p2: Vec3f, p3: Vec3f, p4: Vec3f, t: f32) -> Vec3f {
2715    p1 * (1.0 - t) * (1.0 - t) * (1.0 - t) +
2716    p2 * 3.0 * t * (1.0 - t) * (1.0 - t) +
2717    p3 * 3.0 * t * t * (1.0 - t) +
2718    p4 * t * t * t
2719}
2720
2721fn cubic_tangent(p1: Vec3f, p2: Vec3f, p3: Vec3f, p4: Vec3f, t: f32) -> Vec3f {
2722    p1 * (-1.0 + 2.0 * t - t * t) +
2723    p2 * (1.0 - 4.0 * t + 3.0 * t * t) +
2724    p3 * (2.0 * t - 3.0 * t * t) +
2725    p4 * (t * t)
2726}
2727
2728/// Create a unit utah teapot mesh
2729pub fn create_teapot_mesh<D: gfx::Device>(dev: &mut D, tessellation: usize) -> pmfx::Mesh<D> {
2730    // this code was ported from DirectXTK https://github.com/microsoft/DirectXTK
2731    struct TeapotPatch {
2732        mirror_z: bool,
2733        indices: [u32; 16]
2734    }
2735
2736    let patches = vec![
2737        // rim
2738        TeapotPatch {
2739            mirror_z: true,
2740            indices: [
2741                102, 103, 104, 105, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
2742            ]
2743        },
2744
2745        // body
2746        TeapotPatch {
2747            mirror_z: true,
2748            indices: [
2749                12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27
2750            ]
2751        },
2752        TeapotPatch {
2753            mirror_z: true,
2754            indices: [
2755                24, 25, 26, 27, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40
2756            ]
2757        },
2758
2759        // lid
2760        TeapotPatch {
2761            mirror_z: true,
2762            indices: [
2763                96, 96, 96, 96, 97, 98, 99, 100, 101, 101, 101, 101, 0, 1, 2, 3
2764            ]
2765        },
2766        TeapotPatch {
2767            mirror_z: true,
2768            indices: [
2769                0, 1, 2, 3, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117
2770            ]
2771        },
2772
2773        // handle 
2774        TeapotPatch {
2775            mirror_z: false,
2776            indices: [
2777                41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56
2778            ]
2779        },
2780        TeapotPatch {
2781            mirror_z: false,
2782            indices: [
2783                53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 28, 65, 66, 67
2784            ]
2785        },
2786
2787        // spout 
2788        TeapotPatch {
2789            mirror_z: false,
2790            indices: [
2791                68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83
2792            ]
2793        },
2794        TeapotPatch {
2795            mirror_z: false,
2796            indices: [
2797                80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95
2798            ]
2799        },
2800
2801        // bottom
2802        TeapotPatch {
2803            mirror_z: true,
2804            indices: [
2805                118, 118, 118, 118, 124, 122, 119, 121, 123, 126, 125, 120, 40, 39, 38, 37
2806            ]
2807        }
2808    ];
2809
2810    let control_points = vec![
2811        vec3f(0.0, 0.345, -0.05),
2812        vec3f(-0.028, 0.345, -0.05),
2813        vec3f(-0.05, 0.345, -0.028),
2814        vec3f(-0.05, 0.345, -0.0),
2815        vec3f(0.0, 0.3028125, -0.334375),
2816        vec3f(-0.18725, 0.3028125, -0.334375),
2817        vec3f(-0.334375, 0.3028125, -0.18725),
2818        vec3f(-0.334375, 0.3028125, -0.0),
2819        vec3f(0.0, 0.3028125, -0.359375),
2820        vec3f(-0.20125, 0.3028125, -0.359375),
2821        vec3f(-0.359375, 0.3028125, -0.20125),
2822        vec3f(-0.359375, 0.3028125, -0.0),
2823        vec3f(0.0, 0.27, -0.375),
2824        vec3f(-0.21, 0.27, -0.375),
2825        vec3f(-0.375, 0.27, -0.21),
2826        vec3f(-0.375, 0.27, -0.0),
2827        vec3f(0.0, 0.13875, -0.4375),
2828        vec3f(-0.245, 0.13875, -0.4375),
2829        vec3f(-0.4375, 0.13875, -0.245),
2830        vec3f(-0.4375, 0.13875, -0.0),
2831        vec3f(0.0, 0.007499993, -0.5),
2832        vec3f(-0.28, 0.007499993, -0.5),
2833        vec3f(-0.5, 0.007499993, -0.28),
2834        vec3f(-0.5, 0.007499993, -0.0),
2835        vec3f(0.0, -0.105, -0.5),
2836        vec3f(-0.28, -0.105, -0.5),
2837        vec3f(-0.5, -0.105, -0.28),
2838        vec3f(-0.5, -0.105, -0.0),
2839        vec3f(0.0, -0.105, 0.5),
2840        vec3f(0.0, -0.2175, -0.5),
2841        vec3f(-0.28, -0.2175, -0.5),
2842        vec3f(-0.5, -0.2175, -0.28),
2843        vec3f(-0.5, -0.2175, -0.0),
2844        vec3f(0.0, -0.27375, -0.375),
2845        vec3f(-0.21, -0.27375, -0.375),
2846        vec3f(-0.375, -0.27375, -0.21),
2847        vec3f(-0.375, -0.27375, -0.0),
2848        vec3f(0.0, -0.2925, -0.375),
2849        vec3f(-0.21, -0.2925, -0.375),
2850        vec3f(-0.375, -0.2925, -0.21),
2851        vec3f(-0.375, -0.2925, -0.0),
2852        vec3f(0.0, 0.17625, 0.4),
2853        vec3f(-0.075, 0.17625, 0.4),
2854        vec3f(-0.075, 0.2325, 0.375),
2855        vec3f(0.0, 0.2325, 0.375),
2856        vec3f(0.0, 0.17625, 0.575),
2857        vec3f(-0.075, 0.17625, 0.575),
2858        vec3f(-0.075, 0.2325, 0.625),
2859        vec3f(0.0, 0.2325, 0.625),
2860        vec3f(0.0, 0.17625, 0.675),
2861        vec3f(-0.075, 0.17625, 0.675),
2862        vec3f(-0.075, 0.2325, 0.75),
2863        vec3f(0.0, 0.2325, 0.75),
2864        vec3f(0.0, 0.12, 0.675),
2865        vec3f(-0.075, 0.12, 0.675),
2866        vec3f(-0.075, 0.12, 0.75),
2867        vec3f(0.0, 0.12, 0.75),
2868        vec3f(0.0, 0.06375, 0.675),
2869        vec3f(-0.075, 0.06375, 0.675),
2870        vec3f(-0.075, 0.007499993, 0.75),
2871        vec3f(0.0, 0.007499993, 0.75),
2872        vec3f(0.0, -0.04875001, 0.625),
2873        vec3f(-0.075, -0.04875001, 0.625),
2874        vec3f(-0.075, -0.09562501, 0.6625),
2875        vec3f(0.0, -0.09562501, 0.6625),
2876        vec3f(-0.075, -0.105, 0.5),
2877        vec3f(-0.075, -0.18, 0.475),
2878        vec3f(0.0, -0.18, 0.475),
2879        vec3f(0.0, 0.02624997, -0.425),
2880        vec3f(-0.165, 0.02624997, -0.425),
2881        vec3f(-0.165, -0.18, -0.425),
2882        vec3f(0.0, -0.18, -0.425),
2883        vec3f(0.0, 0.02624997, -0.65),
2884        vec3f(-0.165, 0.02624997, -0.65),
2885        vec3f(-0.165, -0.12375, -0.775),
2886        vec3f(0.0, -0.12375, -0.775),
2887        vec3f(0.0, 0.195, -0.575),
2888        vec3f(-0.0625, 0.195, -0.575),
2889        vec3f(-0.0625, 0.17625, -0.6),
2890        vec3f(0.0, 0.17625, -0.6),
2891        vec3f(0.0, 0.27, -0.675),
2892        vec3f(-0.0625, 0.27, -0.675),
2893        vec3f(-0.0625, 0.27, -0.825),
2894        vec3f(0.0, 0.27, -0.825),
2895        vec3f(0.0, 0.28875, -0.7),
2896        vec3f(-0.0625, 0.28875, -0.7),
2897        vec3f(-0.0625, 0.2934375, -0.88125),
2898        vec3f(0.0, 0.2934375, -0.88125),
2899        vec3f(0.0, 0.28875, -0.725),
2900        vec3f(-0.0375, 0.28875, -0.725),
2901        vec3f(-0.0375, 0.298125, -0.8625),
2902        vec3f(0.0, 0.298125, -0.8625),
2903        vec3f(0.0, 0.27, -0.7),
2904        vec3f(-0.0375, 0.27, -0.7),
2905        vec3f(-0.0375, 0.27, -0.8),
2906        vec3f(0.0, 0.27, -0.8),
2907        vec3f(0.0, 0.4575, -0.0),
2908        vec3f(0.0, 0.4575, -0.2),
2909        vec3f(-0.1125, 0.4575, -0.2),
2910        vec3f(-0.2, 0.4575, -0.1125),
2911        vec3f(-0.2, 0.4575, -0.0),
2912        vec3f(0.0, 0.3825, -0.0),
2913        vec3f(0.0, 0.27, -0.35),
2914        vec3f(-0.196, 0.27, -0.35),
2915        vec3f(-0.35, 0.27, -0.196),
2916        vec3f(-0.35, 0.27, -0.0),
2917        vec3f(0.0, 0.3075, -0.1),
2918        vec3f(-0.056, 0.3075, -0.1),
2919        vec3f(-0.1, 0.3075, -0.056),
2920        vec3f(-0.1, 0.3075, -0.0),
2921        vec3f(0.0, 0.3075, -0.325),
2922        vec3f(-0.182, 0.3075, -0.325),
2923        vec3f(-0.325, 0.3075, -0.182),
2924        vec3f(-0.325, 0.3075, -0.0),
2925        vec3f(0.0, 0.27, -0.325),
2926        vec3f(-0.182, 0.27, -0.325),
2927        vec3f(-0.325, 0.27, -0.182),
2928        vec3f(-0.325, 0.27, -0.0),
2929        vec3f(0.0, -0.33, -0.0),
2930        vec3f(-0.1995, -0.33, -0.35625),
2931        vec3f(0.0, -0.31125, -0.375),
2932        vec3f(0.0, -0.33, -0.35625),
2933        vec3f(-0.35625, -0.33, -0.1995),
2934        vec3f(-0.375, -0.31125, -0.0),
2935        vec3f(-0.35625, -0.33, -0.0),
2936        vec3f(-0.21, -0.31125, -0.375),
2937        vec3f(-0.375, -0.31125, -0.21),
2938    ];
2939
2940    let create_patch_indices = |tessellation: usize, is_mirrored: bool,  index_offset: usize| -> Vec<usize> {
2941        let stride = tessellation + 1;
2942        let mut indices = Vec::new();
2943        for i in 0..tessellation {
2944            for j in 0..tessellation {
2945                let mut arr = [
2946                    i * stride + j,
2947                    (i + 1) * stride + j,
2948                    (i + 1) * stride + j + 1,
2949
2950                    i * stride + j,
2951                    (i + 1) * stride + j + 1,
2952                    i * stride + j + 1,
2953                ];
2954
2955                if is_mirrored {
2956                    arr.reverse();
2957                }
2958
2959                for ii in arr {
2960                    indices.push(ii + index_offset)
2961                }
2962            }
2963        }
2964        indices
2965    };
2966
2967    let create_patch_vertices = |patch: Vec<Vec3f>, tessellation: usize, is_mirrored: bool| -> Vec<Vertex3D> {
2968        let mut vertices = Vec::new();
2969        for i in 0..tessellation+1 {
2970            let u = i as f32 / tessellation as f32;
2971            for j in 0..tessellation+1 {
2972                let v = j as f32 / tessellation as f32;
2973
2974                // Perform four horizontal bezier interpolations between the control points of this patch.
2975                let p1 = cubic_interpolate(patch[0], patch[1], patch[2], patch[3], u);
2976                let p2 = cubic_interpolate(patch[4], patch[5], patch[6], patch[7], u);
2977                let p3 = cubic_interpolate(patch[8], patch[9], patch[10], patch[11], u);
2978                let p4 = cubic_interpolate(patch[12], patch[13], patch[14], patch[15], u);
2979
2980                // Perform a vertical interpolation between the results of the
2981                // previous horizontal interpolations, to compute the position.
2982                let pos = cubic_interpolate(p1, p2, p3, p4, v);
2983
2984                // Perform another four bezier interpolations between the control
2985                // points, but this time vertically rather than horizontally.
2986                let q1 = cubic_interpolate(patch[0], patch[4], patch[8], patch[12], v);
2987                let q2 = cubic_interpolate(patch[1], patch[5], patch[9], patch[13], v);
2988                let q3 = cubic_interpolate(patch[2], patch[6], patch[10], patch[14], v);
2989                let q4 = cubic_interpolate(patch[3], patch[7], patch[11], patch[15], v);
2990
2991                let mut tangent1 = cubic_tangent(p1, p2, p3, p4, v);
2992                let mut tangent2 = cubic_tangent(q1, q2, q3, q4, u);
2993                let mut normal = cross(tangent1, tangent2);
2994
2995                if is_mirrored {
2996                    normal = -normal;
2997                }
2998
2999                // this is a hack, because the bezier patches are not very well constructed
3000                if approx(normal, Vec3f::zero(), 0.001) {
3001                    normal = Vec3f::unit_y();
3002                    tangent1 = Vec3f::unit_x();
3003                    tangent2 = Vec3f::unit_z();
3004                    if pos.y < 0.0 {
3005                        normal *= -1.0;
3006                        tangent1 *= -1.0;
3007                    }
3008                }
3009
3010                let uv = Vec2f {
3011                    x: if is_mirrored { 1.0 - u } else { u },
3012                    y: v
3013                };
3014
3015                vertices.push(Vertex3D { 
3016                    position: pos, 
3017                    texcoord: uv, 
3018                    normal: normalize(normal), 
3019                    tangent: tangent1, 
3020                    bitangent: tangent2
3021                });
3022            }
3023        }
3024        vertices
3025    };
3026
3027    let tessalate_patch = |patch: &TeapotPatch, tesselation: usize, scale: Vec3f, is_mirrored: bool, index_offset: usize| -> (Vec<Vertex3D>, Vec<usize>) {
3028
3029        let mut patch_verts = Vec::new();
3030        for i in 0..16 {
3031            patch_verts.push(control_points[patch.indices[i] as usize] * scale * 2.0);
3032        } 
3033
3034        (create_patch_vertices(patch_verts, tesselation, is_mirrored), create_patch_indices(tesselation, is_mirrored, index_offset))
3035    };
3036
3037    let mut vertices = Vec::new();
3038    let mut indices = Vec::new();
3039    let mut lid_index_offset = 0;
3040    let mut spout_index_offset = 0;
3041
3042    for (ii, patch) in patches.iter().enumerate() {
3043        // grab the offset to the lid to join it later and the spount to fill in the gap
3044        if ii == 4 {
3045            lid_index_offset = vertices.len();
3046        }
3047        else if ii == 8 {
3048            spout_index_offset = vertices.len();
3049        }
3050
3051        let (patch_vertices, patch_indices) = tessalate_patch(patch, tessellation, Vec3f::one(), false, vertices.len());
3052        vertices.extend(patch_vertices);
3053        indices.extend(patch_indices);
3054
3055        let (patch_vertices, patch_indices) = tessalate_patch(patch, tessellation, vec3f(-1.0, 1.0, 1.0), true, vertices.len());
3056        vertices.extend(patch_vertices);
3057        indices.extend(patch_indices);
3058
3059        if patch.mirror_z {
3060            let (patch_vertices, patch_indices) = tessalate_patch(patch, tessellation, vec3f(1.0, 1.0, -1.0), true, vertices.len());
3061            vertices.extend(patch_vertices);
3062            indices.extend(patch_indices);
3063
3064            let (patch_vertices, patch_indices) = tessalate_patch(patch, tessellation, vec3f(-1.0, 1.0, -1.0), false, vertices.len());
3065            vertices.extend(patch_vertices);
3066            indices.extend(patch_indices);
3067        }
3068    }
3069
3070    // join the lid and the rim
3071    let stride = tessellation+1;
3072    for i in 0..tessellation {
3073        // a quad per tesselated patch
3074        for q in 0..4 {
3075            let v = i + q * stride;
3076            let lid = lid_index_offset + tessellation + v * stride;
3077            let rim = v * stride;
3078            let lid_next = lid_index_offset + tessellation + (v+1) * stride;
3079            let rim_next = (v+1) * stride;
3080
3081            // we need to flip te winding on the second 2 quadrants
3082            if q == 0 || q == 3 {
3083                indices.extend(vec![
3084                    rim,
3085                    lid,
3086                    lid_next,
3087                    rim,
3088                    lid_next,
3089                    rim_next
3090                ]);
3091            }
3092            else {
3093                indices.extend(vec![
3094                    rim,
3095                    lid_next,
3096                    lid,
3097                    rim,
3098                    rim_next,
3099                    lid_next
3100                ]);
3101            }
3102        }
3103    }
3104
3105    // plug a gap in the spout
3106    let (mut spout_verts, _) = tessalate_patch(&patches[8], tessellation, Vec3f::one(), false, vertices.len());
3107    let (spout_verts2, _) = tessalate_patch(&patches[8], tessellation, vec3f(-1.0, 1.0, 1.0), true, vertices.len());
3108    spout_verts.extend(spout_verts2);
3109
3110    // get a central vertex pos
3111    let mut ii = 0;
3112    let mut loop_count = 0;
3113    let mut spout_centre = Vec3f::zero();
3114    for v in spout_verts {
3115        ii += 1;
3116        if (ii-1) % stride != tessellation {
3117            continue;
3118        }
3119        spout_centre += v.position;
3120        loop_count += 1;
3121    }
3122    spout_centre /= loop_count as f32;
3123
3124    let spount_centre_index = vertices.len();
3125    vertices.push(Vertex3D{
3126        position: spout_centre,
3127        texcoord: normalize(spout_centre.xz()) * 0.5 + 0.5,
3128        normal: Vec3f::unit_y(),
3129        tangent: Vec3f::unit_x(),
3130        bitangent: Vec3f::unit_z()
3131    });
3132
3133    for i in 0..tessellation {
3134        for q in 0..2 {
3135            let v = i + q * stride;
3136            let vi = spout_index_offset + tessellation + v * stride;
3137            let vn = spout_index_offset + tessellation + (v+1) * stride;
3138            if q == 1 {
3139                indices.extend(vec![
3140                    vi,
3141                    spount_centre_index,
3142                    vn
3143                ])
3144            }
3145            else {
3146                indices.extend(vec![
3147                    vi,
3148                    vn,
3149                    spount_centre_index
3150                ])
3151            }
3152        }
3153    }
3154
3155    create_mesh_3d(dev, vertices, indices)
3156}