1 module grape.file;
2 
3 import std.algorithm;
4 import std.array;
5 import std.stdio;
6 import std.conv;
7 //import std.string;
8 
9 import grape.math;
10 // obj hdr
11 /**
12  * ファイル操作をするクラス
13  *
14  * TODO:
15  * Rename
16  */
17 class FileHdr {
18   public:
19     /**
20      * objファイルから頂点を読み込む
21      *
22      * objファイルを読み込んで、頂点をVec3[]の配列にして返します。
23      * file: objファイル名
24      */
25     Vec3[] make_vertices(in string file) {
26       Vec3[] vertices;
27       auto f = File(file, "r");
28 
29       float[] coord;
30       foreach (string line; lines(f)) {
31         if (line.split[0] != "v") continue;
32         foreach (float value; line.split[1..$].map!(x => to!(float)(x)).array) {
33           coord ~= value;
34         }
35         vertices ~= Vec3(coord);
36         coord.length = 0;
37       }
38 
39       return vertices;
40     }
41 
42     /**
43      * objファイルから法線を読み込む
44      *
45      * objを読み込んで、法線をVec3[]の配列にして返します。
46      * file: objファイル名
47      */
48     // FIXME listの最後にnanが入ってる。
49     Vec3[] make_normals(in string file) {
50       Vec3[] list;
51       float[][] randomNormal;
52       float[] normal;
53       auto f = File(file, "r");
54       // optimize create normal
55       auto memorize = delegate void() {
56       };
57 
58       foreach (string line; lines(f)) {
59         if (line.split[0] == "vn") {
60           randomNormal ~= [line.split[1..$].map!(x => to!(float)(x)).array];
61         }
62 
63         if (line.split[0] == "f" ) {
64           if (normal.length == 0)
65             normal.length = randomNormal.length * 3;
66           foreach (index; line.split[1..$].map!(x => x.split("//")).map!(y => [to!(int)(y[0])-1, to!(int)(y[1])-1])) {
67             for (int i; i<3; ++i)
68               normal[index[0]*3+i] = randomNormal[index[1]][i];
69           }
70         }
71       }
72 
73       for(int i; i<normal.length/3; ++i) {
74         list ~= Vec3([normal[i*3], normal[i*3+1], normal[i*3+2]]);
75       }
76 
77       return list;
78     }
79 
80 
81     /**
82      * objファイルからインデックスを読み込む
83      *
84      * objを読み込んで、インデックスをint[]の配列にして返します。
85      * file: objファイル名
86      */
87     int[] make_indices(in string file) {
88       int[] t;
89       auto buf = appender(t);
90       auto f = File(file, "r");
91 
92       foreach (string line; lines(f)) {
93         if (line.split[0] != "f") continue;
94 
95         string[] u = line.split[1..$];
96         auto k = u.map!(x => x.split("//"));
97         int[] index = (k[0].length < 2) ?
98                        u.map!(x => to!(int)(x)-1).array :
99                        k.map!(x => x[0]).map!(y => to!(int)(y)-1).array;
100 
101         buf.put([index[0], index[1], index[2]]);
102         if (index.length > 3)
103           buf.put([index[0], index[3], index[2]]);
104       }
105 
106       return buf.data;
107     }
108 }
109