00001 /*
00002 File: Writers.cc
00003
00004 Function: Implements various scene writer functions
00005
00006 Author: Andrew Willmott
00007
00008 Notes:
00009 */
00010
00011 #include "gcl/Writers.h"
00012 #include "gcl/SceneObjects.h"
00013
00014 #define INFO_COUT cerr
00015
00016 Int ObjWriter::pointsWritten;
00017 FILE *ObjWriter::file = 0;
00018
00019 Void ObjWriter::HandlePoly(
00020 Int numVertices,
00021 Int vertices[],
00022 Int changed
00023 )
00024 {
00025 Int i;
00026
00027 if (numVertices < 0) return;
00028
00029 if (pointsWritten < pointsAcc->NumItems())
00030 {
00031 for (i = pointsWritten; i < pointsAcc->NumItems(); i++)
00032 fprintf(file, "v %g %g %g\n", (*pointsAcc)[i][0],
00033 (*pointsAcc)[i][1],
00034 (*pointsAcc)[i][2]
00035 );
00036 pointsWritten = pointsAcc->NumItems();
00037 }
00038
00039 fprintf(file, "f");
00040 for (i = 0; i < numVertices; i++)
00041 fprintf(file, " %d", vertices[i] + 1);
00042 fprintf(file, "\n");
00043 }
00044
00045 Void ObjWriter::SaveAs(scScenePtr scene, StrConst filename)
00046 {
00047 file = fopen(filename, "w");
00048
00049 if (!file)
00050 {
00051 _Warning("(WriteObjFile) couldn't open output file for writing");
00052 return;
00053 }
00054
00055 fprintf(file, "# GCL scene wavefront writer\n");
00056
00057 fprintf(file, "\n");
00058
00059 // dump points, colours, and texture coords if we have 'em.
00060
00061 pointsWritten = 0;
00062 scene->Decimate(SELF, DecUseMaster);
00063
00064 fclose(file);
00065 }
00066
00067 // --- MGF format ----------------------------------------------------------------
00068
00069 Int MGFWriter::vertNum;
00070 Int MGFWriter::pointsWritten;
00071 FILE *MGFWriter::file = 0;
00072
00073 Void MGFWriter::HandlePoly(
00074 Int numVertices,
00075 Int vertices[],
00076 Int changed
00077 )
00078 {
00079 Int i;
00080
00081 const Colour wtMGF(0.265, 0.670, 0.065);
00082
00083 if (numVertices < 0) return;
00084
00085 if (changed)
00086 // write out new material definition
00087 {
00088 Colour *reflectancePtr = SC_GET(Colour), rdc;
00089 Colour *emittancePtr = SC_GET(Emittance), edc;
00090 ClrReal rd, ed;
00091
00092 if (reflectancePtr)
00093 rdc = *reflectancePtr;
00094 else
00095 rdc = scPrimitive::sDefaultColour;
00096
00097 rd = dot(wtMGF, rdc);
00098 if (rd > 0.0)
00099 rdc /= rd;
00100 rdc *= wtMGF;
00101
00102 if (emittancePtr)
00103 {
00104 edc = *emittancePtr;
00105 // MGF 'ed' is illuminance, i.e., photometric irradiance.
00106 // we are (currently) pure irradiance
00107 edc *= 179.0;
00108 ed = dot(wtMGF, edc);
00109 if (ed > 0.0)
00110 edc /= ed;
00111 edc *= wtMGF;
00112 }
00113 else
00114 ed = 0.0;
00115
00116 fprintf(file, "m\n");
00117 // MGF parser has problems with cmix 0 R 0 G 0 B...
00118 if (rd > 0.0)
00119 fprintf(file,
00120 "\tc\n\t\tcmix %g R %g G %g B\n"
00121 "\trd %g\n",
00122 rdc[0], rdc[1], rdc[2],
00123 rd
00124 );
00125 else
00126 fprintf(file,
00127 "\trd 0.0\n"
00128 );
00129
00130 if (ed > 0.0)
00131 fprintf(file,
00132 "\tc\n\t\tcmix %g R %g G %g B\n"
00133 "\ted %g\n",
00134 edc[0], edc[1], edc[2],
00135 ed
00136 );
00137 else
00138 fprintf(file,
00139 "\ted 0.0\n"
00140 );
00141 }
00142
00143 if (pointsWritten < pointsAcc->NumItems())
00144 {
00145 for (i = pointsWritten; i < pointsAcc->NumItems(); i++)
00146 fprintf(file, "v v%d = \n\tp %g %g %g\n",
00147 vertNum++,
00148 (*pointsAcc)[i][0],
00149 (*pointsAcc)[i][1],
00150 (*pointsAcc)[i][2]
00151 );
00152 pointsWritten = pointsAcc->NumItems();
00153 }
00154
00155 fprintf(file, "f");
00156 for (i = 0; i < numVertices; i++)
00157 fprintf(file, " v%d", vertices[i]);
00158 fprintf(file, "\n");
00159 }
00160
00161 Void MGFWriter::SaveAs(scScenePtr scene, StrConst filename)
00162 {
00163 file = fopen(filename, "w");
00164
00165 if (!file)
00166 {
00167 _Warning("(WriteMGFFile) couldn't open output file for writing");
00168 return;
00169 }
00170
00171 fprintf(file, "# GCL scene MGF format writer\n");
00172
00173 fprintf(file, "\n");
00174 fprintf(file, "o test\n");
00175 // MGF files are generally zup, so 'correct' our usual yup
00176 fprintf(file, "xf -rx 90\n");
00177 fprintf(file,
00178 "c R =\n"
00179 " cxy 0.64 0.33\n"
00180 "c G =\n"
00181 " cxy 0.29 0.6\n"
00182 "c B =\n"
00183 " cxy 0.15 0.06\n\n");
00184
00185 // dump points and colours
00186 // only attempt to write out polygon meshes at the moment, though
00187 // MGF can handle more.
00188 // need to add normals etc.
00189
00190 pointsWritten = 0;
00191 vertNum = 0;
00192
00193 scene->Decimate(SELF, DecUseMaster);
00194
00195 fclose(file);
00196 }
00197
00198 // --- Rad format ----------------------------------------------------------------
00199
00200 // this is here 'cause mgf2rad dumps core on large (polygonal) scenes
00201 // quick & dirty
00202 // note: that bug's since been fixed by Greg; it was a problem with the hash
00203 // table code.
00204
00205 Int RadWriter::matNum;
00206 Int RadWriter::polyNum;
00207 Int RadWriter::pointsWritten;
00208 FILE *RadWriter::file = 0;
00209
00210 Void RadWriter::HandlePoly(
00211 Int numVertices,
00212 Int vertices[],
00213 Int changed
00214 )
00215 {
00216 PointList *points = SC_GET(Points);
00217 Int i;
00218
00219 if (numVertices < 0 || points == 0) return;
00220
00221 if (changed)
00222 {
00223 Colour *reflectancePtr = SC_GET(Colour), rdc;
00224 Colour *emittancePtr = SC_GET(Emittance), edc;
00225
00226 matNum++;
00227
00228 if (reflectancePtr)
00229 rdc = *reflectancePtr;
00230 else
00231 rdc = cOrange;
00232
00233 if (emittancePtr)
00234 {
00235 edc = *emittancePtr;
00236 // convert from irradiance to radiance necessary for the
00237 // .rad format.
00238 edc /= vl_pi;
00239 }
00240 else
00241 edc = cBlack;
00242
00243 if (len(edc) > 0.0)
00244 {
00245 fprintf(file, "void light mat%d\n", matNum);
00246 fprintf(file, "0\n0\n3 %g %g %g\n\n",
00247 edc[0], edc[1], edc[2]);
00248 }
00249 else
00250 {
00251 fprintf(file, "void plastic mat%d\n", matNum);
00252 fprintf(file, "0\n0\n5 %g %g %g 0.0 0.0\n\n",
00253 rdc[0], rdc[1], rdc[2]);
00254 }
00255 }
00256
00257 fprintf(file, "mat%d polygon f%d\n0\n0\n%d\n",
00258 matNum, polyNum++, numVertices * 3
00259 );
00260
00261 for (i = 0; i < numVertices; i++)
00262 {
00263 Point p = (*points)[vertices[i]];
00264
00265 p = xform(transAcc, p);
00266
00267 fprintf(file, "%-20g %-20g %-20g\n",
00268 p[0], p[1], p[2]
00269 );
00270 }
00271
00272 fprintf(file, "\n");
00273 }
00274
00275 Void RadWriter::SaveAs(scScenePtr scene, StrConst filename)
00276 {
00277 file = fopen(filename, "w");
00278
00279 if (!file)
00280 {
00281 _Warning("(WriteRadFile) couldn't open output file for writing");
00282 return;
00283 }
00284
00285 fprintf(file, "# GCL scene Radiance format writer\n");
00286
00287 fprintf(file, "\n");
00288
00289 pointsWritten = 0;
00290 matNum = 0;
00291 polyNum = 1;
00292
00293 scene->Decimate(SELF, 0);
00294
00295 fclose(file);
00296 }
00297
00298 // --- Generic writer -------------------------------------------------------------
00299
00300 Void SceneWriter::Save(scScenePtr scene, FileName filename)
00301 {
00302 INFO_COUT << "Writing " << filename.GetPath() << endl;
00303
00304 if (filename.GetExtension() == "mgf")
00305 MGFWriter().SaveAs(scene, filename.GetPath());
00306 else if (filename.GetExtension() == "obj")
00307 ObjWriter().SaveAs(scene, filename.GetPath());
00308 else if (filename.GetExtension() == "rad")
00309 RadWriter().SaveAs(scene, filename.GetPath());
00310 else if (filename.GetExtension() == "sl")
00311 {
00312 ofstream fout;
00313
00314 fout.open(filename.GetPath());
00315 if (fout)
00316 {
00317 scene->Print(fout);
00318 fout.close();
00319 }
00320 else
00321 perror("Couldn't open output file");
00322 }
00323 else
00324 {
00325 INFO_COUT << "unknown scene file extension " << filename.GetExtension()
00326 << ": saving as default (obj)" << endl;
00327 filename.SetExtension("obj");
00328 ObjWriter().SaveAs(scene, filename.GetPath());
00329 }
00330 }
00331
00332 static StrConst tSceneWriterFormats[] =
00333 {
00334 "sl", "GCL's scene language.",
00335 "obj", "Wavefront .obj ascii format [default]",
00336 "mgf", "material and geometry format",
00337 "rad", "radiance format",
00338 "mrb", "binary multi-resolution model(s)",
00339 0
00340 };
00341
00342 Void SceneWriter::PrintSupportedFormats(ostream &s)
00343 {
00344 StrConst *str = tSceneWriterFormats;
00345 Int i;
00346
00347 while (*str)
00348 {
00349 s << " " << *str;
00350 for (i = 0; i < 4 - str->Length(); i++)
00351 s << ' ';
00352 str++;
00353 s << *str++ << endl;
00354 }
00355 }