@@ -119,7 +119,7 @@ pub fn subdivide_triangle(t0: &Vertex3D, t1: &Vertex3D, t2: &Vertex3D, order: u3
119119}
120120
121121/// Utility to create faceted meshes with varying index sizes depending on the index requirements
122- fn create_mesh_3d < D : gfx:: Device > ( dev : & mut D , vertices : Vec < Vertex3D > , indices : Vec < usize > ) -> pmfx:: Mesh < D > {
122+ pub fn create_mesh_3d < D : gfx:: Device > ( dev : & mut D , vertices : Vec < Vertex3D > , indices : Vec < usize > ) -> pmfx:: Mesh < D > {
123123 let max_index = vertices. len ( ) ;
124124 let index_buffer = if max_index > 65535 {
125125 let mut indices32 : Vec < u32 > = Vec :: new ( ) ;
@@ -180,7 +180,7 @@ fn create_mesh_3d<D: gfx::Device>(dev: &mut D, vertices: Vec<Vertex3D>, indices:
180180}
181181
182182/// Utility to create a facent mesh which will have hard edged normals and automatically generate and index buffer from vertices
183- fn create_faceted_mesh_3d < D : gfx:: Device > ( dev : & mut D , vertices : Vec < Vertex3D > ) -> pmfx:: Mesh < D > {
183+ pub fn create_faceted_mesh_3d < D : gfx:: Device > ( dev : & mut D , vertices : Vec < Vertex3D > ) -> pmfx:: Mesh < D > {
184184 let mut indices = Vec :: new ( ) ;
185185 for i in 0 ..vertices. len ( ) {
186186 indices. push ( i) ;
@@ -2764,6 +2764,316 @@ pub fn create_tube_prism_mesh<D: gfx::Device>(
27642764 }
27652765}
27662766
2767+ /// Create an `segments` sided prism tube where the exterior is extruded out to a cube, if `smooth` the prism is a cylinder with smooth normals
2768+ /// 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
2769+ /// use thickness to control the size of the inner hole
2770+ #[ allow( clippy:: too_many_arguments) ]
2771+ pub fn create_cube_tube_prism_mesh < D : gfx:: Device > (
2772+ dev : & mut D , segments : usize , trunc_start : usize , trunc_end : usize , smooth : bool , cap : bool , height : f32 , thickness : f32 , taper : f32 ) -> pmfx:: Mesh < D > {
2773+ let axis = Vec3f :: unit_y ( ) ;
2774+ let right = Vec3f :: unit_x ( ) ;
2775+ let up = cross ( axis, right) ;
2776+ let right = cross ( axis, up) ;
2777+
2778+ // add an extra segment at the end to make uv's wrap nicely
2779+ let vertex_segments = segments + 1 ;
2780+
2781+ let prism_vertices = |radius : f32 , flip : f32 | -> ( Vec < Vertex3D > , Vec < Vertex3D > ) {
2782+ let mut vertices = Vec :: new ( ) ;
2783+ let mut cap_vertices = Vec :: new ( ) ;
2784+ let mut points = Vec :: new ( ) ;
2785+ let mut bottom_points = Vec :: new ( ) ;
2786+ let mut top_points = Vec :: new ( ) ;
2787+ let mut tangents = Vec :: new ( ) ;
2788+
2789+ // rotate around up axis and extract some data we can lookup to build vb and ib
2790+ let mut angle = 0.0 ;
2791+ let angle_step = f32:: two_pi ( ) / segments as f32 ;
2792+ for i in 0 ..vertex_segments {
2793+ // current
2794+ let mut x = cos ( angle) ;
2795+ let mut y = -sin ( angle) ;
2796+ let v1 = right * x + up * y;
2797+
2798+ // next
2799+ angle += angle_step;
2800+ x = cos ( angle) ;
2801+ y = -sin ( angle) ;
2802+ let v2 = right * x + up * y;
2803+
2804+ points. push ( v1 * radius) ;
2805+ tangents. push ( v2 - v1) ;
2806+
2807+ bottom_points. push ( points[ i] - Vec3f :: unit_y ( ) * height) ;
2808+ top_points. push ( points[ i] * taper + Vec3f :: unit_y ( ) * height) ;
2809+ }
2810+
2811+ // bottom ring
2812+ for i in 0 ..vertex_segments {
2813+ let u = 0.5 + atan2 ( bottom_points[ i] . z , bottom_points[ i] . x ) / f32:: two_pi ( ) ;
2814+ let u = if i == segments { 0.0 } else { u } ;
2815+ let bt = cross ( tangents[ i] , points[ i] ) ;
2816+ vertices. push ( Vertex3D {
2817+ position : bottom_points[ i] ,
2818+ normal : points[ i] * flip,
2819+ tangent : tangents[ i] ,
2820+ bitangent : bt,
2821+ texcoord : Vec2f :: new ( u * 3.0 , 0.0 )
2822+ } ) ;
2823+ }
2824+
2825+ // top ring
2826+ for i in 0 ..vertex_segments {
2827+ let u = 0.5 + atan2 ( top_points[ i] . z , top_points[ i] . x ) / f32:: two_pi ( ) ;
2828+ let u = if i == segments { 0.0 } else { u } ;
2829+ let bt = cross ( tangents[ i] , points[ i] ) ;
2830+ vertices. push ( Vertex3D {
2831+ position : top_points[ i] ,
2832+ normal : points[ i] * flip,
2833+ tangent : tangents[ i] ,
2834+ bitangent : bt,
2835+ texcoord : Vec2f :: new ( u * 3.0 , 1.0 )
2836+ } ) ;
2837+ }
2838+
2839+ // bottom cap
2840+ for point in bottom_points. iter ( ) . take ( vertex_segments) {
2841+ cap_vertices. push ( Vertex3D {
2842+ position : point. xyz ( ) ,
2843+ normal : -Vec3f :: unit_y ( ) ,
2844+ tangent : Vec3f :: unit_x ( ) ,
2845+ bitangent : Vec3f :: unit_z ( ) ,
2846+ texcoord : point. xz ( ) * 0.5 + 0.5
2847+ } ) ;
2848+ }
2849+
2850+ // top cap
2851+ for point in top_points. iter ( ) . take ( vertex_segments) {
2852+ cap_vertices. push ( Vertex3D {
2853+ position : point. xyz ( ) ,
2854+ normal : Vec3f :: unit_y ( ) ,
2855+ tangent : Vec3f :: unit_x ( ) ,
2856+ bitangent : Vec3f :: unit_z ( ) ,
2857+ texcoord : point. xz ( ) * 0.5 + 0.5
2858+ } ) ;
2859+ }
2860+
2861+ ( vertices, cap_vertices)
2862+ } ;
2863+
2864+ let end_cap = |loop_start : usize , v : & Vec < Vertex3D > , inner_offset : usize , flip : f32 | -> Vec < Vertex3D > {
2865+ // start
2866+ let bottom = loop_start;
2867+ let top = loop_start + vertex_segments;
2868+ let inner_bottom = bottom + inner_offset;
2869+ let inner_top = top + inner_offset;
2870+
2871+ let mut verts = vec ! [
2872+ v[ bottom] . clone( ) ,
2873+ v[ top] . clone( ) ,
2874+ v[ inner_bottom] . clone( ) ,
2875+ v[ inner_top] . clone( ) ,
2876+ ] ;
2877+
2878+ let b = normalize ( verts[ 1 ] . position - verts[ 0 ] . position ) ;
2879+ let t = normalize ( verts[ 2 ] . position - verts[ 0 ] . position ) ;
2880+ let n = cross ( b, t) * flip;
2881+
2882+ for v in & mut verts {
2883+ v. normal = n;
2884+ v. tangent = t;
2885+ v. bitangent = b;
2886+ }
2887+
2888+ verts[ 0 ] . texcoord = Vec2f :: zero ( ) ;
2889+ verts[ 1 ] . texcoord = vec2f ( 0.0 , 1.0 ) ;
2890+ verts[ 2 ] . texcoord = vec2f ( 1.0 - thickness, 0.0 ) ;
2891+ verts[ 3 ] . texcoord = vec2f ( 1.0 - thickness, 1.0 ) ;
2892+
2893+ verts
2894+ } ;
2895+
2896+ let ( mut outer_vertices, mut outer_cap_vertices) = prism_vertices ( 1.0 , 1.0 ) ;
2897+ let ( inner_vertices, inner_cap_vertices) = prism_vertices ( thickness, -1.0 ) ;
2898+
2899+ // project outer vertices onto cube, normals / tangent also need flattening
2900+ for v in & mut outer_vertices {
2901+ // keep y
2902+ let y = v. position . y ;
2903+
2904+ // normalize xz onto cube
2905+ v. position . y = 0.0 ;
2906+ v. position = chebyshev_normalize ( v. position ) ;
2907+
2908+ // reset y
2909+ v. position . y = y;
2910+ }
2911+
2912+ // project outer cap vertices onto cube, normals stay the same
2913+ for v in & mut outer_cap_vertices {
2914+ // keep y
2915+ let y = v. position . y ;
2916+
2917+ // normalize xz onto cube
2918+ v. position . y = 0.0 ;
2919+ v. position = chebyshev_normalize ( v. position ) ;
2920+
2921+ // reset y
2922+ v. position . y = y;
2923+ }
2924+
2925+ let mut indices = Vec :: new ( ) ;
2926+ let mut vertices = Vec :: new ( ) ;
2927+
2928+ // 2 tris per segment for outer (always faceted)
2929+ for i in trunc_start..trunc_end {
2930+ let bottom = i;
2931+ let top = i + vertex_segments;
2932+ let next = i + 1 ;
2933+ let top_next = i + 1 + vertex_segments;
2934+
2935+ let face_index = vertices. len ( ) ;
2936+ vertices. extend ( vec ! [
2937+ outer_vertices[ bottom] . clone( ) ,
2938+ outer_vertices[ top] . clone( ) ,
2939+ outer_vertices[ next] . clone( ) ,
2940+ outer_vertices[ top] . clone( ) ,
2941+ outer_vertices[ top_next] . clone( ) ,
2942+ outer_vertices[ next] . clone( )
2943+ ] ) ;
2944+
2945+ let v = face_index;
2946+ let n = get_triangle_normal (
2947+ vertices[ v] . position ,
2948+ vertices[ v+2 ] . position ,
2949+ vertices[ v+1 ] . position
2950+ ) ;
2951+
2952+ // set hard face normals
2953+ for vertex in vertices. iter_mut ( ) . skip ( face_index) {
2954+ vertex. normal = n;
2955+ }
2956+ }
2957+
2958+ // faceted inner
2959+ if !smooth {
2960+ for i in trunc_start..trunc_end {
2961+ let bottom = i;
2962+ let top = i + vertex_segments;
2963+ let next = i + 1 ;
2964+ let top_next = i + 1 + vertex_segments;
2965+
2966+ let face_index = vertices. len ( ) ;
2967+ vertices. extend ( vec ! [
2968+ inner_vertices[ bottom] . clone( ) ,
2969+ inner_vertices[ next] . clone( ) ,
2970+ inner_vertices[ top] . clone( ) ,
2971+ inner_vertices[ top] . clone( ) ,
2972+ inner_vertices[ next] . clone( ) ,
2973+ inner_vertices[ top_next] . clone( )
2974+ ] ) ;
2975+
2976+ let v = face_index;
2977+ let n = get_triangle_normal (
2978+ vertices[ v] . position ,
2979+ vertices[ v+2 ] . position ,
2980+ vertices[ v+1 ] . position ,
2981+ ) ;
2982+
2983+ // set hard face normals
2984+ for vertex in vertices. iter_mut ( ) . skip ( face_index) {
2985+ vertex. normal = n;
2986+ }
2987+ }
2988+ }
2989+
2990+ // top / bottom cap
2991+ if cap {
2992+ for i in trunc_start..trunc_end {
2993+ let bottom = i;
2994+ let top = i + vertex_segments;
2995+ let next = i + 1 ;
2996+ let top_next = i + 1 + vertex_segments;
2997+
2998+ vertices. extend ( vec ! [
2999+ outer_cap_vertices[ top] . clone( ) ,
3000+ inner_cap_vertices[ top] . clone( ) ,
3001+ inner_cap_vertices[ top_next] . clone( ) ,
3002+ outer_cap_vertices[ top] . clone( ) ,
3003+ inner_cap_vertices[ top_next] . clone( ) ,
3004+ outer_cap_vertices[ top_next] . clone( )
3005+ ] ) ;
3006+
3007+ vertices. extend ( vec ! [
3008+ inner_cap_vertices[ bottom] . clone( ) ,
3009+ outer_cap_vertices[ bottom] . clone( ) ,
3010+ outer_cap_vertices[ next] . clone( ) ,
3011+ inner_cap_vertices[ bottom] . clone( ) ,
3012+ outer_cap_vertices[ next] . clone( ) ,
3013+ inner_cap_vertices[ next] . clone( )
3014+ ] ) ;
3015+ }
3016+ }
3017+
3018+ // end cap
3019+ if trunc_start != 0 || trunc_end != segments {
3020+ let mut cap_vertices = outer_vertices. to_vec ( ) ;
3021+ let inner_offset = cap_vertices. len ( ) ;
3022+ cap_vertices. extend ( inner_vertices. clone ( ) ) ;
3023+
3024+ let start_verts = end_cap ( trunc_start, & cap_vertices, inner_offset, 1.0 ) ;
3025+ vertices. extend ( vec ! [
3026+ start_verts[ 0 ] . clone( ) ,
3027+ start_verts[ 3 ] . clone( ) ,
3028+ start_verts[ 1 ] . clone( ) ,
3029+ start_verts[ 0 ] . clone( ) ,
3030+ start_verts[ 2 ] . clone( ) ,
3031+ start_verts[ 3 ] . clone( ) ,
3032+ ] ) ;
3033+
3034+ let end_verts = end_cap ( trunc_end, & cap_vertices, inner_offset, -1.0 ) ;
3035+ vertices. extend ( vec ! [
3036+ end_verts[ 0 ] . clone( ) ,
3037+ end_verts[ 1 ] . clone( ) ,
3038+ end_verts[ 3 ] . clone( ) ,
3039+ end_verts[ 0 ] . clone( ) ,
3040+ end_verts[ 3 ] . clone( ) ,
3041+ end_verts[ 2 ] . clone( ) ,
3042+ ] ) ;
3043+ }
3044+
3045+ // create facet indices
3046+ for i in 0 ..vertices. len ( ) {
3047+ indices. push ( i) ;
3048+ }
3049+
3050+ // smooth inner appeneded
3051+ if smooth {
3052+ let inner_offset = vertices. len ( ) ;
3053+ vertices. extend ( inner_vertices) ;
3054+
3055+ // sides
3056+ for i in trunc_start..trunc_end {
3057+ let bottom = i;
3058+ let top = i + vertex_segments;
3059+ let next = i + 1 ;
3060+ let top_next = i + 1 + vertex_segments;
3061+
3062+ // inner
3063+ indices. extend ( vec ! [
3064+ bottom + inner_offset,
3065+ next + inner_offset,
3066+ top + inner_offset,
3067+ top + inner_offset,
3068+ next + inner_offset,
3069+ top_next + inner_offset,
3070+ ] ) ;
3071+ }
3072+ }
3073+
3074+ create_mesh_3d ( dev, vertices, indices)
3075+ }
3076+
27673077fn cubic_interpolate ( p1 : Vec3f , p2 : Vec3f , p3 : Vec3f , p4 : Vec3f , t : f32 ) -> Vec3f {
27683078 p1 * ( 1.0 - t) * ( 1.0 - t) * ( 1.0 - t) +
27693079 p2 * 3.0 * t * ( 1.0 - t) * ( 1.0 - t) +
0 commit comments