/* ui_camera.c: camera menu */ #include #include #include #include "ui.h" #include "uit.h" #include "camera.h" #include "transform.h" #include "render.h" #include "pools.h" #include "error.h" static Widget viewsBox, viewButtonsForm; /* dialog with predefined views */ static int nrviews = 0, curview = -1; static Widget *viewButtons; static CAMERA *cams; static float anim_time = 5., pause_time = 0.; static Widget fpsLabel; /* label widget displaying the frames/sec rate */ static int movebusy = FALSE; static void UpdateFramesPerSecond(double fps) { char s[100]; sprintf(s, "%.3g frames/second", fps); SetLabelString(fpsLabel, s); } static void GoToView(CAMERA dst) { int nframes = 0; CAMERA src = Camera; double tstart = get_time(); movebusy = TRUE; /* rerender current frame */ CameraSet(&Camera, &src.eyep, &src.lookp, &src.updir, src.fov, Camera.hres, Camera.vres, &src.background); ProcessWaitingEvents(); RenderScene(); nframes++; while (1) { CAMERA cam = Camera; double s = (get_time() - tstart) / anim_time; if (s >= 1.-EPSILON) break; VECTORINTERPOLATE(src.eyep, dst.eyep, s, cam.eyep); VECTORINTERPOLATE(src.lookp, dst.lookp, s, cam.lookp); VECTORINTERPOLATE(src.updir, dst.updir, s, cam.updir); cam.fov = (1. - s) * src.fov + s * dst.fov; CameraSet(&Camera, &cam.eyep, &cam.lookp, &cam.updir, cam.fov, Camera.hres, Camera.vres, &cam.background); ProcessWaitingEvents(); RenderScene(); nframes++; } UpdateFramesPerSecond(renderopts.frames_per_sec); CameraSet(&Camera, &dst.eyep, &dst.lookp, &dst.updir, dst.fov, Camera.hres, Camera.vres, &dst.background); ProcessWaitingEvents(); RenderScene(); movebusy = FALSE; } void GoToNextView(void) { if (movebusy) return; if (curview >= nrviews || curview < 0) curview = 0; else curview = (curview + 1) % nrviews; GoToView(cams[curview]); } void GoToPreviousView(void) { if (movebusy) return; if (curview >= nrviews || curview < 0) curview = 0; else curview = (curview - 1 + nrviews) % nrviews; GoToView(cams[curview]); } void GoToViewNr(int viewnr) { if (movebusy) return; if (viewnr < 0 || viewnr >= nrviews) { Error(NULL, "No view nr %d\n", viewnr); return; } curview = viewnr; GoToView(cams[curview]); } static int making_the_buttons = FALSE; static void GoToViewCallback(Widget button, XtPointer client_data, XtPointer call_data) { int set = (((XmToggleButtonCallbackStruct *)call_data)->set == XmSET); if (set && !making_the_buttons) { curview = (int)client_data; GoToView(cams[curview]); } } void CreatePredefViewButtons(int nr, CAMERA *cam, char **descr) { int i; /* first dispose of the previous buttons */ if (nrviews > 0) { for (i=0; i= nrviews || curview < 0) curview = 0; if (nrviews > 1) { for (i=0; i 0) sleep(pause_time); } } } static void CycleBackwardCallback(Widget w, XtPointer client_data, XtPointer call_data) { int i; XtUnmanageChild(viewsBox); if (curview >= nrviews || curview < 0) curview = 0; if (nrviews > 1) { for (i=0; i 0) sleep(pause_time); } } } static Widget CreatePredefViewsDialog(Widget parent, char *name) { Widget form, frame, subform; Boolean valid; viewsBox = CreateDialog(parent, name); form = CreateRowColumn(viewsBox, "predefViewsForm"); frame = CreateFrame(form, "predefViewsExtraFrame", NULL); subform = CreateRowColumn(frame, "predefViewsExtraForm"); CreateFormEntry(subform, "animTimeLabel", "animTimeTextf", FET_FLOAT, (XtPointer)&anim_time, &valid, 0); CreateFormEntry(subform, "pauseTimeLabel", "pauseTimeTextf", FET_FLOAT, (XtPointer)&pause_time, &valid, 0); CreatePushButton(subform, "cycleForwardButton", CycleForwardCallback, NULL); CreatePushButton(subform, "cycleBackwardButton", CycleBackwardCallback, NULL); fpsLabel = CreateLabel(subform, "fpsLabel"); UpdateFramesPerSecond(0.); XtManageChild(subform); frame = CreateFrame(form, "predefViewsButtonFrame", "predefViewsButtonTitle"); viewButtonsForm = CreateRadioBox(frame, "predefViewsButtonForm"); nrviews = 0; XtManageChild(viewButtonsForm); XtManageChild(form); return viewsBox; } /*************************** Camera Menu ******************************/ CAMERA alternate_camera; static void EditCameraOKCallback(Widget w, XtPointer client_data, XtPointer calldata) { CAMERA *cam = (CAMERA *)client_data; CameraSet(&Camera, &cam->eyep, &cam->lookp, &cam->updir, cam->fov, Camera.hres, Camera.vres, &Camera.background); RenderScene(); } static void EditCameraCancelCallback(Widget w, XtPointer client_data, XtPointer calldata) { Widget editCameraDialog = XtParent(w); CAMERA *cam = (CAMERA *)client_data; XtDestroyWidget(editCameraDialog); CameraDestroy(cam); } static void ShowEditCameraBox(Widget w, XtPointer client_data, XtPointer call_data) { Widget editCameraBox, editCameraForm, frame, subform; CAMERA *cam; static Boolean valid; editCameraBox = CreateDialog(w, "editCameraBox"); editCameraForm = CreateRowColumn(editCameraBox, "editCameraForm"); cam = CameraCreate(); *cam = Camera; frame = CreateFrame(editCameraForm, "eyepFrame", "eyepTitle"); subform = CreateRowColumn(frame, "eyepForm"); CreateFormEntry(subform, "xLabel", "xTextf", FET_FLOAT, (XtPointer)&cam->eyep.x, &valid, 0); CreateFormEntry(subform, "yLabel", "yTextf", FET_FLOAT, (XtPointer)&cam->eyep.y, &valid, 0); CreateFormEntry(subform, "zLabel", "zTextf", FET_FLOAT, (XtPointer)&cam->eyep.z, &valid, 0); XtManageChild(subform); frame = CreateFrame(editCameraForm, "lookpFrame", "lookpTitle"); subform = CreateRowColumn(frame, "lookpForm"); CreateFormEntry(subform, "xLabel", "xTextf", FET_FLOAT, (XtPointer)&cam->lookp.x, &valid, 0); CreateFormEntry(subform, "yLabel", "yTextf", FET_FLOAT, (XtPointer)&cam->lookp.y, &valid, 0); CreateFormEntry(subform, "zLabel", "zTextf", FET_FLOAT, (XtPointer)&cam->lookp.z, &valid, 0); XtManageChild(subform); frame = CreateFrame(editCameraForm, "updirFrame", "updirTitle"); subform = CreateRowColumn(frame, "updirForm"); CreateFormEntry(subform, "xLabel", "xTextf", FET_FLOAT, (XtPointer)&cam->updir.x, &valid, 0); CreateFormEntry(subform, "yLabel", "yTextf", FET_FLOAT, (XtPointer)&cam->updir.y, &valid, 0); CreateFormEntry(subform, "zLabel", "zTextf", FET_FLOAT, (XtPointer)&cam->updir.z, &valid, 0); XtManageChild(subform); frame = CreateFrame(editCameraForm, "fovFrame", "fovTitle"); subform = CreateRowColumn(frame, "fovForm"); CreateFormEntry(subform, NULL, "fovTextf", FET_FLOAT, (XtPointer)&cam->fov, &valid, 0); XtManageChild(subform); XtManageChild(editCameraForm); /* OK and Cancel buttons are automatically created when a callback or labelstring * is defined for them. */ XtAddCallback(editCameraBox, XmNokCallback, EditCameraOKCallback, (XtPointer)cam); XtAddCallback(editCameraBox, XmNcancelCallback, EditCameraCancelCallback, (XtPointer)cam); /* realize the dialog box on the screen */ XtManageChild(editCameraBox); } static void SaveCameraCallback(Widget w, XtPointer client_data, XtPointer call_data) { CameraPush(&Camera); RenderScene(); } static void RestoreCameraCallback(Widget w, XtPointer client_data, XtPointer call_data) { CameraPop(&Camera); RenderScene(); } static void SetAlternateCameraCallback(Widget w, XtPointer client_data, XtPointer call_data) { alternate_camera = Camera; } static void ToggleAlternateCameraCallback(Widget w, XtPointer client_data, XtPointer call_data) { CAMERA tmp = Camera; /* keep hres and vres */ alternate_camera.hres = Camera.hres; alternate_camera.vres = Camera.vres; Camera = alternate_camera; Camera.changed = 0; alternate_camera = tmp; RenderScene(); } static void ResetCameraCallback(Widget w, XtPointer client_data, XtPointer call_data) { SetDefaultView(); RenderScene(); } /* 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, (float)(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); } } static void PrintCameraCallback(Widget w, XtPointer client_data, XtPointer call_data) { WriteVRMLViewPoints(stdout, IdentityTransform); } void CreateCameraMenu(Widget menuBar) { Widget cameraMenu; alternate_camera = Camera; cameraMenu = CreateSubMenu(menuBar, "cameraButton", "cameraMenu"); CreateCascadeDialog(cameraMenu, "predefViewsButton", CreatePredefViewsDialog, "predefViewsBox", DEFAULT_CALLBACK, NULL); CreatePushButton(cameraMenu, "editCameraButton", ShowEditCameraBox, (XtPointer)NULL); CreatePushButton(cameraMenu, "resetCameraButton", ResetCameraCallback, (XtPointer)NULL); CreateSeparator(cameraMenu, "cameraSeparator"); CreatePushButton(cameraMenu, "saveCameraButton", SaveCameraCallback, (XtPointer)NULL); CreatePushButton(cameraMenu, "restoreCameraButton", RestoreCameraCallback, (XtPointer)NULL); CreateSeparator(cameraMenu, "cameraSeparator"); CreatePushButton(cameraMenu, "setAlternateCameraButton", SetAlternateCameraCallback, (XtPointer)NULL); CreatePushButton(cameraMenu, "toggleAlternateCameraButton", ToggleAlternateCameraCallback, (XtPointer)NULL); CreateSeparator(cameraMenu, "cameraSeparator"); CreatePushButton(cameraMenu, "printCameraButton", PrintCameraCallback, (XtPointer)NULL); }