📄 calculator.cpp.in
字号:
" DEF r5s9 Sphere {}", " }", " }", " }", " DEF info Separator {", " OrthographicCamera {", " height 1", " }", " DEF infoposition Translation {}", " DEF infoscale Scale {}", " Separator {", " BaseColor { rgb 1 1 0 }", " Translation { translation 0.02 -0.04 0 }", " Text2 { string \"You do the math. ['Esc', then 'q' to quit.]\" }", " }", " }", "}", NULL};/* ********************************************************************** */char *strconcat(const char * array[], unsigned int &total){ int i; for (i = total = 0; array[i]; i++ ) total += strlen(array[i]) + 1; char * buf = new char [total + 1]; for (i = total = 0; array[i]; i++ ) { strcpy(buf+total, array[i]); total += strlen(array[i]); buf[total] = '\n'; total++; } return buf;}/* ********************************************************************** */SoNode *getNodeByName(SoNode * root, const char * name){ static SoSearchAction * action; if ( !action ) action = new SoSearchAction; action->reset(); // action->setFind(SoSearchAction::NAME); action->setName(SbName(name)); action->setInterest(SoSearchAction::FIRST); action->apply(root); if ( !action->getPath() ) return NULL; return action->getPath()->getTail();}/* ********************************************************************** */#define ROWS 6float spherepositions[10][ROWS];void adjust_row(SoNode * scene, int row){ const float mintrans = 1.93f; const float maxtrans = 13.7f; scene->enableNotify(FALSE); for ( int i = 0; i < 10; i++ ) { char name[5]; sprintf(name, "r%dt%d", row, i); SoTranslation * translation = (SoTranslation *) getNodeByName(scene, name); assert(translation != NULL); float delta = 0.0f; if ( i > 0 ) delta = spherepositions[i][row] - spherepositions[i-1][row]; else delta = spherepositions[0][row]; if ( i == 0 ) delta = (13.7-1.93) * delta; else delta = 1.93 + (13.7-1.93) * delta; // fprintf(stderr, "delta for %s = %g\n", name, delta); translation->translation.setValue(delta, 0.0f, 0.0f); } scene->enableNotify(TRUE); scene->touch();}/* ********************************************************************** */static SbVec2s lastviewport = SbVec2s(-1,-1);static SbLine ray(SbVec3f(0,0,0), SbVec3f(1,0,0));voidevent_cb(void * closure, SoAction * action){ So@Gui@ExaminerViewer * viewer = (So@Gui@ExaminerViewer *) closure; if ( action->isOfType(SoGLRenderAction::getClassTypeId()) ) { SoGLRenderAction * raaction = (SoGLRenderAction *) action; SoNode * scene = action->getNodeAppliedTo(); SbVec2s viewport = raaction->getViewportRegion().getWindowSize(); if ( viewport != lastviewport ) { lastviewport = viewport; SoTranslation * translation = (SoTranslation *) getNodeByName(scene, "infoposition"); assert(translation != NULL); float aspect = float(viewport[0]) / float(viewport[1]); float factor = float(100)/float(viewport[1]) * 6.0f; if ( aspect > 1.0f ) { translation->translation.setValue(SbVec3f(-0.5f * aspect, 0.5f, 0.0f)); } else { translation->translation.setValue(SbVec3f(-0.5f, 0.5f / aspect, 0.0f)); factor /= aspect; } SoScale * scale = (SoScale *) getNodeByName(scene, "infoscale"); assert(scale != NULL); scale->scaleFactor.setValue( SbVec3f(factor,factor,1.0f) ); } return; } static SoRayPickAction * rpaction = NULL; static SbBool attached = FALSE; static int row = 0; static int sphere = 0; static SbPlane * plane = NULL; static SbVec3f * lastpoint = NULL; static float lastval = 0.0f; if ( action->isOfType(SoHandleEventAction::getClassTypeId()) ) { // SoDebugError::postInfo("event", "handle event"); SoHandleEventAction * heaction = (SoHandleEventAction *) action; if ( !rpaction ) rpaction = new SoRayPickAction(heaction->getViewportRegion()); else { // fprintf(stderr, "viewport: "); // heaction->getViewportRegion().print(stderr); // fprintf(stderr, "\n"); rpaction->setViewportRegion(heaction->getViewportRegion()); } const SoEvent * event = heaction->getEvent(); if ( event->isOfType(SoMouseButtonEvent::getClassTypeId()) ) { const SoMouseButtonEvent * mbevent = (const SoMouseButtonEvent *) event; if ( mbevent->getState() == SoMouseButtonEvent::DOWN ) { rpaction->setPoint(mbevent->getPosition()); rpaction->apply(heaction->getNodeAppliedTo()); SoPickedPoint * point = rpaction->getPickedPoint(); if ( point == NULL ) return; SoPath * path = point->getPath(); if ( path == NULL ) return; SoNode * node = path->getTail(); if ( node == NULL ) return; if ( !node->isOfType(SoSphere::getClassTypeId()) ) return; const char * name = node->getName().getString(); attached = TRUE; switch ( name[1] ) { case '0': row = 0; break; default: row = (name[1] - '1') + 1; break; } switch ( name[3] ) { case '0': sphere = 0; break; default: sphere = (name[3] - '1') + 1; break; } if ( !plane ) plane = new SbPlane(SbVec3f(0,0,0), SbVec3f(0,1,0), SbVec3f(1,0,0)); SbVec3f thispoint; if ( !plane->intersect(ray, thispoint) ) return; lastpoint = new SbVec3f(thispoint); lastval = spherepositions[sphere][row]; } else if ( mbevent->getState() == SoMouseButtonEvent::UP ) { attached = FALSE; if ( lastpoint != NULL ) { delete lastpoint; lastpoint = NULL; } } } else if ( attached && event->isOfType(SoLocation2Event::getClassTypeId()) ) { const SoLocation2Event * l2event = (const SoLocation2Event *) event; assert( rpaction != NULL ); rpaction->setPoint(l2event->getPosition()); rpaction->apply(heaction->getNodeAppliedTo()); // SbLine ray(rpaction->getLine()); SbVec3f thispoint; if ( !plane->intersect(ray, thispoint) ) return; // fprintf(stderr, "it's a drag (sphere %dx%d) = delta %g\n", row, sphere, float delta = thispoint[0] - (*lastpoint)[0]; float pos = lastval; pos = pos + delta / (13.7-1.93); if ( pos < 0.0f ) pos = 0.0f; if ( pos > 1.0f ) pos = 1.0f; spherepositions[sphere][row] = pos; int j = 0; if ( pos < lastval ) { for ( j = sphere - 1; j >= 0; j-- ) { if ( spherepositions[j][row] > spherepositions[j+1][row] ) spherepositions[j][row] = spherepositions[j+1][row]; } } else { for ( j = sphere + 1; j < 10; j++ ) { if ( spherepositions[j][row] < spherepositions[j-1][row] ) spherepositions[j][row] = spherepositions[j-1][row]; } } adjust_row(heaction->getNodeAppliedTo(), row); } return; }}voidrpevent_cb( void * closure, SoAction * action ){ if ( !action->isOfType(SoRayPickAction::getClassTypeId()) ) return; SoRayPickAction * rpaction = (SoRayPickAction *) action; rpaction->setObjectSpace(); ray = rpaction->getLine();}/* ********************************************************************** */intmain( int argc, char ** argv ){ setbuf(stderr, NULL); setbuf(stdout, NULL); @WIDGET@ window = So@Gui@::init(argv[0]); So@Gui@ExaminerViewer * viewer = new So@Gui@ExaminerViewer(window); viewer->setTransparencyType(SoGLRenderAction::DELAYED_BLEND); viewer->setViewing(FALSE); viewer->setDecoration(FALSE); SoInput * in = new SoInput; unsigned int len; char * buffer = strconcat(scenegraph, len); in->setBuffer(buffer, len); SoNode * scene; if ( ! SoDB::read(in, scene) ) { delete [] buffer; delete in; delete viewer; fprintf(stderr, "%s: error in scene - exiting.\n", argv[0]); exit(-1); } delete [] buffer; delete in; scene->ref(); // FIXME: getNodeByName() fails when running on top SGI // Inventor. Investigate. 20010919 mortene. SoCallback * hook = (SoCallback *) getNodeByName(scene, "hook"); if ( ! hook ) { fprintf(stderr, "hook not installed.\n"); } else { hook->setCallback(event_cb, viewer); } SoCallback * snoop = (SoCallback *) getNodeByName(scene, "raysnoop"); if ( ! hook ) { fprintf(stderr, "raypick hook not installed.\n"); } else { snoop->setCallback(rpevent_cb, viewer); } scene->unrefNoDelete(); viewer->setSceneGraph(scene); for ( int row = 0; row < ROWS; row++ ) { for ( int sphere = 0; sphere < 10; sphere++ ) spherepositions[sphere][row] = 0.0f; adjust_row(scene, row); } // viewer->goFullScreen(TRUE); // might be too slow? viewer->show(); viewer->viewAll(); viewer->setTitle("Calculator"); So@Gui@::show(window); So@Gui@::mainLoop(); delete viewer; return 0;}/* EOF ****************************************************************** */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -