/************************************* Iv2Ray.c++ ************************************** * (C) 1997 Mark Lasersohn - Cow House Productions Iv2Ray V0.12 This is a beta executable and source for Irix 5.3 and the OpenInventor 2.0 (or better) run-time library. I reserve all rights, this executable and source file is the copywritten property of Cow House Productions and may not be packaged or resold without written permission. It is distributed from my web page (http://www.cowhouse.com). The source and executable may be distributed freely, as long as it is done so freely and my copyright notices remain intact. Syntax: iv2ray [-b] file.iv [ > file.ray] It writes its output to stdout which should be redirected. You can also aim it right at Rayshade: iv2ray file.iv | rayshade > out.rle The -b flag causes backface removal. This will save memory and rendering time, but if there is a reflection that reveals the back of an object, the removal will be evident. It maps pretty well. Some of the Inventor primitives texture map differently. To get a fairly exact fit, use IndexedTriangleStripSets and indexed texture coordinates instead of primitives. The materials map over, but may need hand-tweeking. By the way - it does not convert any .rgb files used by textures into the .rle format Rayshade wants - you have to do that by hand. I use the URT toolkit for that. Iv2Ray will not translate the inventor 2D constructs, such as points, lines, or 2D text. I have also been informed that it won't do so well with quads or nurbs. To compile the source on SGI with OpenInventor, simple type: CC iv2ray.c++ -lInventor -o iv2ray I don't have any other versions of Inventor, so TGS and Portable Graphics users are on their own. This is command line utility without a graphical user interface. Thus it should readily compile. But if you have any problems, please feel free to contact me at laser@cowhouse.com. I have happily tracked down and on occasion fixed bugs found by users. I don't promise to fix any problems but I will get back to you and I really do want to hear your ideas, suggestions, and comments. Mark Lasersohn Cow House Productions laser@cowhouse.com http://www.cowhouse.com */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define DEGREES (360.0 / 6.28) char surf_name[10000][20]; float surf_ambient_r[10000]; float surf_ambient_g[10000]; float surf_ambient_b[10000]; float surf_diffuse_r[10000]; float surf_diffuse_g[10000]; float surf_diffuse_b[10000]; float surf_specular_r[10000]; float surf_specular_g[10000]; float surf_specular_b[10000]; float surf_transparency[10000]; float surf_shininess[10000]; int surf_cnt; int backface; char texture_filename[256]; long int texture_index_count; int vcnt; int nvcnt; SbVec3f gvec[1000000]; SbVec3f nvec[1000000]; SbVec3f gvec2[1000000]; SbVec3f nvec2[1000000]; FILE *fp1, *fp2; static const SbVec3f &transformPoint(const SbMatrix &m, const SbVec3f &p) { static SbVec3f tp; m.multVecMatrix(p, tp); return tp; } static const SbVec3f &transformNormal(const SbMatrix &m, const SbVec3f &n) { static SbVec3f tn; m.multDirMatrix(n, tn); tn.normalize(); return tn; } SoCallbackAction::Response preTextureCB(void *, SoCallbackAction *, const SoNode *nd) { char *cp; SoTexture2 *texture = (SoTexture2 *)nd; strcpy(texture_filename, texture->filename.getValue().getString()); cp = texture_filename + strlen(texture_filename); while((*cp != '.') && (cp > texture_filename)) cp--; *cp = '\0'; return(SoCallbackAction::CONTINUE); } SoCallbackAction::Response preCameraCB(void *, SoCallbackAction *, const SoNode *nd) { SoPerspectiveCamera *camera = (SoPerspectiveCamera *)nd; printf("eyep 0 0 0\n"); printf("lookp 0 0 -1\n"); printf("fov %g\n", camera->heightAngle.getValue() * DEGREES); printf("focaldist %g\n", camera->focalDistance.getValue()); return(SoCallbackAction::CONTINUE); } SoCallbackAction::Response preLightCB(void *, SoCallbackAction *cba, const SoNode *nd) { float x, y, z; float x2, y2, z2; float r, g, b; float angle; SbVec3f vec; if(nd->isOfType(SoDirectionalLight::getClassTypeId())) { const SbMatrix &vm = cba->getViewingMatrix(); SoDirectionalLight *light = (SoDirectionalLight *)nd; vec = transformPoint(vm, light->direction.getValue()); vec.getValue(x, y, z); light->color.getValue().getValue(r, g, b); printf("light %g %g %g directional %g %g %g\n", r, g, b, x, y, z); } if(nd->isOfType(SoPointLight::getClassTypeId())) { const SbMatrix &vm = cba->getViewingMatrix(); const SbMatrix &mm = cba->getModelMatrix(); SoPointLight *light = (SoPointLight *)nd; light->color.getValue().getValue(r, g, b); vec = transformPoint(mm, light->location.getValue()); vec = transformPoint(vm, light->location.getValue()); vec.getValue(x, y, z); printf("light %g %g %g point %g %g %g\n", r, g, b, x, y, z); } if(nd->isOfType(SoSpotLight::getClassTypeId())) { const SbMatrix &vm = cba->getViewingMatrix(); SoSpotLight *light = (SoSpotLight *)nd; vec = transformPoint(vm, light->location.getValue()); vec.getValue(x, y, z); vec = transformPoint(vm, light->direction.getValue()); vec.getValue(x2, y2, z2); light->color.getValue().getValue(r, g, b); angle = light->cutOffAngle.getValue() * DEGREES; printf("light %g %g %g spot %g %g %g %g %g %g %g %g %g\n", r, g, b, x, y, z, x2, y2, z2, angle, angle / 2.0, angle); } return(SoCallbackAction::CONTINUE); } static void addTriangleCB(void *, SoCallbackAction *cba, const SoPrimitiveVertex *v1, const SoPrimitiveVertex *v2, const SoPrimitiveVertex *v3) { static int flag = 0; if((vcnt < 999999) && (nvcnt < 999999)) { flag = 0; if(backface == 1) { const SbMatrix &mm = cba->getModelMatrix(); SbMatrix nm = mm.inverse().transpose(); SbVec3f vec1 = transformNormal(nm, v1->getNormal()); SbVec3f vec2 = transformNormal(nm, v2->getNormal()); SbVec3f vec3 = transformNormal(nm, v3->getNormal()); if((vec1[2] >= 0.0) || (vec2[2] >= 0.0) || (vec3[2] >= 0.0)) { gvec[vcnt++] = v1->getPoint(); nvec[nvcnt++] = v1->getNormal(); gvec[vcnt++] = v2->getPoint(); nvec[nvcnt++] = v2->getNormal(); gvec[vcnt++] = v3->getPoint(); nvec[nvcnt++] = v3->getNormal(); } } else { gvec[vcnt++] = v1->getPoint(); nvec[nvcnt++] = v1->getNormal(); gvec[vcnt++] = v2->getPoint(); nvec[nvcnt++] = v2->getNormal(); gvec[vcnt++] = v3->getPoint(); nvec[nvcnt++] = v3->getNormal(); } } else { if(flag == 0) { fprintf(stderr, "\n\nError: Too many triangles ( > 1000000) in a single shape\n"); fprintf(stderr, "further triangles in this shape will be ignored\n\n"); } flag = 1; } } SoCallbackAction::Response countMaterialCB(void *, SoCallbackAction *, const SoNode *) { static int cnt = 0; cnt++; fprintf(stderr, "\r shape nodes: %d", cnt); return(SoCallbackAction::CONTINUE); } //////////////////////////////////////////////////////////////////////// // // Description: // Callback used to add triangle info to scene graph being built. // SoCallbackAction::Response addMaterialCB(void *, SoCallbackAction *cba, const SoNode *nd) { SbColor ambient; SbColor diffuse; SbColor specular; SbColor emission; float shininess; float transparency; float r, g, b; char geometry_file[256]; static int file_counter = 0; SbVec2f vec2; SbVec3f vec3; int loop; float x, y, z; int flag; long int index1; long int index2; long int index3; long int nindex1; long int nindex2; long int nindex3; long int tindex1; long int tindex2; long int tindex3; SbVec3f translation; SbRotation rotation; SbVec3f scale; SbRotation scale_orientation; float angle; int trans_it = 0; float xmin, ymin, zmin; float xmax, ymax, zmax; SbVec2s size; int numComps; int texturing = 0; char node_name[1024]; int normals; cba->getMaterial(ambient, diffuse, specular, emission, shininess, transparency); sprintf(geometry_file, "geo%04d", file_counter); fprintf(stderr, "\r (%d) ", file_counter); file_counter++; texture_index_count = cba->getNumTextureCoordinates(); node_name[0] = '\0'; strcpy(node_name, nd->getName().getString()); flag = -1; for(loop = 0;loop < surf_cnt;loop++) { ambient.getValue(r, g, b); if((r == surf_ambient_r[loop]) && (g == surf_ambient_g[loop]) && (b == surf_ambient_b[loop])) { diffuse.getValue(r, g, b); if((r == surf_diffuse_r[loop]) && (g == surf_diffuse_g[loop]) && (b == surf_diffuse_b[loop])) { specular.getValue(r, g, b); if((r == surf_specular_r[loop]) && (g == surf_specular_g[loop]) && (b == surf_specular_b[loop])) { if(transparency == surf_transparency[loop]) { if(shininess == surf_shininess[loop]) { if(strlen(node_name) > 0) { printf("/* %s */\n", node_name); } printf("grid 5 5 5\n"); flag = loop; printf("applysurf %s\n", surf_name[loop]); } } } } } } if(flag == -1) { strcpy(surf_name[surf_cnt], geometry_file); ambient.getValue(r, g, b); surf_ambient_r[surf_cnt] = r; surf_ambient_g[surf_cnt] = g; surf_ambient_b[surf_cnt] = b; diffuse.getValue(r, g, b); surf_diffuse_r[surf_cnt] = r; surf_diffuse_g[surf_cnt] = g; surf_diffuse_b[surf_cnt] = b; specular.getValue(r, g, b); surf_specular_r[surf_cnt] = r; surf_specular_g[surf_cnt] = g; surf_specular_b[surf_cnt] = b; surf_transparency[surf_cnt] = transparency; surf_shininess[surf_cnt] = shininess; surf_cnt++; printf("surface %s\n", geometry_file); ambient.getValue(r, g, b); printf("\tambient %g %g %g\n", r, g, b); diffuse.getValue(r, g, b); printf("\tdiffuse %g %g %g\n", r, g, b); specular.getValue(r, g, b); printf("\tspecular %g %g %g\n", r, g, b); printf("\ttransp %g\n", transparency); printf("\tspecpow %g\n", shininess); printf("\treflect %g\n", (r + g + b) / 30.0); printf("\tindex 1.0\n"); printf("\textinct 1.0\n"); diffuse.getValue(r, g, b); printf("\ttranslucency %g %g %g %g 12\n", transparency, r, g, b); if(strlen(node_name) > 0) { printf("/* %s */\n", node_name); } printf("grid 5 5 5\n"); printf("applysurf %s\n", geometry_file); } if(nd->isOfType(SoIndexedTriangleStripSet::getClassTypeId())) { SoIndexedTriangleStripSet *tri = (SoIndexedTriangleStripSet *)nd; const SbMatrix &mm = cba->getModelMatrix(); SbMatrix nm = mm.inverse().transpose(); const SbMatrix &vm = cba->getViewingMatrix(); if(tri->coordIndex.getNum() == tri->normalIndex.getNum()) normals = 1; else normals = 0; for(loop = 0;loop < tri->coordIndex.getNum() - 2;loop++) { index1 = tri->coordIndex[loop + 2]; index2 = tri->coordIndex[loop + 1]; index3 = tri->coordIndex[loop]; if(normals == 1) { nindex1 = tri->normalIndex[loop + 2]; nindex2 = tri->normalIndex[loop + 1]; nindex3 = tri->normalIndex[loop]; } if(texture_index_count > 0) { texturing = 1; if(cba->getTextureCoordinateBinding() == SoTextureCoordinateBinding::PER_VERTEX_INDEXED) { tindex1 = tri->textureCoordIndex[loop + 2]; tindex2 = tri->textureCoordIndex[loop + 1]; tindex3 = tri->textureCoordIndex[loop]; } else { tindex1 = index1; tindex2 = index2; tindex3 = index3; } } if((index1 != -1) && (index2 != -1) && (index3 != -1)) { vec3 = cba->getCoordinate3((int)index1); vec3 = transformPoint(mm, vec3); vec3 = transformPoint(vm, vec3); vec3.getValue(x, y, z); if(texture_index_count > 0) { printf("triangleuv %g %g %g\n", x, y, z); } else { printf("triangle %g %g %g\n", x, y, z); } if(normals == 1) { vec3 = cba->getNormal((int)nindex1); vec3 = transformNormal(nm, vec3); vec3.getValue(x, y, z); printf(" %g %g %g\n", x, y, z); } if(texture_index_count > 0) { vec2 = cba->getTextureCoordinate2((int)tindex1); vec2.getValue(x, y); printf(" %g %g\n", x, y); } vec3 = cba->getCoordinate3((int)index2); vec3 = transformPoint(mm, vec3); vec3 = transformPoint(vm, vec3); vec3.getValue(x, y, z); printf(" %g %g %g\n", x, y, z); if(normals == 1) { vec3 = cba->getNormal((int)nindex2); vec3 = transformNormal(nm, vec3); vec3.getValue(x, y, z); printf(" %g %g %g\n", x, y, z); } if(texture_index_count > 0) { vec2 = cba->getTextureCoordinate2((int)tindex2); vec2.getValue(x, y); printf(" %g %g\n", x, y); } vec3 = cba->getCoordinate3((int)index3); vec3 = transformPoint(mm, vec3); vec3 = transformPoint(vm, vec3); vec3.getValue(x, y, z); printf(" %g %g %g\n", x, y, z); if(normals == 1) { vec3 = cba->getNormal((int)nindex3); vec3 = transformNormal(nm, vec3); vec3.getValue(x, y, z); printf(" %g %g %g\n", x, y, z); } if(texture_index_count > 0) { vec2 = cba->getTextureCoordinate2((int)tindex3); vec2.getValue(x, y); printf(" %g %g\n", x, y); } } } } else { SoNode *node = (SoNode *)nd; SoGetBoundingBoxAction bba(SbViewportRegion(0, 0)); bba.apply(node); SbBox3f box = bba.getBoundingBox(); box.getBounds(xmin, ymin, zmin, xmax, ymax, zmax); box.getSize(x, y, z); const SbMatrix &mm = cba->getModelMatrix(); mm.getTransform(translation, rotation, scale, scale_orientation); x *= scale[0]; y *= scale[1]; z *= scale[2]; if(vcnt == 0) { fprintf(stderr, "\n\nError: Unsupported shape type - probably 2D (Point, Line, or Text2) node\n"); fprintf(stderr, "Creating a tiny sphere to keep Rayshade from complaining\n"); printf("/* Error: Unsupported shape type - probably 2D (Point, Line, or Text2) node */\n"); printf("/* Creating a tiny sphere to keep Rayshade from complaining */\n"); printf("sphere 0.00001 0.0 0.0 0.0\n"); } const SbMatrix &vm = cba->getViewingMatrix(); SbMatrix nm = mm.inverse().transpose(); if(cba->getTextureImage(size, numComps) != NULL) { texturing = 1; } for(loop = 0;loop < vcnt;loop++) { gvec2[loop] = transformPoint(mm, gvec[loop]); gvec2[loop] = transformPoint(vm, gvec2[loop]); nvec2[loop] = transformNormal(nm, nvec[loop]); } int cnt = 0; for(loop = 0;loop < vcnt;loop++) { if(texturing) { if((loop % 3) == 0) { printf("triangleuv %g %g %g %g %g %g " , gvec2[loop][0], gvec2[loop][1], gvec2[loop][2] , nvec2[loop][0], nvec2[loop][1], nvec2[loop][2]); } else { printf("%g %g %g %g %g %g " , gvec2[loop][0], gvec2[loop][1], gvec2[loop][2] , nvec2[loop][0], nvec2[loop][1], nvec2[loop][2]); } float sx = scale[0] * x; float sy = scale[1] * y; float sz = scale[2] * z; float u, v; float low = sx; int flag = 1; if(sy <= low) { flag = 2; low = sy; } if(sz <= low) { flag = 3; low = sz; } if(flag == 1) { u = ((scale[2] * gvec[loop][2]) - zmin) / z; v = ((scale[1] * gvec[loop][1]) - ymin) / y; } if(flag == 2) { u = ((scale[0] * gvec[loop][0]) - xmin) / x; v = ((scale[2] * gvec[loop][2]) - zmin) / z; } if(flag == 3) { u = ((scale[0] * gvec[loop][0]) - xmin) / x; v = ((scale[1] * gvec[loop][1]) - ymin) / y; } int flat_flag = 0; if((loop % 3) == 0) { SbVec3f tvec1 = gvec[loop]; SbVec3f tvec2 = gvec[loop + 1]; SbVec3f tvec3 = gvec[loop + 2]; if((tvec1[0] == tvec2[0]) && (tvec1[0] == tvec3[0])) { u = ((scale[2] * gvec[loop][2]) - zmin) / z; v = ((scale[1] * gvec[loop][1]) - ymin) / y; printf("%g %g\n", u, v); printf("%g %g %g %g %g %g " , gvec2[loop + 1][0], gvec2[loop + 1][1], gvec2[loop + 1][2] , nvec2[loop + 1][0], nvec2[loop + 1][1], nvec2[loop + 1][2]); u = ((scale[2] * gvec[loop + 1][2]) - zmin) / z; v = ((scale[1] * gvec[loop + 1][1]) - ymin) / y; printf("%g %g\n", u, v); printf("%g %g %g %g %g %g " , gvec2[loop + 2][0], gvec2[loop + 2][1], gvec2[loop + 2][2] , nvec2[loop + 2][0], nvec2[loop + 2][1], nvec2[loop + 2][2]); u = ((scale[2] * gvec[loop + 2][2]) - zmin) / z; v = ((scale[1] * gvec[loop + 2][1]) - ymin) / y; printf("%g %g\n", u, v); loop += 2; flat_flag = 1; } if((tvec1[1] == tvec2[1]) && (tvec1[1] == tvec3[1])) { u = ((scale[0] * gvec[loop][0]) - xmin) / x; v = ((scale[2] * gvec[loop][2]) - zmin) / z; printf("%g %g\n", u, v); printf("%g %g %g %g %g %g " , gvec2[loop + 1][0], gvec2[loop + 1][1], gvec2[loop + 1][2] , nvec2[loop + 1][0], nvec2[loop + 1][1], nvec2[loop + 1][2]); u = ((scale[0] * gvec[loop + 1][0]) - xmin) / x; v = ((scale[2] * gvec[loop + 1][2]) - zmin) / z; printf("%g %g\n", u, v); printf("%g %g %g %g %g %g " , gvec2[loop + 2][0], gvec2[loop + 2][1], gvec2[loop + 2][2] , nvec2[loop + 2][0], nvec2[loop + 2][1], nvec2[loop + 2][2]); u = ((scale[0] * gvec[loop + 2][0]) - xmin) / x; v = ((scale[2] * gvec[loop + 2][2]) - zmin) / z; printf("%g %g\n", u, v); loop += 2; flat_flag = 1; } if((tvec1[2] == tvec2[2]) && (tvec1[2] == tvec3[2])) { u = ((scale[0] * gvec[loop][0]) - xmin) / x; v = ((scale[1] * gvec[loop][1]) - ymin) / y; printf("%g %g\n", u, v); printf("%g %g %g %g %g %g " , gvec2[loop + 1][0], gvec2[loop + 1][1], gvec2[loop + 1][2] , nvec2[loop + 1][0], nvec2[loop + 1][1], nvec2[loop + 1][2]); u = ((scale[0] * gvec[loop + 1][0]) - xmin) / x; v = ((scale[1] * gvec[loop + 1][1]) - ymin) / y; printf("%g %g\n", u, v); printf("%g %g %g %g %g %g " , gvec2[loop + 2][0], gvec2[loop + 2][1], gvec2[loop + 2][2] , nvec2[loop + 2][0], nvec2[loop + 2][1], nvec2[loop + 2][2]); u = ((scale[0] * gvec[loop + 2][0]) - xmin) / x; v = ((scale[1] * gvec[loop + 2][1]) - ymin) / y; printf("%g %g\n", u, v); loop += 2; flat_flag = 1; } } if(flat_flag == 0) printf("%g %g\n", u, v); } else { if((loop % 3) == 0) { printf("triangle %g %g %g %g %g %g\n" , gvec2[loop][0], gvec2[loop][1], gvec2[loop][2] , nvec2[loop][0], nvec2[loop][1], nvec2[loop][2]); } else { printf("%g %g %g %g %g %g\n" , gvec2[loop][0], gvec2[loop][1], gvec2[loop][2] , nvec2[loop][0], nvec2[loop][1], nvec2[loop][2]); } } } trans_it = 0; } printf("end\n"); if(texturing) { SbVec3f vec; SbMatrix mat = cba->getTextureMatrix(); mat.getTransform(translation, rotation, scale, scale_orientation); rotation.getValue(vec, angle); if(cba->getTextureModel() == SoTexture2::MODULATE) { printf("texture image %s.rle map uv component diffuse smooth ", texture_filename); } else { printf("texture image %s.rle map uv smooth ", texture_filename); } printf("translate %g %g %g ", translation[0], translation[1], translation[2]); printf("rotate %g %g %g %g " , vec[0], vec[1], vec[2], angle * DEGREES); printf("scale %g %g %g\n" , 1.0 / scale[0], 1.0 / scale[1], 1.0 / scale[2]); } if(trans_it == 1) { const SbMatrix &mm = cba->getModelMatrix(); mm.getTransform(translation, rotation, scale, scale_orientation); rotation.getValue(vec3, angle); printf("scale %g %g %g\n" , scale[0], scale[1], scale[2]); printf("rotate %g %g %g %g\n" , vec3[0], vec3[1], vec3[2], angle * DEGREES); printf("translate %g %g %g\n" , translation[0], translation[1], translation[2]); } vcnt = 0; nvcnt = 0; return(SoCallbackAction::CONTINUE); } void evalGraph(SoSeparator *root) { // Set up callbacks to add to scene graph, then apply SoType shapeType = SoShape::getClassTypeId(); SoType lightType = SoLight::getClassTypeId(); SoType textureType = SoTexture2::getClassTypeId(); SoType cameraType = SoCamera::getClassTypeId(); SoCallbackAction ca; ca.addTriangleCallback(shapeType, addTriangleCB, NULL); ca.addPostCallback(shapeType, addMaterialCB, NULL); ca.addPreCallback(lightType, preLightCB, NULL); ca.addPreCallback(cameraType, preCameraCB, NULL); ca.addPreCallback(textureType, preTextureCB, NULL); ca.apply(root); fprintf(stderr, "\rdone \n"); } void countGraph(SoSeparator *root) { // Set up callbacks to add to scene graph, then apply SoType shapeType = SoShape::getClassTypeId(); SoCallbackAction ca; ca.addPreCallback(shapeType, countMaterialCB, NULL); ca.apply(root); printf("\n"); } void hunt_text(SoGroup *nd) { int loop; SoNode *child; for(loop = 0;loop < nd->getNumChildren();loop++) { child = nd->getChild(loop); if(child->isOfType(SoText2::getClassTypeId())) { SoText2 *text2 = (SoText2 *)child; SoText3 *text3 = new SoText3; text3->justification = text2->justification; text3->string = text2->string; text3->spacing = text2->spacing; text3->parts = SoText3::FRONT; nd->replaceChild(text2, text3); } else { if(child->isOfType(SoGroup::getClassTypeId())) { hunt_text((SoGroup *)child); } } } } void main(int argc, char **argv) { SoInput in; SoSeparator *root; fprintf(stderr, "iv2ray V0.12 (C) 1997 Mark Lasersohn - Cow House Productions\n"); if(argc > 1) { backface = 0; SoDB::init(); vcnt = 0; nvcnt = 0; if(argc > 2) { if(strncmp(argv[1], "-b", 2) == 0) backface = 1; fprintf(stderr, "Reading %s\n", argv[2]); if(! in.openFile(argv[2])) { fprintf(stderr, "%s: Cannot open %s\n", argv[0], argv[1]); exit(-1); } } else { if(strncmp(argv[1], "-b", 2) != 0) { fprintf(stderr, "Reading %s\n", argv[1]); if(! in.openFile(argv[1])) { fprintf(stderr, "%s: Cannot open %s\n", argv[0], argv[1]); exit(-1); } } else { fprintf(stderr, "syntax: iv2ray [-b] input_file.iv\n"); exit(-1); } } root = SoDB::readAll(&in); if (root == NULL) { fprintf(stderr, "%s: Problem reading data\n", argv[0]); exit(-1); } in.closeFile(); printf("up 0.0 1.0 0.0\n"); printf("report quiet\n"); printf("screen 400 400\n"); printf("contrast 0.250000 0.200000 0.400000\n"); printf("maxdepth 3\n"); printf("cutoff 0.002000\n"); printf("light 0.000000 0.000000 0.000000 ambient\n"); root->ref(); hunt_text((SoGroup *)root); countGraph(root); fprintf(stderr, "\nBuilding Rayshade file\n"); evalGraph(root); } else { fprintf(stderr, "syntax: iv2ray [-b] input_file.iv\n"); } }