rev |
line source |
nuclear@6
|
1 #include <stdlib.h>
|
nuclear@8
|
2 #include <ctype.h>
|
nuclear@8
|
3 #include <string>
|
nuclear@6
|
4 #include "curvefile.h"
|
nuclear@6
|
5
|
nuclear@6
|
6 static bool save_curve(FILE *fp, const Curve *curve);
|
nuclear@6
|
7
|
nuclear@6
|
8 bool save_curves(const char *fname, const Curve * const *curves, int count)
|
nuclear@6
|
9 {
|
nuclear@6
|
10 FILE *fp = fopen(fname, "wb");
|
nuclear@6
|
11 if(!fp) return false;
|
nuclear@6
|
12
|
nuclear@6
|
13 bool res = save_curves(fp, curves, count);
|
nuclear@6
|
14 fclose(fp);
|
nuclear@6
|
15 return res;
|
nuclear@6
|
16 }
|
nuclear@6
|
17
|
nuclear@6
|
18 bool save_curves(FILE *fp, const Curve * const *curves, int count)
|
nuclear@6
|
19 {
|
nuclear@11
|
20 fprintf(fp, "GCURVES\n");
|
nuclear@6
|
21
|
nuclear@6
|
22 for(int i=0; i<count; i++) {
|
nuclear@6
|
23 if(!save_curve(fp, curves[i])) {
|
nuclear@6
|
24 return false;
|
nuclear@6
|
25 }
|
nuclear@6
|
26 }
|
nuclear@6
|
27 return true;
|
nuclear@6
|
28 }
|
nuclear@6
|
29
|
nuclear@6
|
30 static const char *curve_type_str(CurveType type)
|
nuclear@6
|
31 {
|
nuclear@6
|
32 switch(type) {
|
nuclear@6
|
33 case CURVE_LINEAR:
|
nuclear@6
|
34 return "polyline";
|
nuclear@6
|
35 case CURVE_HERMITE:
|
nuclear@6
|
36 return "hermite";
|
nuclear@6
|
37 case CURVE_BSPLINE:
|
nuclear@6
|
38 return "bspline";
|
nuclear@6
|
39 }
|
nuclear@6
|
40 abort();
|
nuclear@6
|
41 }
|
nuclear@6
|
42
|
nuclear@6
|
43 static bool save_curve(FILE *fp, const Curve *curve)
|
nuclear@6
|
44 {
|
nuclear@6
|
45 fprintf(fp, "curve {\n");
|
nuclear@6
|
46 fprintf(fp, " type %s\n", curve_type_str(curve->get_type()));
|
nuclear@6
|
47 fprintf(fp, " cpcount %d\n", curve->size());
|
nuclear@6
|
48 for(int i=0; i<curve->size(); i++) {
|
nuclear@6
|
49 Vector3 cp = curve->get_homo_point(i);
|
nuclear@6
|
50 fprintf(fp, " cp %g %g %g\n", cp.x, cp.y, cp.z);
|
nuclear@6
|
51 }
|
nuclear@6
|
52 fprintf(fp, "}\n");
|
nuclear@6
|
53 return true;
|
nuclear@6
|
54 }
|
nuclear@6
|
55
|
nuclear@10
|
56 std::list<Curve*> load_curves(const char *fname)
|
nuclear@6
|
57 {
|
nuclear@10
|
58 std::list<Curve*> res;
|
nuclear@8
|
59 FILE *fp = fopen(fname, "r");
|
nuclear@10
|
60 if(!fp) return res;
|
nuclear@6
|
61
|
nuclear@10
|
62 res = load_curves(fp);
|
nuclear@6
|
63 fclose(fp);
|
nuclear@6
|
64 return res;
|
nuclear@6
|
65 }
|
nuclear@6
|
66
|
nuclear@8
|
67 static std::string next_token(FILE *fp)
|
nuclear@8
|
68 {
|
nuclear@8
|
69 std::string s;
|
nuclear@8
|
70 int c;
|
nuclear@11
|
71 while((c = fgetc(fp)) != -1) {
|
nuclear@11
|
72 if(!isspace(c)) {
|
nuclear@11
|
73 ungetc(c, fp);
|
nuclear@11
|
74 break;
|
nuclear@11
|
75 }
|
nuclear@11
|
76 }
|
nuclear@11
|
77
|
nuclear@8
|
78 if(feof(fp)) return s;
|
nuclear@11
|
79 while((c = fgetc(fp)) != -1) {
|
nuclear@11
|
80 if(isspace(c)) {
|
nuclear@11
|
81 ungetc(c, fp);
|
nuclear@11
|
82 break;
|
nuclear@11
|
83 }
|
nuclear@8
|
84 s.push_back(c);
|
nuclear@8
|
85 }
|
nuclear@11
|
86
|
nuclear@11
|
87 printf("TOKEN: \"%s\"\n", s.c_str());
|
nuclear@8
|
88 return s;
|
nuclear@8
|
89 }
|
nuclear@8
|
90
|
nuclear@8
|
91 static bool expect_str(FILE *fp, const char *s)
|
nuclear@8
|
92 {
|
nuclear@8
|
93 std::string tok = next_token(fp);
|
nuclear@8
|
94 if(tok != std::string(s)) {
|
nuclear@11
|
95 if(tok.empty() && feof(fp)) {
|
nuclear@8
|
96 fprintf(stderr, "expected: %s\n", s);
|
nuclear@8
|
97 }
|
nuclear@8
|
98 return false;
|
nuclear@8
|
99 }
|
nuclear@8
|
100 return true;
|
nuclear@8
|
101 }
|
nuclear@8
|
102
|
nuclear@8
|
103 static bool expect_float(FILE *fp, float *ret)
|
nuclear@8
|
104 {
|
nuclear@8
|
105 std::string tok = next_token(fp);
|
nuclear@8
|
106 const char *cs = tok.c_str();
|
nuclear@8
|
107 char *endp;
|
nuclear@8
|
108 *ret = strtod(cs, &endp);
|
nuclear@8
|
109 if(endp != cs + tok.length()) {
|
nuclear@8
|
110 if(!(tok.empty() && feof(fp))) {
|
nuclear@8
|
111 fprintf(stderr, "number expected\n");
|
nuclear@8
|
112 }
|
nuclear@8
|
113 return false;
|
nuclear@8
|
114 }
|
nuclear@8
|
115 return true;
|
nuclear@8
|
116 }
|
nuclear@8
|
117
|
nuclear@8
|
118 static bool expect_int(FILE *fp, int *ret)
|
nuclear@8
|
119 {
|
nuclear@8
|
120 std::string tok = next_token(fp);
|
nuclear@8
|
121 const char *cs = tok.c_str();
|
nuclear@8
|
122 char *endp;
|
nuclear@8
|
123 *ret = strtol(cs, &endp, 0);
|
nuclear@8
|
124 if(endp != cs + tok.length()) {
|
nuclear@8
|
125 if(!(tok.empty() && feof(fp))) {
|
nuclear@8
|
126 fprintf(stderr, "integer expected\n");
|
nuclear@8
|
127 }
|
nuclear@8
|
128 return false;
|
nuclear@8
|
129 }
|
nuclear@8
|
130 return true;
|
nuclear@8
|
131 }
|
nuclear@8
|
132
|
nuclear@8
|
133 static Curve *curve_block(FILE *fp)
|
nuclear@8
|
134 {
|
nuclear@8
|
135 if(!expect_str(fp, "curve") || !expect_str(fp, "{")) {
|
nuclear@8
|
136 return 0;
|
nuclear@8
|
137 }
|
nuclear@8
|
138
|
nuclear@8
|
139 Curve *curve = new Curve;
|
nuclear@8
|
140 int cpcount = -1;
|
nuclear@8
|
141 std::string tok;
|
nuclear@8
|
142 while(!(tok = next_token(fp)).empty() && tok != "}") {
|
nuclear@8
|
143 if(tok == "cpcount") {
|
nuclear@8
|
144 if(cpcount != -1 || !expect_int(fp, &cpcount) || cpcount <= 0) {
|
nuclear@8
|
145 goto err;
|
nuclear@8
|
146 }
|
nuclear@8
|
147 } else if(tok == "type") {
|
nuclear@8
|
148 tok = next_token(fp);
|
nuclear@8
|
149 if(tok == "polyline") {
|
nuclear@8
|
150 curve->set_type(CURVE_LINEAR);
|
nuclear@8
|
151 } else if(tok == "hermite") {
|
nuclear@8
|
152 curve->set_type(CURVE_HERMITE);
|
nuclear@8
|
153 } else if(tok == "bspline") {
|
nuclear@8
|
154 curve->set_type(CURVE_BSPLINE);
|
nuclear@8
|
155 } else {
|
nuclear@8
|
156 goto err;
|
nuclear@8
|
157 }
|
nuclear@8
|
158 } else {
|
nuclear@11
|
159 if(tok != "cp") {
|
nuclear@8
|
160 goto err;
|
nuclear@8
|
161 }
|
nuclear@8
|
162 Vector3 cp;
|
nuclear@8
|
163 for(int i=0; i<3; i++) {
|
nuclear@8
|
164 if(!expect_float(fp, &cp[i])) {
|
nuclear@8
|
165 goto err;
|
nuclear@8
|
166 }
|
nuclear@8
|
167 }
|
nuclear@8
|
168 curve->add_point(Vector2(cp.x, cp.y), cp.z);
|
nuclear@8
|
169 }
|
nuclear@8
|
170 }
|
nuclear@8
|
171
|
nuclear@8
|
172 if(curve->size() != cpcount) {
|
nuclear@8
|
173 fprintf(stderr, "warning: curve cpcount was %d, but read %d control points\n", cpcount, curve->size());
|
nuclear@8
|
174 }
|
nuclear@8
|
175
|
nuclear@8
|
176 return curve;
|
nuclear@8
|
177 err:
|
nuclear@8
|
178 fprintf(stderr, "failed to parse curve block\n");
|
nuclear@8
|
179 delete curve;
|
nuclear@8
|
180 return 0;
|
nuclear@8
|
181 }
|
nuclear@8
|
182
|
nuclear@10
|
183 std::list<Curve*> load_curves(FILE *fp)
|
nuclear@6
|
184 {
|
nuclear@10
|
185 std::list<Curve*> curves;
|
nuclear@8
|
186 if(!expect_str(fp, "GCURVES")) {
|
nuclear@8
|
187 fprintf(stderr, "load_curves: failed to load, invalid file format\n");
|
nuclear@10
|
188 return curves;
|
nuclear@8
|
189 }
|
nuclear@8
|
190
|
nuclear@8
|
191 Curve *curve;
|
nuclear@8
|
192 while((curve = curve_block(fp))) {
|
nuclear@8
|
193 curves.push_back(curve);
|
nuclear@8
|
194 }
|
nuclear@8
|
195
|
nuclear@8
|
196 int ncurves = (int)curves.size();
|
nuclear@8
|
197 if(!feof(fp)) {
|
nuclear@10
|
198 std::list<Curve*>::iterator it = curves.begin();
|
nuclear@10
|
199 while(it != curves.end()) {
|
nuclear@10
|
200 delete *it++;
|
nuclear@8
|
201 }
|
nuclear@10
|
202 return curves;
|
nuclear@8
|
203 }
|
nuclear@8
|
204
|
nuclear@10
|
205 return curves;
|
nuclear@6
|
206 }
|
nuclear@6
|
207
|