Geant4 Cross Reference |
1 // 1 2 // ******************************************* 3 // * License and Disclaimer 4 // * 5 // * The Geant4 software is copyright of th 6 // * the Geant4 Collaboration. It is provided 7 // * conditions of the Geant4 Software License 8 // * LICENSE and available at http://cern.ch/ 9 // * include a list of copyright holders. 10 // * 11 // * Neither the authors of this software syst 12 // * institutes,nor the agencies providing fin 13 // * work make any representation or warran 14 // * regarding this software system or assum 15 // * use. Please see the license in the file 16 // * for the full disclaimer and the limitatio 17 // * 18 // * This code implementation is the result 19 // * technical work of the GEANT4 collaboratio 20 // * By using, copying, modifying or distri 21 // * any work based on the software) you ag 22 // * use in resulting scientific publicati 23 // * acceptance of all terms of the Geant4 Sof 24 // ******************************************* 25 // 26 // John Allison 6th October 2019 27 28 #ifndef G4TOOLSSGVIEWER_HH 29 #define G4TOOLSSGVIEWER_HH 30 31 #include "G4VViewer.hh" 32 33 #include "G4ToolsSGSceneHandler.hh" 34 #include "G4Scene.hh" 35 #include "G4VVisCommand.hh" 36 37 #include <tools/fpng> 38 #include <tools/toojpeg> 39 40 #include <tools/sg/device_interactor> 41 #include <tools/sg/separator> 42 #include <tools/sg/ortho> 43 #include <tools/sg/perspective> 44 #include <tools/sg/torche> 45 #include <tools/sg/blend> 46 #include <tools/sg/noderef> 47 #include <tools/sg/keys> 48 49 #include <tools/tokenize> 50 #include <tools/sg/write_paper> 51 52 template <class SG_SESSION,class SG_VIEWER> 53 class G4ToolsSGViewer : public G4VViewer, tool 54 typedef G4VViewer parent; 55 typedef tools::sg::device_interactor parent_ 56 public: //tools::sg::device_interactor interfa 57 virtual void key_press(const tools::sg::key_ 58 fKeyPressed = true; 59 fKeyShift = a_event.key() == tools::sg::ke 60 } 61 virtual void key_release(const tools::sg::ke 62 virtual void mouse_press(const tools::sg::mo 63 fMousePressed = true; 64 fMousePressedX = a_event.x(); 65 fMousePressedY = a_event.y(); 66 } 67 virtual void mouse_release(const tools::sg:: 68 virtual void mouse_move(const tools::sg::mou 69 G4double x = a_event.x(); 70 G4double y = a_event.y(); 71 G4double dx = x-fMousePressedX; 72 G4double dy = y-fMousePressedY; 73 fMousePressedX = x; 74 fMousePressedY = y; 75 76 if (fMousePressed) { 77 78 if (fKeyPressed && fKeyShift) { // Tran 79 80 const G4double sceneRadius = fSGSceneH 81 const G4double scale = 300; // Roughl 82 const G4double dxScene = dx*sceneRadiu 83 const G4double dyScene = dy*sceneRadiu 84 fVP.IncrementPan(-dxScene,dyScene); 85 86 } else { // Rotation 87 88 // Simple ad-hoc algorithms 89 const G4Vector3D& x_prime = fVP.GetVie 90 const G4Vector3D& y_prime = x_prime.cr 91 const G4double scale = 200; // Roughl 92 G4Vector3D newViewpointDirection = fVP 93 newViewpointDirection += dx*x_prime/sc 94 newViewpointDirection += dy*y_prime/sc 95 fVP.SetViewpointDirection(newViewpoint 96 97 if (fVP.GetRotationStyle() == G4ViewPa 98 G4Vector3D newUpVector = fVP.GetUpVe 99 newUpVector += dx*x_prime/scale; 100 newUpVector += dy*y_prime/scale; 101 fVP.SetUpVector(newUpVector.unit()); 102 } 103 } 104 } 105 106 SetView(); 107 DrawView(); 108 } 109 virtual void wheel_rotate(const tools::sg::w 110 const G4double angleY = a_event.angle(); 111 if (fVP.GetFieldHalfAngle() == 0.) { // O 112 const G4double scale = 500; // Empirica 113 fVP.MultiplyZoomFactor(1.+angleY/scale); 114 } else { // P 115 const G4double delta = fSceneHandler.Get 116 fVP.SetDolly(fVP.GetDolly()+angleY*delta 117 } 118 SetView(); 119 DrawView(); 120 } 121 public: 122 G4ToolsSGViewer(SG_SESSION& a_session,G4Tool 123 :parent(a_scene_handler,a_scene_handler.Incr 124 ,fSGSession(a_session) 125 ,fSGSceneHandler(a_scene_handler) 126 ,fSGViewer(nullptr) 127 ,fKeyPressed(false) 128 ,fKeyShift(false) 129 ,fMousePressed(false) 130 ,fMousePressedX(0) 131 ,fMousePressedY(0) 132 { 133 //::printf("debug : G4ToolsSGViewer::G4Too 134 Messenger::Create(); 135 } 136 137 virtual ~G4ToolsSGViewer() { 138 //::printf("debug : G4ToolsSGViewer::~G4To 139 //WARNING : nodes may refer f_gl2ps_mgr, f 140 // we have to delete them first. 141 fSGViewer->sg().clear(); 142 delete fSGViewer; 143 } 144 protected: 145 G4ToolsSGViewer(const G4ToolsSGViewer& a_fro 146 :parent(a_from) 147 ,parent_interactor(a_from) 148 ,fSGSession(a_from.fSGSession) 149 ,fSGSceneHandler(a_from.fSGSceneHandler) 150 ,fSGViewer(nullptr) 151 ,fKeyPressed(false) 152 ,fKeyShift(false) 153 ,fMousePressed(false) 154 ,fMousePressedX(0) 155 ,fMousePressedY(0) 156 {} 157 G4ToolsSGViewer& operator=(const G4ToolsSGVi 158 public: 159 virtual void Initialise() { 160 if(fSGViewer) return; //done. 161 fVP.SetAutoRefresh(true); 162 fDefaultVP.SetAutoRefresh(true); 163 //::printf("debug : G4ToolsSGViewer::Initi 164 ////////////////////////////////////////// 165 /// create the viewer, set the scene graph 166 ////////////////////////////////////////// 167 fSGViewer = new SG_VIEWER(fSGSession 168 ,fVP.GetWindowAbsoluteLocationHintX(1440 169 ,fVP.GetWindowAbsoluteLocationHintY(900) 170 ,fVP.GetWindowSizeHintX() 171 ,fVP.GetWindowSizeHintY() 172 ,fName); 173 if(!fSGViewer->has_window()) { 174 fViewId = -1; // This flags an error. 175 G4cerr << "G4ToolsSGViewer::Initialise : 176 return; 177 } 178 fSGViewer->set_device_interactor(this); 179 } 180 181 virtual void SetView() { 182 //::printf("debug : G4ToolsSGViewer::SetVi 183 if(!fSceneHandler.GetScene()) { 184 fSGViewer->set_clear_color(0.3,0.3,0.3,1 185 G4cerr << "G4ToolsSGViewer::SetView : no 186 return; 187 } 188 189 ////////////////////////////////////////// 190 ////////////////////////////////////////// 191 ////////////////////////////////////////// 192 // Get radius of scene, etc. 193 // Note that this procedure properly takes 194 const G4Point3D targetPoint 195 = fSceneHandler.GetScene()->GetStandardT 196 G4double radius = fSceneHandler.GetScene() 197 if(radius<=0.) radius = 1.; 198 const G4double cameraDistance = fVP.GetCam 199 const G4Point3D cameraPosition = targetPoi 200 const G4Normal3D& up = fVP.GetUpVector (); 201 const G4double pnear = fVP.GetNearDistanc 202 const G4double pfar = fVP.GetFarDistance 203 //const G4double right = fVP.GetFrontHalfHe 204 //const G4double left = -right; 205 const G4double top = fVP.GetFrontHalfHe 206 const G4double bottom = -top; 207 // sanity check : 208 tools::vec3f dir(float(targetPoint.x()-cam 209 float(targetPoint.y()-cam 210 float(targetPoint.z()-cam 211 if(!dir.length()) { 212 fSGViewer->set_clear_color(0.3,0.3,0.3,1 213 G4cerr << "G4ToolsSGViewer::SetView : nu 214 return; 215 } 216 217 ////////////////////////////////////////// 218 ////////////////////////////////////////// 219 ////////////////////////////////////////// 220 /* 221 G4cout << "debug : 0002 : radius " << radi 222 G4cout << "debug : cameraDistance : " << c 223 G4cout << "debug : fieldHalfAngle : " << f 224 G4cout << "debug : zoomFactor : " << fVP.G 225 G4cout << "debug : up : " << up.x() << " " 226 G4cout << "debug : targetPoint : " << targ 227 G4cout << "debug : cameraPosition : " << c 228 G4cout << "debug : camera : znear " << pne 229 */ 230 ////////////////////////////////////////// 231 /// create scene graph /////////////////// 232 ////////////////////////////////////////// 233 // Set projection, then create the tools:: 234 tools::sg::base_camera* _camera = nullptr; 235 if (fVP.GetFieldHalfAngle() <= 0.) { 236 //G4cout << "debug : camera : ortho : to 237 if((top-bottom)<=0) { 238 fSGViewer->set_clear_color(0.3,0.3,0.3 239 G4cerr << "G4ToolsSGViewer::SetView : 240 return; 241 } 242 tools::sg::ortho* ortho_camera = new too 243 ortho_camera->height.value(float(top-bot 244 _camera = ortho_camera; 245 } else { 246 //G4cout << "debug : camera : perspec : 247 tools::sg::perspective* perspective_came 248 perspective_camera->height_angle.value(f 249 _camera = perspective_camera; 250 } 251 252 _camera->position.value 253 (tools::vec3f(float(cameraPosition.x()), 254 float(cameraPosition.y()), 255 float(cameraPosition.z()))); 256 _camera->znear.value(float(pnear)); 257 _camera->zfar.value(float(pfar)); 258 259 _camera->look_at(dir,tools::vec3f(up.x(),u 260 261 /* 262 const G4Vector3D& lightDirection = fVP.Get 263 G4cout << "debug : lightDirection : " << l 264 const G4Vector3D& actualLightDirection = f 265 G4cout << "debug : actualLightDirection : 266 */ 267 268 CreateSG(_camera,fVP.GetActualLightpointDi 269 270 {G4Color background = fVP.GetBackgroundColo 271 fSGViewer->set_clear_color(float(backgroun 272 } 273 274 virtual void ClearView() {} 275 276 virtual void DrawView() { 277 if (!fNeedKernelVisit) KernelVisitDecision 278 G4bool kernelVisitWasNeeded = fNeedKernelV 279 fLastVP = fVP; 280 ProcessView(); // Clears store and proces 281 if (kernelVisitWasNeeded) { 282 // We might need to do something if the 283 } else { 284 } 285 FinishView (); // Flush streams and/ 286 } 287 288 virtual void ShowView() {FinishView();} 289 290 virtual void FinishView() { 291 if(fSGViewer) { 292 fSGSceneHandler.TouchPlotters(fSGViewer- 293 fSGViewer->show(); 294 fSGViewer->win_render(); 295 fSGSession.sync(); 296 } 297 } 298 299 virtual void SwitchToVisSubThread() {} 300 301 virtual void SwitchToMasterThread() { 302 if (G4Threading::IsMultithreadedApplicatio 303 // I have not figured out how to draw du 304 // 305 // Setting fNeedKernelVisit=true causes 306 // including trajectories, hits, etc. fr 307 // 308 // Clearly this is a limitation because 309 // get those kept (default 100), and eve 310 // "refresh", you only get one event (th 311 // 312 // Also, strictly, there is no need to r 313 // but a complete rebuild is the easiest 314 // 315 // Only do this if there are end-of-even 316 // may require it. 317 if (fSceneHandler.GetScene() && fSceneHa 318 fNeedKernelVisit = true; 319 DrawView(); // Draw trajectories, etc 320 } 321 } 322 } 323 324 //SG_VIEWER* sg_viewer() {return fSGViewer;} 325 protected: 326 void KernelVisitDecision () { 327 if (CompareForKernelVisit(fLastVP)) { 328 NeedKernelVisit (); // Sets fNeedKernel 329 } 330 } 331 332 G4bool CompareForKernelVisit(G4ViewParameter 333 // Typical comparison. Taken from OpenInv 334 if ( 335 (vp.GetDrawingStyle () != fVP.GetDra 336 (vp.GetNumberOfCloudPoints() != fVP.Ge 337 (vp.IsAuxEdgeVisible () != fVP.IsAuxE 338 (vp.IsCulling () != fVP.IsCull 339 (vp.IsCullingInvisible () != fVP.IsCull 340 (vp.IsDensityCulling () != fVP.IsDens 341 (vp.IsCullingCovered () != fVP.IsCull 342 (vp.GetCBDAlgorithmNumber() != 343 fVP.GetCBDAlgorithmNumber()) 344 (vp.IsSection () != fVP.IsSect 345 (vp.IsCutaway () != fVP.IsCuta 346 // This assumes use of generic clipping 347 // DCUT, cutaway). If a decision is ma 348 // this will need changing. See G4Open 349 // G4OpenGLStoredViewer.cc::CompareForK 350 // G4OpenGLStoredSceneHander::CreateSec 351 (vp.IsExplode () != fVP.IsExpl 352 (vp.GetNoOfSides () != fVP.GetNoO 353 (vp.GetGlobalMarkerScale() != fVP.Ge 354 (vp.GetGlobalLineWidthScale() != fVP.Ge 355 (vp.IsMarkerNotHidden () != fVP.IsMark 356 (vp.GetDefaultVisAttributes()->GetColou 357 fVP.GetDefaultVisAttributes()->GetColo 358 (vp.GetDefaultTextVisAttributes()->GetC 359 fVP.GetDefaultTextVisAttributes()->Get 360 (vp.GetBackgroundColour ()!= fVP.GetBac 361 (vp.IsPicking () != fVP.IsPick 362 // Scaling for Open Inventor is done by 363 // needs a kernel visit. (In this resp 364 // OpenGL drivers, where it's done in S 365 (vp.GetScaleFactor () != fVP.GetSca 366 (vp.GetVisAttributesModifiers() != 367 fVP.GetVisAttributesModifiers()) 368 (vp.IsSpecialMeshRendering() != 369 fVP.IsSpecialMeshRendering()) 370 (vp.GetSpecialMeshRenderingOption() != 371 fVP.GetSpecialMeshRenderingOption()) 372 ) 373 return true; 374 375 if (vp.IsDensityCulling () && 376 (vp.GetVisibleDensity () != fVP.GetVis 377 return true; 378 379 if (vp.GetCBDAlgorithmNumber() > 0) { 380 if (vp.GetCBDParameters().size() != fVP. 381 else if (vp.GetCBDParameters() != fVP.Ge 382 } 383 384 if (vp.IsSection () && 385 (vp.GetSectionPlane () != fVP.GetSecti 386 return true; 387 388 if (vp.IsCutaway ()) { 389 if (vp.GetCutawayMode() != fVP.GetCutawa 390 if (vp.GetCutawayPlanes ().size () != 391 fVP.GetCutawayPlanes ().size ()) ret 392 for (size_t i = 0; i < vp.GetCutawayPlan 393 if (vp.GetCutawayPlanes()[i] != fVP.GetC 394 return true; 395 } 396 397 if (vp.IsExplode () && 398 (vp.GetExplodeFactor () != fVP.GetExpl 399 return true; 400 401 if (vp.IsSpecialMeshRendering() && 402 (vp.GetSpecialMeshVolumes() != fVP.Get 403 return true; 404 405 return false; 406 } 407 // void keyPressEvent (KeyEvent*); 408 // void keyReleaseEvent (KeyEvent*); 409 // void mouseDoubleClickEvent(MouseEvent*); 410 // void mouseMoveEvent (MouseEvent*); 411 // void mousePressEvent (MouseEvent*); 412 // void mouseReleaseEvent (MouseEvent*); 413 // void wheelEvent (WheelEvent*); 414 415 protected: 416 void CreateSG(tools::sg::base_camera* a_came 417 tools::sg::group& _parent = fSGViewer->sg( 418 _parent.clear(); 419 420 ////////////////////////////////////////// 421 /// 2D scene graph: ////////////////////// 422 ////////////////////////////////////////// 423 tools::sg::separator* scene_2D = new tools 424 _parent.add(scene_2D); 425 scene_2D->add(new tools::sg::noderef(fSGSc 426 scene_2D->add(new tools::sg::noderef(fSGSc 427 428 ////////////////////////////////////////// 429 /// 3D scene graph: ////////////////////// 430 ////////////////////////////////////////// 431 tools::sg::separator* scene_3D = new tools 432 _parent.add(scene_3D); 433 434 scene_3D->add(a_camera); 435 436 {tools::sg::torche* light = new tools::sg:: 437 light->on = true; 438 light->direction = tools::vec3f(-a_light_d 439 light->ambient = tools::colorf(0.2f,0.2f,0 440 light->color = tools::colorf(0.8f,0.8f,0.8 441 scene_3D->add(light);} 442 443 {tools::sg::blend* blend = new tools::sg::b 444 blend->on = true; //to handle transparency 445 scene_3D->add(blend);} 446 447 scene_3D->add(new tools::sg::noderef(fSGSc 448 scene_3D->add(new tools::sg::noderef(fSGSc 449 } 450 451 void Export(const G4String& a_format,const G 452 if(!fSGViewer) return; 453 const G4Colour& back_color = fVP.GetBackgr 454 bool top_to_bottom = false; //if using to 455 if(!tools::sg::write_paper(G4cout,f_gl2ps_ 456 tools::fpng::write,tools:: 457 float(back_color.GetRed()) 458 fSGViewer->sg(),fSGViewer- 459 a_file,a_format,a_do_trans 460 G4cout << "G4ToolsSGViewer::Export: writ 461 return; 462 } 463 } 464 465 protected: 466 class Messenger: public G4VVisCommand { 467 public: 468 static void Create() {static Messenger s_m 469 private: 470 Messenger() { 471 G4UIparameter* parameter; 472 //////////////////////////////////////// 473 //////////////////////////////////////// 474 write_scene = new G4UIcommand("/vis/tsg/ 475 write_scene->SetGuidance("Write the cont 476 write_scene->SetGuidance("Default file i 477 write_scene->SetGuidance("Available form 478 write_scene->SetGuidance("- gl2ps_eps: g 479 write_scene->SetGuidance("- gl2ps_ps: g 480 write_scene->SetGuidance("- gl2ps_pdf: g 481 write_scene->SetGuidance("- gl2ps_svg: g 482 write_scene->SetGuidance("- gl2ps_tex: g 483 write_scene->SetGuidance("- gl2ps_pgf: g 484 write_scene->SetGuidance("- zb_ps: tools 485 write_scene->SetGuidance("- zb_png: tool 486 write_scene->SetGuidance("- zb_jpeg: too 487 488 parameter = new G4UIparameter("format",' 489 parameter->SetDefaultValue("gl2ps_eps"); 490 write_scene->SetParameter (parameter); 491 492 parameter = new G4UIparameter("file",'s' 493 parameter->SetDefaultValue("out.eps"); 494 write_scene->SetParameter (parameter); 495 496 parameter = new G4UIparameter ("do_tran 497 parameter->SetDefaultValue ("true"); 498 write_scene->SetParameter (parameter); 499 500 } 501 virtual ~Messenger() { 502 delete write_scene; 503 } 504 public: 505 virtual void SetNewValue(G4UIcommand* a_cm 506 G4VisManager::Verbosity verbosity = GetV 507 G4VViewer* viewer = GetVisManager()->Get 508 if (!viewer) { 509 if (verbosity >= G4VisManager::errors) 510 return; 511 } 512 G4ToolsSGViewer* tsg_viewer = dynamic_ca 513 if(!tsg_viewer) { 514 G4cout << "G4ToolsSGViewer::SetNewValu 515 << " current viewer is not a G4 516 return; 517 } 518 std::vector<std::string> args; 519 tools::double_quotes_tokenize(a_value,ar 520 if(args.size()!=a_cmd->GetParameterEntri 521 if(a_cmd==write_scene) { 522 G4bool do_transparency = G4UIcommand:: 523 tsg_viewer->Export(args[0],args[1],do_ 524 } 525 } 526 private: 527 G4UIcommand* write_scene; 528 }; 529 530 protected: 531 SG_SESSION& fSGSession; 532 G4ToolsSGSceneHandler& fSGSceneHandler; 533 SG_VIEWER* fSGViewer; 534 G4ViewParameters fLastVP; // Memory for mak 535 536 G4bool fKeyPressed; 537 G4bool fKeyShift; 538 G4bool fMousePressed; 539 G4double fMousePressedX, fMousePressedY; 540 541 tools::sg::zb_manager f_zb_mgr; 542 tools::sg::gl2ps_manager f_gl2ps_mgr; 543 544 }; 545 546 #endif 547