1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
|
// A module for reading simple obj files with groups.
// Authors: Jens Schwaiger and John Bowman
//
// Here simple means that :
//
// 1) all vertex statements should come before the face statements;
//
// 2) face informations with respect to texture and/or normal vectors are
// ignored;
//
// 3) face statements only contain positive numbers(no relative positions).
//
// The reading process only takes into account lines starting with "v" or
// "f" or "g"(group).
import three;
struct obj {
surface s;
material[] surfacepen;
pen[] meshpen;
path3[][] read(string datafile, bool verbose=false) {
file in=input(datafile).word().line();
triple[] vert;
path3[][] g;
g[0]=new path3[] ;
string[] G;
void Vertex(real x,real y ,real z) {vert.push((x,y,z));}
void Face(int[] vertnr, int groupnr) {
guide3 gh;
for(int i=0; i < vertnr.length; ++i)
gh=gh--vert[vertnr[i]-1];
gh=gh--cycle;
g[groupnr].push(gh);
}
if(verbose) write("Reading data from "+datafile+".");
int groupnr;
while(true) {
string[] str=in;
if(str.length == 0) break;
str=sequence(new string(int i) {return split(str[i],"/")[0];},str.length);
if(str[0] == "g" && str.length > 1) {
int tst=find(G == str[1]);
if(tst == -1) {
G.push(str[1]);
groupnr=G.length-1;
g[groupnr]=new path3[] ;
}
if(tst > -1) groupnr=tst;
}
if(str[0] == "v") Vertex((real) str[1],(real) str[2],(real) str[3]);
if(str[0] == "f") {
int[] vertnr;
for(int i=1; i < str.length; ++i) vertnr[i-1]=(int) str[i];
Face(vertnr,groupnr);
}
if(eof(in)) break;
}
close(in);
if(verbose) {
write("Number of groups: ",(string) G.length);
write("Groups and their names");
write(G);
write("Reading done.");
write("Number of faces contained in the groups: ");
for(int j=0; j < g.length; ++j)
write(G[j],": ",(string) g[j].length);
}
return g;
}
void operator init(path3[][] g, material[] surfacepen, pen[] meshpen) {
for(int i=0; i < g.length; ++i) {
path3[] gi=g[i];
for(int j=0; j < gi.length; ++j) {
// Treat all faces as planar to avoid subdivision cracks.
surface sij=surface(gi[j],planar=true);
s.append(sij);
this.surfacepen.append(array(sij.s.length,surfacepen[i]));
this.meshpen.append(array(sij.s.length,meshpen[i]));
}
}
}
void operator init(string datafile, bool verbose=false,
material[] surfacepen, pen[] meshpen=nullpens) {
operator init(read(datafile,verbose),surfacepen,meshpen);
}
void operator init(string datafile, bool verbose=false,
material surfacepen, pen meshpen=nullpen) {
material[] surfacepen={surfacepen};
pen[] meshpen={meshpen};
surfacepen.cyclic=true;
meshpen.cyclic=true;
operator init(read(datafile,verbose),surfacepen,meshpen);
}
}
void draw(picture pic=currentpicture, obj o, light light=currentlight)
{
draw(pic,o.s,o.surfacepen,o.meshpen,light);
}
|