1use std::{env, path::Path};
2
3use mesh::Vertex;
4use proc_macro::TokenStream;
5use quote::quote;
6use read_file::read_lines;
7use syn::{LitStr, parse_macro_input};
8
9mod mesh;
10mod read_file;
11
12#[proc_macro]
13pub fn obj_2_rust(input: TokenStream) -> TokenStream {
14 let input = parse_macro_input!(input as LitStr);
15 let file_name = input.value();
16
17 let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
18 let manifest_path = Path::new(&manifest_dir);
19 let file_path = manifest_path.with_file_name(file_name);
20 let lines = read_lines(file_path).unwrap();
21
22 let mut vertices: Vec<[f32; 3]> = Vec::new();
23 let mut normals: Vec<[f32; 3]> = Vec::new();
24 let mut uv_coords: Vec<[f32; 2]> = Vec::new();
25
26 let mut model_vertices: Vec<Vertex> = Vec::new();
27
28 let mut indices: Vec<u32> = Vec::new();
29
30 for line in lines.map_while(Result::ok) {
31 let line_split = line.split_whitespace().collect::<Vec<_>>();
32
33 if line_split.is_empty() {
34 continue;
35 }
36
37 match line_split[0] {
38 "o" => {
39 }
41 "v" => {
43 vertices.push([
44 line_split[1].parse::<f32>().unwrap(),
45 line_split[2].parse::<f32>().unwrap(),
46 line_split[3].parse::<f32>().unwrap(),
47 ]);
48 }
49 "vt" => {
51 uv_coords.push([
52 1.0 - line_split[1].parse::<f32>().unwrap(),
53 1.0 - line_split[2].parse::<f32>().unwrap(),
54 ]);
55 }
56 "vn" => {
58 normals.push([
59 line_split[1].parse::<f32>().unwrap(),
60 line_split[2].parse::<f32>().unwrap(),
61 line_split[3].parse::<f32>().unwrap(),
62 ]);
63 }
64 "f" => {
66 for vertex_info in line_split[1..3].iter() {
68 let vertex_info_split = vertex_info.split('/').collect::<Vec<_>>();
69
70 let (vertex_index, uv_index, normal_index) = (
72 vertex_info_split[0].parse::<usize>().unwrap() - 1,
73 vertex_info_split[1].parse::<usize>().unwrap() - 1,
74 vertex_info_split[2].parse::<usize>().unwrap() - 1,
75 );
76
77 model_vertices.push(Vertex {
78 position: vertices[vertex_index],
79 normal: normals[normal_index],
80 uv: uv_coords[uv_index],
81 });
82
83 indices.push(model_vertices.len() as u32 - 1);
84 }
85 }
86 _ => {}
87 }
88 }
89
90 let vertex_tokens = model_vertices
91 .iter()
92 .map(|vertex| {
93 let position = &vertex.position;
94 let normal = &vertex.normal;
95 let uv = &vertex.uv;
96
97 quote! {
98 (#(#position),*, #(#normal),*, #(#uv),*)
99 }
100 })
101 .collect::<Vec<_>>();
102
103 let index_tokens = indices
104 .iter()
105 .map(|index| {
106 let model_index = &index;
107
108 quote! {
109 #model_index
110 }
111 })
112 .collect::<Vec<_>>();
113
114 let size = index_tokens.len();
115
116 let combined = quote! {
117 ([#(#vertex_tokens),*], [#(#index_tokens),*], #size)
118 };
119
120 combined.into()
121}