+
+ if ( sgWriteError() ) {
+ cout << "We detected an error while writing the file." << endl;
+ return false;
+ }
+
+ return true;
+}
+
+
+// write out the structures to an ASCII file. We assume that the
+// groups come to us sorted by material property. If not, things
+// don't break, but the result won't be as optimal.
+bool SGBinObject::write_ascii( const string& base, const string& name,
+ const SGBucket& b )
+{
+ int i, j;
+
+ SGPath file = base + "/" + b.gen_base_path() + "/" + name;
+ file.create_dir( 0755 );
+ cout << "Output file = " << file.str() << endl;
+
+ FILE *fp;
+ if ( (fp = fopen( file.c_str(), "w" )) == NULL ) {
+ cout << "ERROR: opening " << file.str() << " for writing!" << endl;
+ return false;
+ }
+
+ cout << "triangles size = " << tris_v.size() << " tri_materials = "
+ << tri_materials.size() << endl;
+ cout << "strips size = " << strips_v.size() << " strip_materials = "
+ << strip_materials.size() << endl;
+ cout << "fans size = " << fans_v.size() << " fan_materials = "
+ << fan_materials.size() << endl;
+
+ cout << "points = " << wgs84_nodes.size() << endl;
+ cout << "tex coords = " << texcoords.size() << endl;
+ // write headers
+ fprintf(fp, "# FGFS Scenery\n");
+ fprintf(fp, "# Version %s\n", SG_SCENERY_FILE_FORMAT);
+
+ time_t calendar_time = time(NULL);
+ struct tm *local_tm;
+ local_tm = localtime( &calendar_time );
+ char time_str[256];
+ strftime( time_str, 256, "%a %b %d %H:%M:%S %Z %Y", local_tm);
+ fprintf(fp, "# Created %s\n", time_str );
+ fprintf(fp, "\n");
+
+ // write bounding sphere
+ fprintf(fp, "# gbs %.5f %.5f %.5f %.2f\n",
+ gbs_center.x(), gbs_center.y(), gbs_center.z(), gbs_radius);
+ fprintf(fp, "\n");
+
+ // dump vertex list
+ fprintf(fp, "# vertex list\n");
+ for ( i = 0; i < (int)wgs84_nodes.size(); ++i ) {
+ SGVec3d p = wgs84_nodes[i] - gbs_center;
+
+ fprintf(fp, "v %.5f %.5f %.5f\n", p.x(), p.y(), p.z() );
+ }
+ fprintf(fp, "\n");
+
+ fprintf(fp, "# vertex normal list\n");
+ for ( i = 0; i < (int)normals.size(); ++i ) {
+ SGVec3f p = normals[i];
+ fprintf(fp, "vn %.5f %.5f %.5f\n", p.x(), p.y(), p.z() );
+ }
+ fprintf(fp, "\n");
+
+ // dump texture coordinates
+ fprintf(fp, "# texture coordinate list\n");
+ for ( i = 0; i < (int)texcoords.size(); ++i ) {
+ SGVec2f p = texcoords[i];
+ fprintf(fp, "vt %.5f %.5f\n", p.x(), p.y() );
+ }
+ fprintf(fp, "\n");
+
+ // dump individual triangles if they exist
+ if ( tris_v.size() > 0 ) {
+ fprintf(fp, "# triangle groups\n");
+
+ int start = 0;
+ int end = 1;
+ string material;
+ while ( start < (int)tri_materials.size() ) {
+ // find next group
+ material = tri_materials[start];
+ while ( (end < (int)tri_materials.size()) &&
+ (material == tri_materials[end]) )
+ {
+ // cout << "end = " << end << endl;
+ end++;
+ }
+ // cout << "group = " << start << " to " << end - 1 << endl;
+
+ // make a list of points for the group
+ point_list group_nodes;
+ group_nodes.clear();
+ SGVec3d bs_center;
+ double bs_radius = 0;
+ for ( i = start; i < end; ++i ) {
+ for ( j = 0; j < (int)tris_v[i].size(); ++j ) {
+ group_nodes.push_back( Point3D::fromSGVec3(wgs84_nodes[ tris_v[i][j] ]) );
+ bs_center = sgCalcCenter( group_nodes ).toSGVec3d();
+ bs_radius = sgCalcBoundingRadius( Point3D::fromSGVec3(bs_center), group_nodes );
+ }
+ }
+
+ // write group headers
+ fprintf(fp, "\n");
+ fprintf(fp, "# usemtl %s\n", material.c_str());
+ fprintf(fp, "# bs %.4f %.4f %.4f %.2f\n",
+ bs_center.x(), bs_center.y(), bs_center.z(), bs_radius);
+
+ // write groups
+ for ( i = start; i < end; ++i ) {
+ fprintf(fp, "f");
+ for ( j = 0; j < (int)tris_v[i].size(); ++j ) {
+ fprintf(fp, " %d/%d", tris_v[i][j], tris_tc[i][j] );
+ }
+ fprintf(fp, "\n");
+ }
+
+ start = end;
+ end = start + 1;
+ }
+ }
+
+ // dump triangle groups
+ if ( strips_v.size() > 0 ) {
+ fprintf(fp, "# triangle strips\n");
+
+ int start = 0;
+ int end = 1;
+ string material;
+ while ( start < (int)strip_materials.size() ) {
+ // find next group
+ material = strip_materials[start];
+ while ( (end < (int)strip_materials.size()) &&
+ (material == strip_materials[end]) )
+ {
+ // cout << "end = " << end << endl;
+ end++;
+ }
+ // cout << "group = " << start << " to " << end - 1 << endl;
+
+ // make a list of points for the group
+ point_list group_nodes;
+ group_nodes.clear();
+ SGVec3d bs_center;
+ double bs_radius = 0;
+ for ( i = start; i < end; ++i ) {
+ for ( j = 0; j < (int)strips_v[i].size(); ++j ) {
+ group_nodes.push_back( Point3D::fromSGVec3(wgs84_nodes[ strips_v[i][j] ]) );
+ bs_center = sgCalcCenter( group_nodes ).toSGVec3d();
+ bs_radius = sgCalcBoundingRadius( Point3D::fromSGVec3(bs_center), group_nodes );
+ }
+ }
+
+ // write group headers
+ fprintf(fp, "\n");
+ fprintf(fp, "# usemtl %s\n", material.c_str());
+ fprintf(fp, "# bs %.4f %.4f %.4f %.2f\n",
+ bs_center.x(), bs_center.y(), bs_center.z(), bs_radius);
+
+ // write groups
+ for ( i = start; i < end; ++i ) {
+ fprintf(fp, "ts");
+ for ( j = 0; j < (int)strips_v[i].size(); ++j ) {
+ fprintf(fp, " %d/%d", strips_v[i][j], strips_tc[i][j] );
+ }
+ fprintf(fp, "\n");
+ }
+
+ start = end;
+ end = start + 1;
+ }
+ }
+
+ // close the file
+ fclose(fp);
+
+ string command = "gzip --force --best " + file.str();
+ system(command.c_str());
+
+ return true;