ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/convertobj.c
Revision: 2.4
Committed: Thu Apr 15 23:51:04 2021 UTC (3 years, 1 month ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.3: +108 -6 lines
Log Message:
feat(genbox,robjutil): Added Radiance normal smoothing support to wfobj library

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: convertobj.c,v 2.3 2020/04/23 22:35:27 greg Exp $";
3 #endif
4 /*
5 * convertobj.c
6 *
7 * Convert .OBJ scene to Radiance
8 *
9 * Created by Greg Ward on Thu Apr 22 2004.
10 */
11
12 #include "paths.h"
13 #include "fvect.h"
14 #include "tmesh.h"
15 #include "rterror.h"
16 #include "objutil.h"
17
18 #define TEXNAME "T-nor"
19
20 static int fcnt = 0; /* face output counter */
21
22 /* Callback for face smoothing detection */
23 static int
24 checksmooth(Scene *sc, Face *f, void *ptr)
25 {
26 int nrev = 0;
27 Normal fnrm;
28 int i;
29
30 f->flags &= ~FACE_RESERVED; /* using reserved flag */
31
32 for (i = f->nv; i--; )
33 if (f->v[i].nid < 0)
34 return(0); /* missing normal */
35
36 if (faceArea(sc, f, fnrm) == 0) /* degenerate?? */
37 return(0);
38 /* check each normal */
39 for (i = f->nv; i--; ) {
40 float *tnrm = sc->norm[f->v[i].nid];
41 double dprod = DOT(tnrm, fnrm);
42 if (dprod >= COSTOL) /* this one agrees? */
43 continue;
44 if (dprod > -COSTOL) /* active smoothing? */
45 break;
46 ++nrev; /* count opposite face normal */
47 }
48 if ((i < 0) & !nrev) /* all normals agree w/ face? */
49 return(0);
50 if (nrev == f->nv) { /* all reversed? */
51 for (i = f->nv; i--; ) /* remove normal indices */
52 f->v[i].nid = -1;
53 for (i = f->nv/2; i--; ) { /* and swap others around */
54 int j = f->nv-1 - i;
55 int vi = f->v[i].vid;
56 int ti = f->v[i].tid;
57 f->v[i].vid = f->v[j].vid;
58 f->v[i].tid = f->v[j].tid;
59 f->v[j].vid = vi;
60 f->v[j].tid = ti;
61 }
62 return(0);
63 }
64 f->flags |= FACE_RESERVED; /* else we got one to smooth */
65 return(1);
66 }
67
68 /* Callback to write out smoothed Radiance triangle */
69 static int
70 trismooth(Scene *sc, Face *f, void *ptr)
71 {
72 FILE *fp = (FILE *)ptr;
73 BARYCCM bcm;
74 RREAL ncoor[3][3];
75 int i;
76
77 if (f->nv != 3)
78 return(0); /* should never happen */
79 if (sizeof(sc->vert[0].p) != sizeof(FVECT))
80 error(INTERNAL, "Code error in trismooth()");
81 if (comp_baryc(&bcm, sc->vert[f->v[0].vid].p, sc->vert[f->v[1].vid].p,
82 sc->vert[f->v[2].vid].p) < 0)
83 return(0); /* degenerate?? */
84
85 for (i = 3; i--; ) { /* assign BC normals */
86 float *tnrm = sc->norm[f->v[i].nid];
87 ncoor[0][i] = tnrm[0];
88 ncoor[1][i] = tnrm[1];
89 ncoor[2][i] = tnrm[2];
90 } /* print texture */
91 fprintf(fp, "\n%s texfunc %s\n4 dx dy dz %s\n0\n",
92 sc->matname[f->mat], TEXNAME, TCALNAME);
93 fput_baryc(&bcm, ncoor, 3, fp); /* with BC normals */
94 fprintf(fp, "\n%s polygon %s.%d\n0\n0\n9\n",
95 TEXNAME, sc->grpname[f->grp], ++fcnt);
96 for (i = 0; i < 3; i++) { /* then triangle */
97 double *v = sc->vert[f->v[i].vid].p;
98 fprintf(fp, "\t%18.12g %18.12g %18.12g\n", v[0], v[1], v[2]);
99 }
100 return(1);
101 }
102
103 /* Callback to convert face to Radiance */
104 static int
105 radface(Scene *sc, Face *f, void *ptr)
106 {
107 FILE *fp = (FILE *)ptr;
108 int i;
109
110 fprintf(fp, "\n%s polygon %s.%d\n0\n0\n%d\n", sc->matname[f->mat],
111 sc->grpname[f->grp], ++fcnt, 3*f->nv);
112 for (i = 0; i < f->nv; i++) {
113 Vertex *vp = sc->vert + f->v[i].vid;
114 fprintf(fp, "\t%18.12g %18.12g %18.12g\n",
115 vp->p[0], vp->p[1], vp->p[2]);
116 }
117 return(1);
118 }
119
120 /* Convert indicated faces to Radiance, return # written or -1 on error */
121 int
122 toRadiance(Scene *sc, FILE *fp, int flreq, int flexc)
123 {
124 int n;
125
126 if (sc == NULL || sc->nfaces <= 0 || fp == NULL)
127 return(0);
128 /* not passing empties */
129 flexc |= FACE_DEGENERATE;
130 /* reset counter if not stdout */
131 fcnt *= (fp == stdout);
132 /* write comments */
133 for (n = 0; n < sc->ndescr; n++)
134 fprintf(fp, "# %s\n", sc->descr[n]);
135 /* flag faces to smooth */
136 n = foreachFace(sc, checksmooth, flreq, flexc, NULL);
137 if (n > 0) { /* write smooth faces */
138 Scene *smoothies = dupScene(sc, flreq|FACE_RESERVED, flexc);
139 if (!smoothies)
140 return(-1);
141 n = triangulateScene(smoothies);
142 if (n >= 0)
143 n = foreachFace(smoothies, trismooth, 0, 0, fp);
144 freeScene(smoothies);
145 }
146 if (n < 0)
147 return(-1);
148 /* write flat faces */
149 n += foreachFace(sc, radface, flreq, flexc|FACE_RESERVED, fp);
150
151 if (fflush(fp) < 0) {
152 error(SYSTEM, "Error writing Radiance scene data");
153 return(-1);
154 }
155 return(n);
156 }
157
158 /* Convert faces to Radiance file, return # written or -1 on error */
159 int
160 writeRadiance(Scene *sc, const char *fspec, int flreq, int flexc)
161 {
162 extern char *progname;
163 FILE *fp;
164 int n;
165
166 if (sc == NULL || sc->nfaces <= 0 || fspec == NULL || !*fspec)
167 return(0);
168 #if POPEN_SUPPORT
169 if (fspec[0] == '!') {
170 if ((fp = popen(fspec+1, "w")) == NULL) {
171 sprintf(errmsg, "%s: cannot execute", fspec);
172 error(SYSTEM, errmsg);
173 return(-1);
174 }
175 } else
176 #endif
177 if ((fp = fopen(fspec, "w")) == NULL) {
178 sprintf(errmsg, "%s: cannot open for writing", fspec);
179 error(SYSTEM, errmsg);
180 return(-1);
181 }
182 /* start off header */
183 fprintf(fp, "# Radiance scene file converted from .OBJ by %s\n#\n",
184 progname);
185 n = toRadiance(sc, fp, flreq, flexc); /* write file */
186 #if POPEN_SUPPORT
187 if (fspec[0] == '!') {
188 if (pclose(fp)) {
189 sprintf(errmsg, "%s: error writing to command\n", fspec);
190 error(SYSTEM, errmsg);
191 return(-1);
192 }
193 } else
194 #endif
195 fclose(fp); /* close it (already flushed) */
196 return(n);
197 }