// // ******************************************************************** // * License and Disclaimer * // * * // * The Geant4 software is copyright of the Copyright Holders of * // * the Geant4 Collaboration. It is provided under the terms and * // * conditions of the Geant4 Software License, included in the file * // * LICENSE and available at http://cern.ch/geant4/license . These * // * include a list of copyright holders. * // * * // * Neither the authors of this software system, nor their employing * // * institutes,nor the agencies providing financial support for this * // * work make any representation or warranty, express or implied, * // * regarding this software system or assume any liability for its * // * use. Please see the license in the file LICENSE and URL above * // * for the full disclaimer and the limitation of liability. * // * * // * This code implementation is the result of the scientific and * // * technical work of the GEANT4 collaboration. * // * By using, copying, modifying or distributing the software (or * // * any work based on the software) you agree to acknowledge its * // * use in resulting scientific publications, and indicate your * // * acceptance of all terms of the Geant4 Software license. * // ******************************************************************** // // // $Id: G4OpenGLViewer.cc 75567 2013-11-04 11:35:11Z gcosmo $ // // // Andrew Walkden 27th March 1996 // OpenGL view - opens window, hard copy, etc. #ifdef G4VIS_BUILD_OPENGL_DRIVER #include "G4ios.hh" #include "G4SystemOfUnits.hh" #include "G4OpenGLViewer.hh" #include "G4OpenGLSceneHandler.hh" #include "G4OpenGLTransform3D.hh" #include "G4OpenGL2PSAction.hh" #include "G4Scene.hh" #include "G4VisExtent.hh" #include "G4LogicalVolume.hh" #include "G4VSolid.hh" #include "G4Point3D.hh" #include "G4Normal3D.hh" #include "G4Plane3D.hh" #include "G4AttHolder.hh" #include "G4AttCheck.hh" #include "G4Text.hh" #ifdef G4VIS_BUILD_OPENGLWT_DRIVER // We need to have a Wt gl drawer because we will draw inside the WtGL component (ImmediateWtViewer) #include "G4OpenGLWtDrawer.hh" #endif // GL2PS #include "Geant4_gl2ps.h" #include G4int G4OpenGLViewer::fPrintSizeX = -1; G4int G4OpenGLViewer::fPrintSizeY = -1; G4String G4OpenGLViewer::fPrintFilename = "G4OpenGL"; int G4OpenGLViewer::fPrintFilenameIndex = 0; G4OpenGLViewer::G4OpenGLViewer (G4OpenGLSceneHandler& scene): G4VViewer (scene, -1), #ifdef G4VIS_BUILD_OPENGLWT_DRIVER fWtDrawer(NULL), #endif fPrintColour (true), fVectoredPs (true), fOpenGLSceneHandler(scene), background (G4Colour(0.,0.,0.)), transparency_enabled (true), antialiasing_enabled (false), haloing_enabled (false), fStartTime(-DBL_MAX), fEndTime(DBL_MAX), fFadeFactor(0.), fDisplayHeadTime(false), fDisplayHeadTimeX(-0.9), fDisplayHeadTimeY(-0.9), fDisplayHeadTimeSize(24.), fDisplayHeadTimeRed(0.), fDisplayHeadTimeGreen(1.), fDisplayHeadTimeBlue(1.), fDisplayLightFront(false), fDisplayLightFrontX(0.), fDisplayLightFrontY(0.), fDisplayLightFrontZ(0.), fDisplayLightFrontT(0.), fDisplayLightFrontRed(0.), fDisplayLightFrontGreen(1.), fDisplayLightFrontBlue(0.), fRot_sens(1.), fPan_sens(0.01), fWinSize_x(0), fWinSize_y(0), fPointSize (0), fSizeHasChanged(0), fGl2psDefaultLineWith(1), fGl2psDefaultPointSize(2) { #ifdef G4DEBUG_VIS_OGL printf("G4OpenGLViewer:: Creation\n"); #endif // Make changes to view parameters for OpenGL... fVP.SetAutoRefresh(true); fDefaultVP.SetAutoRefresh(true); fGL2PSAction = new G4OpenGL2PSAction(); // glClearColor (0.0, 0.0, 0.0, 0.0); // glClearDepth (1.0); // glDisable (GL_BLEND); // glDisable (GL_LINE_SMOOTH); // glDisable (GL_POLYGON_SMOOTH); } G4OpenGLViewer::~G4OpenGLViewer () { delete fGL2PSAction; } void G4OpenGLViewer::InitializeGLView () { #ifdef G4OPENGL_VERSION_2 const char *fragmentShaderSrc = "#ifdef GL_ES\n" "precision highp float;\n" "#endif\n" "\n" "varying vec3 vLightWeighting;\n" "uniform vec4 uPointColor; // Point Color\n" "\n" "void main(void) {\n" " vec4 matColor = uPointColor;\n" " gl_FragColor = vec4(matColor.rgb, matColor.a);\n" "}\n"; const char *vertexShaderSrc = "attribute vec3 aVertexPosition;\n" "attribute vec3 aVertexNormal;\n" "\n" "uniform mat4 uMVMatrix; // [M]odel[V]iew matrix\n" "uniform mat4 uCMatrix; // Client-side manipulated [C]amera matrix\n" "uniform mat4 uPMatrix; // Perspective [P]rojection matrix\n" "uniform mat4 uNMatrix; // [N]ormal transformation\n" "// uNMatrix is the transpose of the inverse of uCMatrix * uMVMatrix\n" "uniform mat4 uTMatrix; // [T]ransformation matrix\n" "uniform float uPointSize; // Point size\n" "\n" "varying vec3 vLightWeighting;\n" "\n" "void main(void) {\n" " // Calculate the position of this vertex\n" " gl_Position = uPMatrix * uCMatrix * uMVMatrix * uTMatrix * vec4(aVertexPosition, 1.0);\n" "\n" " // Phong shading\n" " vec3 transformedNormal = normalize((uNMatrix * vec4(normalize(aVertexNormal), 0)).xyz);\n" " vec3 lightingDirection = normalize(vec3(1, 1, 1));\n" " float directionalLightWeighting = max(dot(transformedNormal, lightingDirection), 0.0);\n" " vec3 uAmbientLightColor = vec3(0.2, 0.2, 0.2);\n" " vec3 uDirectionalColor = vec3(0.8, 0.8, 0.8);\n" " gl_PointSize = uPointSize;\n" " vLightWeighting = uAmbientLightColor + uDirectionalColor * directionalLightWeighting;\n" "}\n"; vertexShader_ = vertexShaderSrc; fragmentShader_ = fragmentShaderSrc; // First, load a simple shader Shader fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); const char *frag = fragmentShader_.c_str(); glShaderSource(fragmentShader, 1, &frag, NULL); glCompileShader(fragmentShader); Shader vertexShader = glCreateShader(GL_VERTEX_SHADER); const char *vert = vertexShader_.c_str(); glShaderSource(vertexShader, 1, &vert, NULL); glCompileShader(vertexShader); shaderProgram_ = glCreateProgram(); glAttachShader(shaderProgram_, vertexShader); glAttachShader(shaderProgram_, fragmentShader); glLinkProgram(shaderProgram_); glUseProgram(shaderProgram_); // UniformLocation uColor = getUniformLocation(shaderProgram_, "uColor"); // uniform4fv(uColor, [0.0, 0.3, 0.0, 1.0]); // Extract the references to the attributes from the shader. vertexPositionAttribute_ = glGetAttribLocation(shaderProgram_, "aVertexPosition"); glEnableVertexAttribArray(vertexPositionAttribute_); // Extract the references the uniforms from the shader pMatrixUniform_ = glGetUniformLocation(shaderProgram_, "uPMatrix"); cMatrixUniform_ = glGetUniformLocation(shaderProgram_, "uCMatrix"); mvMatrixUniform_ = glGetUniformLocation(shaderProgram_, "uMVMatrix"); nMatrixUniform_ = glGetUniformLocation(shaderProgram_, "uNMatrix"); tMatrixUniform_ = glGetUniformLocation(shaderProgram_, "uTMatrix"); #endif #ifdef G4DEBUG_VIS_OGL printf("G4OpenGLViewer::InitializeGLView\n"); #endif fWinSize_x = fVP.GetWindowSizeHintX(); fWinSize_y = fVP.GetWindowSizeHintY(); glClearColor (0.0, 0.0, 0.0, 0.0); glClearDepth (1.0); glDisable (GL_LINE_SMOOTH); glDisable (GL_POLYGON_SMOOTH); // clear the buffers and window? ClearView (); FinishView (); glDepthFunc (GL_LEQUAL); glDepthMask (GL_TRUE); glEnable (GL_BLEND); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); #ifdef G4DEBUG_VIS_OGL printf("G4OpenGLViewer::InitializeGLView END\n"); #endif } void G4OpenGLViewer::ClearView () { #ifdef G4DEBUG_VIS_OGL printf("G4OpenGLViewer::ClearView\n"); #endif glClearColor (background.GetRed(), background.GetGreen(), background.GetBlue(), 1.); glClearDepth (1.0); //Below line does not compile with Mesa includes. //glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear (GL_COLOR_BUFFER_BIT); glClear (GL_DEPTH_BUFFER_BIT); glClear (GL_STENCIL_BUFFER_BIT); #ifdef G4DEBUG_VIS_OGL printf("G4OpenGLViewer::ClearView flush\n"); #endif glFlush (); } void G4OpenGLViewer::ResizeWindow(unsigned int aWidth, unsigned int aHeight) { if ((fWinSize_x != aWidth) || (fWinSize_y != aHeight)) { fWinSize_x = aWidth; fWinSize_y = aHeight; fSizeHasChanged = true; } else { fSizeHasChanged = false; } } /** * Set the viewport of the scene * MAXIMUM SIZE is : * GLint dims[2]; * glGetIntegerv(GL_MAX_VIEWPORT_DIMS, dims); */ void G4OpenGLViewer::ResizeGLView() { #ifdef G4DEBUG_VIS_OGL printf("G4OpenGLViewer::ResizeGLView %d %d %#lx\n",fWinSize_x,fWinSize_y,(unsigned long)this); #endif // Check size GLint dims[2]; dims[0] = 0; dims[1] = 0; glGetIntegerv(GL_MAX_VIEWPORT_DIMS, dims); if ((dims[0] !=0 ) && (dims[1] !=0)) { if (fWinSize_x > (unsigned)dims[0]) { G4cerr << "Try to resize view greater than max X viewport dimension. Desired size "< (unsigned)dims[1]) { G4cerr << "Try to resize view greater than max Y viewport dimension. Desired size "< fWinSize_x) { ratioX = ((G4double)fWinSize_y) / ((G4double)fWinSize_x); } if (fWinSize_x > fWinSize_y) { ratioY = ((G4double)fWinSize_x) / ((G4double)fWinSize_y); } // Get radius of scene, etc. // Note that this procedure properly takes into account zoom, dolly and pan. const G4Point3D targetPoint = fSceneHandler.GetScene()->GetStandardTargetPoint() + fVP.GetCurrentTargetPoint (); G4double radius = fSceneHandler.GetScene()->GetExtent().GetExtentRadius(); if(radius<=0.) radius = 1.; const G4double cameraDistance = fVP.GetCameraDistance (radius); const G4Point3D cameraPosition = targetPoint + cameraDistance * fVP.GetViewpointDirection().unit(); const GLdouble pnear = fVP.GetNearDistance (cameraDistance, radius); const GLdouble pfar = fVP.GetFarDistance (cameraDistance, pnear, radius); const GLdouble right = fVP.GetFrontHalfHeight (pnear, radius) * ratioY; const GLdouble left = -right; const GLdouble top = fVP.GetFrontHalfHeight (pnear, radius) * ratioX; const GLdouble bottom = -top; // FIXME ResizeGLView(); //SHOULD SetWindowsSizeHint()... glMatrixMode (GL_PROJECTION); // set up Frustum. glLoadIdentity(); const G4Vector3D scaleFactor = fVP.GetScaleFactor(); glScaled(scaleFactor.x(),scaleFactor.y(),scaleFactor.z()); if (fVP.GetFieldHalfAngle() == 0.) { glOrtho (left, right, bottom, top, pnear, pfar); } else { glFrustum (left, right, bottom, top, pnear, pfar); } glMatrixMode (GL_MODELVIEW); // apply further transformations to scene. glLoadIdentity(); const G4Normal3D& upVector = fVP.GetUpVector (); G4Point3D gltarget; if (cameraDistance > 1.e-6 * radius) { gltarget = targetPoint; } else { gltarget = targetPoint - radius * fVP.GetViewpointDirection().unit(); } const G4Point3D& pCamera = cameraPosition; // An alias for brevity. gluLookAt (pCamera.x(), pCamera.y(), pCamera.z(), // Viewpoint. gltarget.x(), gltarget.y(), gltarget.z(), // Target point. upVector.x(), upVector.y(), upVector.z()); // Up vector. // Light position is "true" light direction, so must come after gluLookAt. glLightfv (GL_LIGHT0, GL_POSITION, lightPosition); // OpenGL no longer seems to reconstruct clipped edges, so, when the // BooleanProcessor is up to it, abandon this and use generic // clipping in G4OpenGLSceneHandler::CreateSectionPolyhedron. Also, // force kernel visit on change of clipping plane in // G4OpenGLStoredViewer::CompareForKernelVisit. //if (fVP.IsSection () ) { // pair of back to back clip planes. if (false) { // pair of back to back clip planes. const G4Plane3D& sp = fVP.GetSectionPlane (); double sArray[4]; sArray[0] = sp.a(); sArray[1] = sp.b(); sArray[2] = sp.c(); sArray[3] = sp.d() + radius * 1.e-05; glClipPlane (GL_CLIP_PLANE0, sArray); glEnable (GL_CLIP_PLANE0); sArray[0] = -sp.a(); sArray[1] = -sp.b(); sArray[2] = -sp.c(); sArray[3] = -sp.d() + radius * 1.e-05; glClipPlane (GL_CLIP_PLANE1, sArray); glEnable (GL_CLIP_PLANE1); } else { glDisable (GL_CLIP_PLANE0); glDisable (GL_CLIP_PLANE1); } // What we call intersection of cutaways is easy in OpenGL. You // just keep cutting. Unions are more tricky - you have to have // multiple passes and this is handled in // G4OpenGLImmediate/StoredViewer::ProcessView. const G4Planes& cutaways = fVP.GetCutawayPlanes(); size_t nPlanes = cutaways.size(); if (fVP.IsCutaway() && fVP.GetCutawayMode() == G4ViewParameters::cutawayIntersection && nPlanes > 0) { double a[4]; a[0] = cutaways[0].a(); a[1] = cutaways[0].b(); a[2] = cutaways[0].c(); a[3] = cutaways[0].d(); glClipPlane (GL_CLIP_PLANE2, a); glEnable (GL_CLIP_PLANE2); if (nPlanes > 1) { a[0] = cutaways[1].a(); a[1] = cutaways[1].b(); a[2] = cutaways[1].c(); a[3] = cutaways[1].d(); glClipPlane (GL_CLIP_PLANE3, a); glEnable (GL_CLIP_PLANE3); } if (nPlanes > 2) { a[0] = cutaways[2].a(); a[1] = cutaways[2].b(); a[2] = cutaways[2].c(); a[3] = cutaways[2].d(); glClipPlane (GL_CLIP_PLANE4, a); glEnable (GL_CLIP_PLANE4); } } else { glDisable (GL_CLIP_PLANE2); glDisable (GL_CLIP_PLANE3); glDisable (GL_CLIP_PLANE4); } // Background. background = fVP.GetBackgroundColour (); } void G4OpenGLViewer::ResetView () { G4VViewer::ResetView(); fRot_sens = 1; fPan_sens = 0.01; } void G4OpenGLViewer::HaloingFirstPass () { //To perform haloing, first Draw all information to the depth buffer //alone, using a chunky line width, and then Draw all info again, to //the colour buffer, setting a thinner line width an the depth testing //function to less than or equal, so if two lines cross, the one //passing behind the other will not pass the depth test, and so not //get rendered either side of the infront line for a short distance. //First, disable writing to the colo(u)r buffer... glColorMask (GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); //Now enable writing to the depth buffer... glDepthMask (GL_TRUE); glDepthFunc (GL_LESS); glClearDepth (1.0); //Finally, set the line width to something wide... ChangeLineWidth(3.0); } void G4OpenGLViewer::HaloingSecondPass () { //And finally, turn the colour buffer back on with a sesible line width... glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glDepthFunc (GL_LEQUAL); ChangeLineWidth(1.0); } void G4OpenGLViewer::Pick(GLdouble x, GLdouble y) { //G4cout << "X: " << x << ", Y: " << y << G4endl; const G4int BUFSIZE = 512; GLuint selectBuffer[BUFSIZE]; glSelectBuffer(BUFSIZE, selectBuffer); glRenderMode(GL_SELECT); glInitNames(); glPushName(0); glMatrixMode(GL_PROJECTION); G4double currentProjectionMatrix[16]; glGetDoublev(GL_PROJECTION_MATRIX, currentProjectionMatrix); glPushMatrix(); glLoadIdentity(); GLint viewport[4]; glGetIntegerv(GL_VIEWPORT, viewport); // Define 5x5 pixel pick area gluPickMatrix(x, viewport[3] - y, 5., 5., viewport); glMultMatrixd(currentProjectionMatrix); glMatrixMode(GL_MODELVIEW); DrawView(); GLint hits = glRenderMode(GL_RENDER); if (hits < 0) G4cout << "Too many hits. Zoom in to reduce overlaps." << G4endl; else if (hits > 0) { G4cout << hits << " hit(s)" << G4endl; GLuint* p = selectBuffer; for (GLint i = 0; i < hits; ++i) { GLuint nnames = *p++; // This bit of debug code or... //GLuint zmin = *p++; //GLuint zmax = *p++; //G4cout << "Hit " << i << ": " << nnames << " names" // << "\nzmin: " << zmin << ", zmax: " << zmax << G4endl; // ...just increment the pointer p++; p++; for (GLuint j = 0; j < nnames; ++j) { GLuint name = *p++; G4cout << "Hit: " << i << ", Sub-hit: " << j << ", PickName: " << name << G4endl; std::map::iterator iter = fOpenGLSceneHandler.fPickMap.find(name); if (iter != fOpenGLSceneHandler.fPickMap.end()) { G4AttHolder* attHolder = iter->second; if(attHolder && attHolder->GetAttDefs().size()) { for (size_t iAtt = 0; iAtt < attHolder->GetAttDefs().size(); ++iAtt) { G4cout << G4AttCheck(attHolder->GetAttValues()[iAtt], attHolder->GetAttDefs()[iAtt]); } } } } G4cout << G4endl; } } glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); } GLubyte* G4OpenGLViewer::grabPixels (int inColor, unsigned int width, unsigned int height) { GLubyte* buffer; GLint swapbytes, lsbfirst, rowlength; GLint skiprows, skippixels, alignment; GLenum format; int size; if (inColor) { format = GL_RGB; size = width*height*3; } else { format = GL_LUMINANCE; size = width*height*1; } buffer = new GLubyte[size]; if (buffer == NULL) return NULL; glGetIntegerv (GL_UNPACK_SWAP_BYTES, &swapbytes); glGetIntegerv (GL_UNPACK_LSB_FIRST, &lsbfirst); glGetIntegerv (GL_UNPACK_ROW_LENGTH, &rowlength); glGetIntegerv (GL_UNPACK_SKIP_ROWS, &skiprows); glGetIntegerv (GL_UNPACK_SKIP_PIXELS, &skippixels); glGetIntegerv (GL_UNPACK_ALIGNMENT, &alignment); glPixelStorei (GL_UNPACK_SWAP_BYTES, GL_FALSE); glPixelStorei (GL_UNPACK_LSB_FIRST, GL_FALSE); glPixelStorei (GL_UNPACK_ROW_LENGTH, 0); glPixelStorei (GL_UNPACK_SKIP_ROWS, 0); glPixelStorei (GL_UNPACK_SKIP_PIXELS, 0); glPixelStorei (GL_UNPACK_ALIGNMENT, 1); glReadBuffer(GL_FRONT); glReadPixels (0, 0, (GLsizei)width, (GLsizei)height, format, GL_UNSIGNED_BYTE, (GLvoid*) buffer); glPixelStorei (GL_UNPACK_SWAP_BYTES, swapbytes); glPixelStorei (GL_UNPACK_LSB_FIRST, lsbfirst); glPixelStorei (GL_UNPACK_ROW_LENGTH, rowlength); glPixelStorei (GL_UNPACK_SKIP_ROWS, skiprows); glPixelStorei (GL_UNPACK_SKIP_PIXELS, skippixels); glPixelStorei (GL_UNPACK_ALIGNMENT, alignment); return buffer; } void G4OpenGLViewer::printEPS() { bool res; #ifdef G4DEBUG_VIS_OGL printf("G4OpenGLViewer::printEPS file:%s Vec:%d Name:%s\n",getRealPrintFilename().c_str(),fVectoredPs,GetName().c_str()); #endif // Change the LC_NUMERIC value in order to have "." separtor and not "," // This case is only useful for French, Canadien... size_t len = strlen(setlocale(LC_NUMERIC,NULL)); char* oldLocale = (char*)(malloc(len+1)); if(oldLocale!=NULL) strncpy(oldLocale,setlocale(LC_NUMERIC,NULL),len); setlocale(LC_NUMERIC,"C"); if (fVectoredPs) { res = printVectoredEPS(); } else { res = printNonVectoredEPS(); } // restore the local if (oldLocale) { setlocale(LC_NUMERIC,oldLocale); free(oldLocale); } if (res == false) { G4cerr << "Error while saving file... "<0; i--) { fprintf (fp, "%02hx ", (unsigned short)(*(curpix++))); if (++pos >= 32) { fprintf (fp, "\n"); pos = 0; } } if (pos) fprintf (fp, "\n"); fprintf (fp, "grestore\n"); fprintf (fp, "showpage\n"); delete [] pixels; fclose (fp); // Reset for next time (useful is size change) // fPrintSizeX = -1; // fPrintSizeY = -1; return true; } /** Return if gl2ps is currently writing */ bool G4OpenGLViewer::isGl2psWriting() { if (!fGL2PSAction) return false; if (fGL2PSAction->fileWritingEnabled()) { return true; } return false; } /* Draw Gl2Ps text if needed */ void G4OpenGLViewer::DrawText(const G4Text& g4text) { // gl2ps or GL window ? if (isGl2psWriting()) { G4VSceneHandler::MarkerSizeType sizeType; G4double size = fSceneHandler.GetMarkerSize(g4text,sizeType); G4Point3D position = g4text.GetPosition(); G4String textString = g4text.GetText(); const char* textCString = textString.c_str(); glRasterPos3d(position.x(),position.y(),position.z()); GLint align = GL2PS_TEXT_B; switch (g4text.GetLayout()) { case G4Text::left: align = GL2PS_TEXT_BL; break; case G4Text::centre: align = GL2PS_TEXT_B; break; case G4Text::right: align = GL2PS_TEXT_BR; } gl2psTextOpt(textCString,"Times-Roman",GLshort(size),align,0); } else { static G4int callCount = 0; ++callCount; //if (callCount <= 10 || callCount%100 == 0) { if (callCount <= 1) { G4cout << "G4OpenGLViewer::DrawText: Not implemented for \"" << fName << "\"\n Called with " << g4text << G4endl; } } } /** Change PointSize on gl2ps if needed */ void G4OpenGLViewer::ChangePointSize(G4double size) { if (isGl2psWriting()) { fGL2PSAction->setPointSize(int(size)); } else { glPointSize (size); } } /** Change LineSize on gl2ps if needed */ void G4OpenGLViewer::ChangeLineWidth(G4double width) { if (isGl2psWriting()) { fGL2PSAction->setLineWidth(int(width)); } else { glLineWidth (width); } } bool G4OpenGLViewer::printGl2PS() { int width = getRealPrintSizeX(); int height = getRealPrintSizeY(); if (!fGL2PSAction) return false; fGL2PSAction->setFileName(getRealPrintFilename().c_str()); // try to resize int X = fWinSize_x; int Y = fWinSize_y; fWinSize_x = width; fWinSize_y = height; // Laurent G. 16/03/10 : Not the good way to do. // We should draw in a new offscreen context instead of // resizing and drawing in current window... // This should be solve when we will do an offscreen method // to render OpenGL // See : // http://developer.apple.com/Mac/library/documentation/GraphicsImaging/Conceptual/OpenGL-MacProgGuide/opengl_offscreen/opengl_offscreen.html // http://www.songho.ca/opengl/gl_fbo.html ResizeGLView(); bool extendBuffer = true; bool endWriteAction = false; bool beginWriteAction = true; while ((extendBuffer) && (! endWriteAction)) { beginWriteAction = fGL2PSAction->enableFileWriting(); if (beginWriteAction) { // Set the viewport // fGL2PSAction->setViewport(0, 0, getRealPrintSizeX(),getRealPrintSizeY()); // By default, we choose the line width (trajectories...) fGL2PSAction->setLineWidth(fGl2psDefaultLineWith); // By default, we choose the point size (markers...) fGL2PSAction->setPointSize(fGl2psDefaultPointSize); DrawView (); endWriteAction = fGL2PSAction->disableFileWriting(); } if ((! endWriteAction) || (! beginWriteAction)) { extendBuffer = fGL2PSAction->extendBufferSize(); } } fGL2PSAction->resetBufferSizeParameters(); if (!extendBuffer ) { G4cerr << "gl2ps buffer size is not big enough to print this geometry. Thy to extend it. No output produced"<< G4endl; } if (!beginWriteAction ) { G4cerr << "Error while writing in the file "< dims[0]){ return dims[0]; } } if (fPrintSizeX < -1){ return 0; } return fPrintSizeX; } G4int G4OpenGLViewer::getRealPrintSizeY() { if (fPrintSizeY == -1) { return fWinSize_y; } GLint dims[2]; glGetIntegerv(GL_MAX_VIEWPORT_DIMS, dims); // L.Garnier 01-2010: Some problems with mac 10.6 if ((dims[0] !=0 ) && (dims[1] !=0)) { if (fPrintSizeY > dims[1]){ return dims[1]; } } if (fPrintSizeY < -1){ return 0; } return fPrintSizeY; } void G4OpenGLViewer::setPrintSize(G4int X, G4int Y) { fPrintSizeX = X; fPrintSizeY = Y; } void G4OpenGLViewer::setPrintFilename(G4String name,G4bool inc) { if (name != "") { fPrintFilename = name; } else { fPrintFilename = "G4OpenGL"; // by default } if (inc) { fPrintFilenameIndex=0; } else { fPrintFilenameIndex=-1; } } std::string G4OpenGLViewer::getRealPrintFilename() { std::string temp = fPrintFilename; if (fPrintFilenameIndex != -1) { temp += std::string("_"); std::ostringstream os; os << fPrintFilenameIndex; std::string nb_str = os.str(); temp += nb_str; } temp += ".eps"; return temp; } GLdouble G4OpenGLViewer::getSceneNearWidth() { if (!fSceneHandler.GetScene()) { return 0; } const G4Point3D targetPoint = fSceneHandler.GetScene()->GetStandardTargetPoint() + fVP.GetCurrentTargetPoint (); G4double radius = fSceneHandler.GetScene()->GetExtent().GetExtentRadius(); if(radius<=0.) radius = 1.; const G4double cameraDistance = fVP.GetCameraDistance (radius); const GLdouble pnear = fVP.GetNearDistance (cameraDistance, radius); return 2 * fVP.GetFrontHalfHeight (pnear, radius); } GLdouble G4OpenGLViewer::getSceneFarWidth() { if (!fSceneHandler.GetScene()) { return 0; } const G4Point3D targetPoint = fSceneHandler.GetScene()->GetStandardTargetPoint() + fVP.GetCurrentTargetPoint (); G4double radius = fSceneHandler.GetScene()->GetExtent().GetExtentRadius(); if(radius<=0.) radius = 1.; const G4double cameraDistance = fVP.GetCameraDistance (radius); const GLdouble pnear = fVP.GetNearDistance (cameraDistance, radius); const GLdouble pfar = fVP.GetFarDistance (cameraDistance, pnear, radius); return 2 * fVP.GetFrontHalfHeight (pfar, radius); } GLdouble G4OpenGLViewer::getSceneDepth() { if (!fSceneHandler.GetScene()) { return 0; } const G4Point3D targetPoint = fSceneHandler.GetScene()->GetStandardTargetPoint() + fVP.GetCurrentTargetPoint (); G4double radius = fSceneHandler.GetScene()->GetExtent().GetExtentRadius(); if(radius<=0.) radius = 1.; const G4double cameraDistance = fVP.GetCameraDistance (radius); const GLdouble pnear = fVP.GetNearDistance (cameraDistance, radius); return fVP.GetFarDistance (cameraDistance, pnear, radius)- pnear; } void G4OpenGLViewer::rotateScene(G4double dx, G4double dy) { if (fVP.GetRotationStyle() == G4ViewParameters::freeRotation) { rotateSceneInViewDirection(dx,dy); } else { if( dx != 0) { rotateSceneThetaPhi(dx,0); } if( dy != 0) { rotateSceneThetaPhi(0,dy); } } } void G4OpenGLViewer::rotateSceneToggle(G4double dx, G4double dy) { if (fVP.GetRotationStyle() != G4ViewParameters::freeRotation) { rotateSceneInViewDirection(dx,dy); } else { if( dx != 0) { rotateSceneThetaPhi(dx,0); } if( dy != 0) { rotateSceneThetaPhi(0,dy); } } } void G4OpenGLViewer::rotateSceneThetaPhi(G4double dx, G4double dy) { if (!fSceneHandler.GetScene()) { return; } G4Vector3D vp; G4Vector3D up; G4Vector3D xprime; G4Vector3D yprime; G4Vector3D zprime; G4double delta_alpha; G4double delta_theta; G4Vector3D new_vp; G4Vector3D new_up; G4double cosalpha; G4double sinalpha; G4Vector3D a1; G4Vector3D a2; G4Vector3D delta; G4Vector3D viewPoint; //phi spin stuff here vp = fVP.GetViewpointDirection ().unit (); up = fVP.GetUpVector ().unit (); yprime = (up.cross(vp)).unit(); zprime = (vp.cross(yprime)).unit(); if (fVP.GetLightsMoveWithCamera()) { delta_alpha = dy * fRot_sens; delta_theta = -dx * fRot_sens; } else { delta_alpha = -dy * fRot_sens; delta_theta = dx * fRot_sens; } delta_alpha *= deg; delta_theta *= deg; new_vp = std::cos(delta_alpha) * vp + std::sin(delta_alpha) * zprime; // to avoid z rotation flipping // to allow more than 360° rotation if (fVP.GetLightsMoveWithCamera()) { new_up = (new_vp.cross(yprime)).unit(); if (new_vp.z()*vp.z() <0) { new_up.set(new_up.x(),-new_up.y(),new_up.z()); } } else { new_up = up; if (new_vp.z()*vp.z() <0) { new_up.set(new_up.x(),-new_up.y(),new_up.z()); } } fVP.SetUpVector(new_up); //////////////// // Rotates by fixed azimuthal angle delta_theta. cosalpha = new_up.dot (new_vp.unit()); sinalpha = std::sqrt (1. - std::pow (cosalpha, 2)); yprime = (new_up.cross (new_vp.unit())).unit (); xprime = yprime.cross (new_up); // Projection of vp on plane perpendicular to up... a1 = sinalpha * xprime; // Required new projection... a2 = sinalpha * (std::cos (delta_theta) * xprime + std::sin (delta_theta) * yprime); // Required Increment vector... delta = a2 - a1; // So new viewpoint is... viewPoint = new_vp.unit() + delta; fVP.SetViewAndLights (viewPoint); } void G4OpenGLViewer::rotateSceneInViewDirection(G4double dx, G4double dy) { if (!fSceneHandler.GetScene()) { return; } G4Vector3D vp; G4Vector3D up; G4Vector3D xprime; G4Vector3D yprime; G4Vector3D zprime; G4Vector3D new_vp; G4Vector3D new_up; G4Vector3D a1; G4Vector3D a2; G4Vector3D delta; G4Vector3D viewPoint; dx = dx/100; dy = dy/100; //phi spin stuff here #ifdef G4DEBUG_VIS_OGL printf("G4OpenGLViewer::rotateScene dx:%f dy:%f delta:%f\n",dx,dy, fRot_sens); #endif vp = fVP.GetViewpointDirection ().unit(); up = fVP.GetUpVector ().unit(); G4Vector3D zPrimeVector = G4Vector3D(up.y()*vp.z()-up.z()*vp.y(), up.z()*vp.x()-up.x()*vp.z(), up.x()*vp.y()-up.y()*vp.x()); viewPoint = vp/fRot_sens + (zPrimeVector*dx - up*dy) ; new_up = G4Vector3D(viewPoint.y()*zPrimeVector.z()-viewPoint.z()*zPrimeVector.y(), viewPoint.z()*zPrimeVector.x()-viewPoint.x()*zPrimeVector.z(), viewPoint.x()*zPrimeVector.y()-viewPoint.y()*zPrimeVector.x()); G4Vector3D new_upUnit = new_up.unit(); fVP.SetUpVector(new_upUnit); fVP.SetViewAndLights (viewPoint); } #ifdef G4VIS_BUILD_OPENGLWT_DRIVER // Associate the Wt drawer to the OpenGLViewer and the OpenGLSceneHandler void G4OpenGLViewer::setWtDrawer(G4OpenGLWtDrawer* drawer) { fWtDrawer = drawer; try { G4OpenGLSceneHandler& sh = dynamic_cast(fSceneHandler); sh.setWtDrawer(fWtDrawer); } catch(std::bad_cast exp) { } } #endif #endif