/* writevrml.c: saves the result of a radiosity computation as a VRML file. */ #include "writevrml.h" #include "scene.h" #include "defaults.h" #include "camera.h" #include "render.h" #include "error.h" /* compute a rotation that will rotate the current "up"-direction to the Y axis. * Y-axis points up in VRML2.0 */ TRANSFORM VRMLModelTransform(VECTOR *model_rotaxis, float *model_rotangle) { VECTOR up_axis; double cosa; VECTORSET(up_axis, 0., 1., 0.); cosa = VECTORDOTPRODUCT(Camera.updir, up_axis); if (cosa < 1. - EPSILON) { *model_rotangle = acos(cosa); VECTORCROSSPRODUCT(Camera.updir, up_axis, *model_rotaxis); VECTORNORMALIZE(*model_rotaxis); return Rotate(*model_rotangle, *model_rotaxis); } else { VECTORSET(*model_rotaxis, 0., 1., 0.); *model_rotangle = 0.; return IdentityTransform; } } /* Write VRML ViewPoint node for the given camera position */ void WriteVRMLViewPoint(FILE *fp, TRANSFORM model_xf, CAMERA *cam, char *vpname) { VECTOR X, Y, Z, view_rotaxis, eyep; TRANSFORM view_xf; float view_rotangle; VECTORSCALE( 1., cam->X, X); /* cam->X points right in window */ VECTORSCALE(-1., cam->Y, Y); /* cam->Y points down in window, VRML wants y up */ VECTORSCALE(-1., cam->Z, Z); /* cam->Z points away, VRML wants Z to point towards viewer */ /* apply model transform */ TRANSFORM_VECTOR_3D(model_xf, X, X); TRANSFORM_VECTOR_3D(model_xf, Y, Y); TRANSFORM_VECTOR_3D(model_xf, Z, Z); /* construct view orientation transform and recover axis and angle */ view_xf = IdentityTransform; SET_3X3MATRIX(view_xf.m, X.x, Y.x, Z.x, X.y, Y.y, Z.y, X.z, Y.z, Z.z); RecoverRotation(view_xf, &view_rotangle, &view_rotaxis); /* apply model transform to eye point */ TRANSFORM_POINT_3D(model_xf, cam->eyep, eyep); fprintf(fp, "Viewpoint {\n position %g %g %g\n orientation %g %g %g %g\n fieldOfView %g\n description \"%s\"\n}\n\n", eyep.x, eyep.y, eyep.z, view_rotaxis.x, view_rotaxis.y, view_rotaxis.z, view_rotangle, (double)(2. * cam->fov * M_PI / 180.), vpname); } void WriteVRMLViewPoints(FILE *fp, TRANSFORM model_xf) { CAMERA *cam = (CAMERA *)NULL; int count = 1; WriteVRMLViewPoint(fp, model_xf, &Camera, "ViewPoint 1"); while ((cam = NextSavedCamera(cam)) != (CAMERA *)NULL) { char vpname[20]; count++; sprintf(vpname, "ViewPoint %d", count); WriteVRMLViewPoint(fp, model_xf, cam, vpname); } } void WriteVRMLHeader(FILE *fp) { TRANSFORM model_xf; VECTOR model_rotaxis; float model_rotangle; fprintf(fp, "#VRML V2.0 utf8\n\n"); fprintf(fp, "WorldInfo {\n title \"%s\"\n info [ \"Created using RenderPark (%s)\" ]\n}\n\n", "Some nice model", RPKHOME); fprintf(fp, "NavigationInfo {\n type \"WALK\"\n headlight FALSE\n}\n\n"); model_xf = VRMLModelTransform(&model_rotaxis, &model_rotangle); WriteVRMLViewPoints(fp, model_xf); fprintf(fp, "Transform {\n rotation %g %g %g %g\n children [\n Shape {\n geometry IndexedFaceSet {\n", model_rotaxis.x, model_rotaxis.y, model_rotaxis.z, model_rotangle); fprintf(fp, "\tsolid %s\n", renderopts.backface_culling ? "TRUE" : "FALSE"); } void WriteVRMLTrailer(FILE *fp) { fprintf(fp, " }\n }\n ]\n}\n\n"); } static void ResetVertexId(void) { ForAllPatches(P, Patches) { int i; for (i=0; inrvertices; i++) P->vertex[i]->tmp = -1; } EndForAll; } static void WriteCoords(FILE *fp) { int id = 0, n = 0; ResetVertexId(); fprintf(fp, "\tcoord Coordinate {\n\t point [ "); ForAllPatches(P, Patches) { int i; for (i=0; inrvertices; i++) { VERTEX *v = P->vertex[i]; if (v->tmp == -1) { /* not yet written */ if (n>0) fprintf(fp, ", "); n++; if (n%4 == 0) fprintf(fp, "\n\t "); fprintf(fp, "%g %g %g", v->point->x, v->point->y, v->point->z); v->tmp = id; id++; } } } EndForAll; fprintf(fp, " ] "); fprintf(fp, "\n\t}\n"); } static void WriteVertexColors(FILE *fp) { int id = 0, n = 0; ResetVertexId(); fprintf(fp, "\tcolor Color {\n\t color [ "); ForAllPatches(P, Patches) { int i; for (i=0; inrvertices; i++) { VERTEX *v = P->vertex[i]; if (v->tmp == -1) { /* not yet written */ if (n>0) fprintf(fp, ", "); n++; if (n%4 == 0) fprintf(fp, "\n\t "); fprintf(fp, "%.3g %.3g %.3g", v->color.r, v->color.g, v->color.b); v->tmp = id; id++; } } } EndForAll; fprintf(fp, " ] "); fprintf(fp, "\n\t}\n"); } static void WriteFaceColors(FILE *fp) { int n = 0; fprintf(fp, "\tcolor Color {\n\t color [ "); ForAllPatches(P, Patches) { if (n>0) fprintf(fp, ", "); n++; if (n%4 == 0) fprintf(fp, "\n\t "); fprintf(fp, "%.3g %.3g %.3g", P->color.r, P->color.g, P->color.b); } EndForAll; fprintf(fp, " ] "); fprintf(fp, "\n\t}\n"); } static void WriteColors(FILE *fp) { fprintf(fp, "\tcolorPerVertex %s\n", renderopts.smooth_shading ? "TRUE" : "FALSE"); if (renderopts.smooth_shading) WriteVertexColors(fp); else WriteFaceColors(fp); } static void WriteCoordIndices(FILE *fp) { int n=0; fprintf(fp, "\tcoordIndex [ "); ForAllPatches(P, Patches) { int i; for (i=0; inrvertices; i++) { VERTEX *v = P->vertex[i]; n++; if (n%20 == 0) fprintf(fp, "\n\t "); fprintf(fp, "%d ", v->tmp); } n++; if (n%20 == 0) fprintf(fp, "\n\t "); fprintf(fp, "-1 "); } EndForAll; fprintf(fp, " ]\n"); } void WriteVRML(FILE *fp) { WriteVRMLHeader(fp); WriteCoords(fp); WriteColors(fp); WriteCoordIndices(fp); WriteVRMLTrailer(fp); }