fshake3d
0.0.1
FreeformDensity3DSurfaceEditor
|
00001 #include "scene_FunctionMixer.hpp" 00002 #include "opengl.hpp" 00003 #include <boost/bind.hpp> 00004 #include <float.h> 00005 00006 // --- constructor ----------------------------------------------------------- 00007 00008 FunctionMixer::FunctionMixer() 00009 : mpElevationGrid(0) 00010 , mSelectHotSpot(0) 00011 , mPointSize(1.0) 00012 , mTex(-1) 00013 , mList(-1) 00014 , mLayerMask(~0U) 00015 , mDefaultXSD(10.0) 00016 , mDefaultYSD(10.0) 00017 , mDefaultAlpha(0.0) 00018 , mPointSizeChanged(true) 00019 { 00020 initControls(); 00021 setElevationGrid(0); 00022 } 00023 00024 // --- initialize ui --------------------------------------------------------- 00025 00026 void FunctionMixer::initControls() 00027 { 00028 Vec4d bgcolor(0.0,0.0,0.0,0.2); 00029 Vec4d colorx(0.8,0.8,0.8,0.3); 00030 Vec4d colory(0.8,0.8,0.8,0.3); 00031 Vec4d colorz(0.8,0.8,0.8,0.3); 00032 00033 mControlZ.setBorder(mPointSize); 00034 mControlZ.setEnabled(false); 00035 mControlZ.setAxis(AXIS_Z); 00036 mControlZ.setUpAxis(AXIS_X); 00037 mControlZ.setColor(colorz); 00038 mControlZ.setBGColor(bgcolor); 00039 mControlZ.setAbsMode(ABSMODE_POSITIVE); 00040 mControlZ.setKnobType(KNOB_TRANSLATE); 00041 // BUG: sensor volume is not displayed using ( -DBL_MAX , DBL_MAX ) 00042 // mControlZ.setMinValue(-DBL_MAX); 00043 // mControlZ.setMaxValue(DBL_MAX); 00044 mControlZ.setMinValue(-10000); 00045 mControlZ.setMaxValue(10000); 00046 mControlZ.setSlotValueChange( boost::bind( &FunctionMixer::updateHotSpotZ, this, _1 ) ); 00047 00048 mControlXSD.setBorder(mPointSize); 00049 mControlXSD.setEnabled(false); 00050 mControlXSD.setAxis(AXIS_X); 00051 mControlXSD.setUpAxis(AXIS_Z); 00052 mControlXSD.setColor(colorx); 00053 mControlXSD.setBGColor(bgcolor); 00054 mControlXSD.setAbsMode(ABSMODE_MIRROR); 00055 mControlXSD.setKnobType(KNOB_STRETCH); 00056 mControlXSD.setMinValue(-10000); 00057 mControlXSD.setMaxValue(10000); 00058 // mControlXSD.setMinValue(DBL_MIN); 00059 // mControlXSD.setMaxValue(DBL_MAX); 00060 mControlXSD.setSlotValueChange( boost::bind( &FunctionMixer::setXSD, this, _1 ) ); 00061 00062 mControlYSD.setBorder(mPointSize); 00063 mControlYSD.setEnabled(false); 00064 mControlYSD.setAxis(AXIS_Y); 00065 mControlYSD.setUpAxis(AXIS_Z); 00066 mControlYSD.setColor(colory); 00067 mControlYSD.setBGColor(bgcolor); 00068 mControlYSD.setAbsMode(ABSMODE_MIRROR); 00069 mControlYSD.setKnobType(KNOB_STRETCH); 00070 mControlYSD.setMinValue(-10000); 00071 mControlYSD.setMaxValue(10000); 00072 // mControlYSD.setMinValue(DBL_MIN); 00073 // mControlYSD.setMaxValue(DBL_MAX); 00074 mControlYSD.setSlotValueChange( boost::bind( &FunctionMixer::setYSD, this, _1 ) ); 00075 00076 mPlotX.setEnabled(false); 00077 mPlotX.setColor(colorx); 00078 mPlotX.setSteps(100); 00079 mPlotX.setXAxis(0); 00080 mPlotX.setYAxis(2); 00081 mPlotX.setYScale(1000.0); 00082 00083 mPlotY.setEnabled(false); 00084 mPlotY.setColor(colory); 00085 mPlotY.setSteps(100); 00086 mPlotY.setXAxis(1); 00087 mPlotY.setYAxis(2); 00088 mPlotY.setYScale(1000.0); 00089 00090 if (mpElevationGrid) 00091 { 00092 mPlotX.setXLimits( mpElevationGrid->getXLimits() ); 00093 mPlotY.setXLimits( mpElevationGrid->getYLimits() ); 00094 } 00095 00096 } 00097 00098 // --- model ----------------------------------------------------------------- 00099 00100 void FunctionMixer::clear() 00101 { 00102 unselect(); 00103 00104 size_t n = getHotSpotCount(); 00105 for (size_t i = 0; i < n ; ++i ) 00106 { 00107 delete &getHotSpotAtIndex(i); 00108 } 00109 mHotSpots.clear(); 00110 mHotSpotMap.clear(); 00111 updateElevationGrid(); 00112 } 00113 00114 HotSpot* FunctionMixer::getHotSpotAtPoint2d(const Point2d& p) 00115 { 00116 std::map< Point2d, HotSpot*>::iterator i = mHotSpotMap.find(p); 00117 if ( i == mHotSpotMap.end() ) 00118 { 00119 HotSpot* pHotSpot = new HotSpot(p[0],p[1],mDefaultXSD,mDefaultYSD,mDefaultAlpha); 00120 addHotSpot(pHotSpot); 00121 return pHotSpot; 00122 } 00123 return i->second; 00124 00125 } 00126 00127 00128 void FunctionMixer::setElevationGrid(ElevationGrid* pElevationGrid) 00129 { 00130 unselect(); 00131 mpElevationGrid = pElevationGrid; 00132 if (mpElevationGrid) 00133 { 00134 mPlotX.setXLimits( mpElevationGrid->getXLimits() ); 00135 mPlotY.setXLimits( mpElevationGrid->getYLimits() ); 00136 } 00137 } 00138 00139 void FunctionMixer::addHotSpot(HotSpot* pHotSpot) 00140 { 00141 mHotSpots.push_back(pHotSpot); 00142 mHotSpotMap[ Point2d( pHotSpot->getXMean(), pHotSpot->getYMean() ) ] = pHotSpot; 00143 } 00144 00145 void FunctionMixer::removeHotSpot(HotSpot* pHotSpot) 00146 { 00147 std::vector<HotSpot*>::iterator i = std::find( mHotSpots.begin(), mHotSpots.end(), pHotSpot ); 00148 if ( i != mHotSpots.end() ) 00149 { 00150 mHotSpots.erase(i); 00151 } 00152 std::map<Point2d,HotSpot*>::iterator j = mHotSpotMap.find( Point2d( pHotSpot->getXMean(), pHotSpot->getYMean() ) ); 00153 if ( j != mHotSpotMap.end() ) 00154 { 00155 mHotSpotMap.erase(j); 00156 } 00157 delete pHotSpot; 00158 updateElevationGrid(); 00159 } 00160 00161 // --- (re-) compute elevation grid ------------------------------------------ 00162 00163 double FunctionMixer::computeAt(double x, double y) 00164 { 00165 double z = 0; 00166 for ( std::vector<HotSpot*>::iterator i = mHotSpots.begin(), end = mHotSpots.end() ; i != end ; ++i ) 00167 { 00168 z += (*i)->compute(x,y); 00169 } 00170 return z; 00171 } 00172 00173 double FunctionMixer::computeAtWithout(double x, double y, HotSpot* pHotSpot) 00174 { 00175 double z = 0; 00176 for ( std::vector<HotSpot*>::iterator i = mHotSpots.begin(), end = mHotSpots.end() ; i != end ; ++i ) 00177 { 00178 if (*i != pHotSpot) 00179 z += (*i)->compute(x,y); 00180 } 00181 return z; 00182 } 00183 00184 00189 void FunctionMixer::updateElevationGrid() 00190 { 00191 if (mpElevationGrid) 00192 { 00193 Vec2d xlim = mpElevationGrid->getXLimits(); 00194 Vec2d ylim = mpElevationGrid->getYLimits(); 00195 double xsize = xlim[1]-xlim[0]; 00196 double ysize = ylim[1]-ylim[0]; 00197 int nysteps = mpElevationGrid->getYSteps(); 00198 int nxsteps = mpElevationGrid->getXSteps(); 00199 00200 for(int iy = 0; iy < nysteps ; ++iy ) 00201 { 00202 double y = ylim[0] + (ysize/(nysteps-1))*iy; 00203 for (int ix = 0; ix < nxsteps ; ++ix ) 00204 { 00205 double x = xlim[0] + (xsize/(nxsteps-1))*ix; 00206 00207 double z = 0; 00208 for ( std::vector<HotSpot*>::iterator i = mHotSpots.begin(), end = mHotSpots.end() ; i != end ; ++i ) 00209 { 00210 z += (*i)->compute(x,y); 00211 } 00212 mpElevationGrid->updatePositionZ(ix,iy,z); 00213 } 00214 } 00215 mpElevationGrid->computeNormals(); 00216 } 00217 } 00218 00219 // --- hotspot control ------------------------------------------------------- 00220 00221 void FunctionMixer::selectHotSpot(const Point2d& p) 00222 { 00223 mSelectHotSpot = getHotSpotAtPoint2d(p); 00224 if ( mSelectHotSpot ) 00225 { 00226 mSelectPoint = Vec3d(p[0],p[1], computeAt(p[0],p[1]) ); 00227 mSelectHotSpotZ = mSelectHotSpot->computeBase(mSelectPoint[0],mSelectPoint[1]); 00228 mSelectBaseZ = mSelectPoint[2] - mSelectHotSpot->compute(mSelectPoint[0],mSelectPoint[1]); 00229 00230 // some coordinates: 00231 Point3d controlPosition( mSelectPoint[0], mSelectPoint[1], -0.1 ); 00232 Point3d basePosition( mSelectPoint[0],mSelectPoint[1], 0.0 ); 00233 00234 // setup hotspot z control 00235 00236 mControlZ.setPosition( basePosition ); 00237 mControlZ.setValue( mSelectPoint[2] ); 00238 mControlZ.setEnabled(true); 00239 00240 // setup hotspot x/y standard deviation controls 00241 00242 mControlXSD.setPosition( controlPosition ); 00243 mControlXSD.setValue( mSelectHotSpot->getXSD() ); 00244 mControlXSD.setEnabled(true); 00245 00246 mControlYSD.setPosition( controlPosition ); 00247 mControlYSD.setValue( mSelectHotSpot->getYSD() ); 00248 mControlYSD.setEnabled(true); 00249 00250 // setup plot controls 00251 00252 mPlotX.setPosition( basePosition ); 00253 mPlotY.setPosition( basePosition ); 00254 mPlotX.setFunction( boost::bind( &HotSpot::computeX, mSelectHotSpot, _1 ) ); 00255 mPlotY.setFunction( boost::bind( &HotSpot::computeY, mSelectHotSpot, _1 ) ); 00256 // mPlotX.setEnabled(true); 00257 // mPlotY.setEnabled(true); 00258 } 00259 } 00260 00261 // --- manipulate z ---------------------------------------------------------- 00262 00263 void FunctionMixer::updateHotSpotZ(double z) 00264 { 00265 if (mpElevationGrid) 00266 { 00267 if (mSelectHotSpot) 00268 { 00269 double restz = computeAtWithout(mSelectPoint[0],mSelectPoint[1], mSelectHotSpot); 00270 mSelectHotSpot->setAlpha( (z - restz) / mSelectHotSpot->computeBase(mSelectPoint[0],mSelectPoint[1]) ); 00271 mSelectPoint[2] = computeAt(mSelectPoint[0],mSelectPoint[1]); 00272 updateElevationGrid(); 00273 } 00274 } 00275 } 00276 00277 // --- manipulate sd --------------------------------------------------------- 00278 00279 /* 00280 template<typename T> 00281 inline T filter_sd(T x) 00282 { 00283 return clamp<T>( abs(x), 0.0000000001, 100); 00284 } 00285 */ 00286 00287 void FunctionMixer::setXSD(double xsd) 00288 { 00289 if (mSelectHotSpot) 00290 { 00291 // update hotspot 00292 mSelectHotSpot->setXSD( xsd ); 00293 00294 // update alpha 00295 updateHotSpotZ( mSelectPoint[2] ); 00296 } 00297 } 00298 00299 void FunctionMixer::setYSD(double ysd) 00300 { 00301 if (mSelectHotSpot) 00302 { 00303 // update hotspot 00304 mSelectHotSpot->setYSD( ysd ); 00305 00306 // update alpha 00307 updateHotSpotZ( mSelectPoint[2] ); 00308 } 00309 } 00310 00311 // --- user-input ------------------------------------------------------------ 00312 00313 void FunctionMixer::setPointSize(double pointsize) 00314 { 00315 mPointSize = pointsize; 00316 mControlZ.setBorder(mPointSize); 00317 mControlXSD.setBorder(mPointSize); 00318 mControlYSD.setBorder(mPointSize); 00319 mPointSizeChanged = true; 00320 } 00321 00322 00323 void FunctionMixer::removeSelected() 00324 { 00325 if (mSelectHotSpot) 00326 { 00327 HotSpot* hs = mSelectHotSpot; 00328 unselect(); 00329 removeHotSpot(hs); 00330 } 00331 } 00332 00333 bool FunctionMixer::select(const Rayd& ray, SceneView& view) 00334 { 00335 if (mpElevationGrid) 00336 { 00337 double t; 00338 Slider* pNear = 0; 00339 double tnear = DBL_MAX; 00340 00341 if ( mControlZ.hit(ray, t) ) 00342 { 00343 pNear = &mControlZ; 00344 tnear = t; 00345 } 00346 00347 if ( mControlXSD.hit(ray, t) ) 00348 { 00349 if ( t < tnear) 00350 { 00351 pNear = &mControlXSD; 00352 tnear = t; 00353 } 00354 } 00355 00356 if (mControlYSD.hit(ray,t) ) 00357 { 00358 if (t < tnear) 00359 { 00360 pNear = &mControlYSD; 00361 tnear = t; 00362 } 00363 } 00364 00365 if (pNear) 00366 { 00367 pNear->select(ray,view); 00368 return true; 00369 } 00370 00371 int x,y; 00372 if ( mpElevationGrid->intersect(ray, x, y, mPointSize ) ) 00373 { 00374 Point3d p = mpElevationGrid->getPoint(x,y); 00375 selectHotSpot( Point2d(p[0],p[1]) ); 00376 mControlZ.select(ray,view); 00377 return true; 00378 } 00379 } 00380 unselect(); 00381 return false; 00382 } 00383 00384 void FunctionMixer::unselect() 00385 { 00386 mSelectHotSpot = 0; 00387 mControlZ.setEnabled(false); 00388 mControlXSD.setEnabled(false); 00389 mControlYSD.setEnabled(false); 00390 mPlotX.setEnabled(false); 00391 mPlotY.setEnabled(false); 00392 } 00393 00394 bool FunctionMixer::drag(const Rayd& ray, SceneView& view) 00395 { 00396 if (mpElevationGrid) 00397 { 00398 if ( mControlZ.drag(ray,view) ) return true; 00399 if ( mControlXSD.drag(ray,view) ) return true; 00400 if ( mControlYSD.drag(ray,view) ) return true; 00401 } 00402 return false; 00403 } 00404 00405 // --- display --------------------------------------------------------------- 00406 00407 00408 void FunctionMixer::display() 00409 { 00410 if (mpElevationGrid) 00411 { 00412 displaySurface(); 00413 if (mSelectHotSpot) 00414 { 00415 displayControls(); 00416 } 00417 } 00418 } 00419 00420 void FunctionMixer::displayControls() 00421 { 00422 mControlZ.display(); 00423 mControlXSD.display(); 00424 mControlYSD.display(); 00425 mPlotX.display(); 00426 mPlotY.display(); 00427 } 00428 00429 void FunctionMixer::displayAlpha() 00430 { 00431 glPushAttrib(GL_ENABLE_BIT|GL_LINE_BIT); 00432 glEnable(GL_BLEND); 00433 glColor4d(1.0,1.0,1.0,0.5); 00434 glDisable(GL_LIGHTING); 00435 glDisable(GL_DEPTH_TEST); 00436 double x = mSelectHotSpot->getXMean(); 00437 double y = mSelectHotSpot->getYMean(); 00438 double z = computeAt(x,y); 00439 glLineWidth(2.0); 00440 glBegin(GL_LINES); 00441 glVertex3d(x,y,z); 00442 glVertex3d(x,y,z-mSelectHotSpot->getAlpha()); 00443 glEnd(); 00444 glPopAttrib(); 00445 } 00446 00447 void FunctionMixer::displaySurface() 00448 { 00449 // GL resources: 00450 00451 if (mList == -1) 00452 { 00453 // init Display List 00454 mList = glGenLists(1); 00455 } 00456 00457 if (mPointSizeChanged) 00458 { 00459 glNewList(mList, GL_COMPILE); 00460 glutSolidSphere( mPointSize , 12, 12 ); 00461 glEndList(); 00462 mPointSizeChanged = false; 00463 } 00464 00465 if (mTex == -1) 00466 { 00467 // init height color 1D texture 00468 glGenTextures(1, &mTex); 00469 glBindTexture(GL_TEXTURE_1D, mTex); 00470 glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 00471 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_REPEAT); 00472 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 00473 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 00474 00475 Vec3d cols[4] = { Vec3d(0.3,0.5,0.3),Vec3d(0.8,0.6,0.4),Vec3d(1.0,1.0,1.0),Vec3d(0.0,0.0,1.0) }; 00476 00477 // Vec3d cols[4] = { Vec3d(0.3,0.5,0.3),Vec3d(0.8,0.6,0.4),Vec3d(0.6,1.0,0.6),Vec3d(1.0,0.6,0.6) }; 00478 unsigned char* colormap = new_colormap(256, &cols[0], sizeof(cols)/sizeof(Vec3d) ); 00479 00480 glTexImage1D(GL_TEXTURE_1D, 0, GL_RGB, 256, 0, GL_RGB, GL_UNSIGNED_BYTE, colormap); 00481 delete [] colormap; 00482 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); 00483 } 00484 00485 // display control points 00486 glEnable(GL_LIGHT0); 00487 00488 // display hotspots 00489 if ( isLayerEnabled(LAYER_HOTSPOTS) ) 00490 { 00491 glPushAttrib(GL_ENABLE_BIT); 00492 00493 glEnable(GL_LIGHTING); 00494 glEnable(GL_DEPTH_TEST); 00495 00496 GLfloat pointDiffuse[4] = { 0.7, 0.3, 0.3, 1.0 }; 00497 GLfloat pointAmbient[4] = { 0.2, 0.2, 0.2, 1.0 }; 00498 glMaterialfv(GL_FRONT, GL_DIFFUSE, pointDiffuse); 00499 glMaterialfv(GL_FRONT, GL_AMBIENT, pointAmbient); 00500 00501 glMatrixMode(GL_MODELVIEW); 00502 for ( std::vector<HotSpot*>::iterator i = mHotSpots.begin(), end = mHotSpots.end() ; i != end ; ++i ) 00503 { 00504 double x = (*i)->getXMean(); 00505 double y = (*i)->getYMean(); 00506 double z = computeAt(x,y); 00507 glPushMatrix(); 00508 glTranslated(x,y,z); 00509 glCallList(mList); 00510 glPopMatrix(); 00511 } 00512 00513 glPopAttrib(); 00514 } 00515 00516 if ( isLayerEnabled(LAYER_CONTROLPOINTS) ) 00517 { 00518 00519 glPushAttrib(GL_ENABLE_BIT); 00520 00521 glEnable(GL_LIGHTING); 00522 glEnable(GL_DEPTH_TEST); 00523 00524 GLfloat pointDiffuse[4] = { 0.5, 0.5, 0.5, 1.0 }; 00525 // GLfloat pointAmbient[4] = { 0.5, 0.5, 0.5, 1.0 }; 00526 GLfloat pointAmbient[4] = { 0.1, 0.1, 0.1, 1.0 }; 00527 glMaterialfv(GL_FRONT, GL_DIFFUSE, pointDiffuse); 00528 glMaterialfv(GL_FRONT, GL_AMBIENT, pointAmbient); 00529 00530 mpElevationGrid->drawPointLists(mList); 00531 00532 glPopAttrib(); 00533 00534 } 00535 00536 // display grid 00537 00538 if ( isLayerEnabled(LAYER_GRID)) 00539 { 00540 glPushAttrib(GL_ENABLE_BIT|GL_LINE_BIT); 00541 00542 glEnable(GL_DEPTH_TEST); 00543 glLineWidth(1.5); 00544 00545 glColor4d(0.0,0.0,0.0,0.5); 00546 mpElevationGrid->drawGrid(); 00547 00548 glPopAttrib(); 00549 } 00550 00551 // display surface 00552 00553 if ( isLayerEnabled(LAYER_SURFACE) ) 00554 { 00555 glPushAttrib(GL_ENABLE_BIT|GL_LIGHTING_BIT); 00556 glEnable(GL_LIGHTING); 00557 glEnable(GL_DEPTH_TEST); 00558 glEnable(GL_TEXTURE_1D); 00559 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); 00560 00561 GLfloat surfaceDiffuse[4] = { 1.0, 1.0, 1.0, 1.0 }; 00562 GLfloat surfaceAmbient[4] = { 0.5, 0.5, 0.5, 1.0 }; 00563 glMaterialfv(GL_FRONT, GL_DIFFUSE, surfaceDiffuse); 00564 // glMaterialfv(GL_FRONT, GL_DIFFUSE, surfaceAmbient); 00565 glMaterialfv(GL_FRONT, GL_AMBIENT, surfaceAmbient); 00566 00567 mpElevationGrid->drawQuadStripNormalT1D(); 00568 glPopAttrib(); 00569 } 00570 00571 // display normals 00572 if ( isLayerEnabled(LAYER_NORMALS) ) 00573 { 00574 glPushAttrib(GL_ENABLE_BIT|GL_LINE_BIT); 00575 glEnable(GL_BLEND); 00576 glEnable(GL_DEPTH_TEST); 00577 glDisable(GL_LIGHTING); 00578 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 00579 glEnable(GL_DEPTH_TEST); 00580 glLineWidth(1); 00581 glColor4d(0.8,0.4,0.4,0.3); 00582 mpElevationGrid->drawNormalLines(2.0); 00583 glPopAttrib(); 00584 } 00585 00586 if ( !isLayerEnabled(LAYER_CONTROLPOINTS) ) 00587 { 00588 glPushAttrib(GL_ENABLE_BIT); 00589 glEnable(GL_DEPTH_TEST); 00590 glColor3d(0.0,0.0,0.0); 00591 glPointSize(3); 00592 mpElevationGrid->drawPoints(); 00593 glPopAttrib(); 00594 } 00595 }