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 }