/*********************************************************************************************************************** * * Copyright (c) 2010 - 2025 by Tech Soft 3D, Inc. * The information contained herein is confidential and proprietary to Tech Soft 3D, Inc., and considered a trade secret * as defined under civil and criminal statutes. Tech Soft 3D shall pursue its civil and criminal remedies in the event * of unauthorized use or misappropriation of its trade secrets. Use of this information by anyone other than authorized * employees of Tech Soft 3D, Inc. is granted only under a written non-disclosure agreement, expressly prescribing the * scope and manner of such use. * ***********************************************************************************************************************/ /** \file Viewer.cpp This file demonstrates how to programmatically visualize a PRC file with a basic OpenGL program using HOOPS Exchange and the connectors and visitors tools. In the main function, we open the file. Then we traverse once the model in order to retrieve the bounding box of the model. Then we re-traverse the model to draw the different items. ***********************************************************************************************************************/ //#define DIRECT_RENDERING #define INITIALIZE_A3D_API #include #include #include "../common.hpp" #define TF_A3DLIBS #include #include #include #include #include "callback_opengl.h" #include "Matrix.h" #include "trackball.h" #include "TreeTraverse.h" #include "VisitorContainer.h" #include "VisitorTessellation.h" #include "VisitorTransfo.h" #include "VisitorTree.h" #include "Viewer.h" #include "VisitorCascadedAttribute.h" //##################################################################################################################### A3DUns32 mNumberOfViews; A3DUns32 mCurrentViewIndex = ~0U; bool stbDrawView = false; //##################################################################################################################### static A3DStatus DrawModel(const A3DAsmModelFile* pModelFile); //###################################################################################################################### A3DStatus DrawGetBoundingBox(const A3DAsmModelFile* pModelFile, A3DBoundingBoxData* psBoundingBox, const A3DBool bIncludeMarkups = false); //###################################################################################################################### static A3DStatus Draw(const A3DAsmModelFile* pModelFile, const A3DBool bIncludeMarkups = false); //###################################################################################################################### A3DAsmModelFile* ComputeSection(A3DAsmModelFile* pModelFile, A3DPlanarSectionData sSectionParametersData); //###################################################################################################################### void ComputeHLR( A3DAsmModelFile const * pModelFile, A3DMkpView const *pActiveView, A3DHLRViewPlaneData const &sHLRViewPlaneData, GLuint &uiHLRDisplayList, GLuint &uiHLRTanEdgeDisplayList, GLuint &uiHLRHiddenDisplayList, GLuint &uiHLRHiddenTanEdgeDisplayList, GLuint &uiHLRSectionDisplayList); //###################################################################################################################### static bool stbTrackBallAnimate = GL_FALSE; //###################################################################################################################### static GLsizei stiXScreen = 0; static GLsizei stiYScreen = 0; static GLdouble stdXPan = 0.0; static GLdouble stdYPan = 0.0; static GLdouble stdZoom = 1.0; static GLdouble stdXPan_Save = 0.0; static GLdouble stdYPan_Save = 0.0; static GLdouble stdZoom_Save = 1.0; static GLint staiViewport[4]; //###################################################################################################################### static bool stbLButtonDown = false; static bool stbRButtonDown = false; //###################################################################################################################### static GLuint stuiModelFileDisplayList = 0; static GLuint stuiMarkupsDisplayList = 0; static GLuint stuiTriedronDisplayList = 0; static GLuint stuiHLRDisplayList = 0; static GLuint stuiHLRTanEdgeDisplayList = 0; static GLuint stuiHLRHiddenDisplayList = 0; static GLuint stuiHLRHiddenTanEdgeDisplayList = 0; static GLuint stuiHLRSectionDisplayList = 0; //###################################################################################################################### static GLfloat stafLightDiffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f }; static GLfloat stafLightAmbient[] = { 0.1f, 0.1f, 0.1f, 1.0f }; static GLfloat stafLightPosition[] = { 0.0f, 0.0f, 1.0f, 0.0f }; //###################################################################################################################### static GLfloat stafMaterialDiffuse[] = { 0.6f, 0.6f, 0.6f, 1.0f }; static GLfloat stafMaterialSpecular[] = { 1.0f, 1.0f, 1.0f, 1.0f }; static GLfloat stafMaterialShininess[] = { 100.0f }; //###################################################################################################################### static GLfloat stafTextColor[] = { 1.0f, 1.0f, 0.0f, 1.0f }; static GLfloat stafErrorTextColor[] = { 1.0f, 0.0f, 0.0f, 1.0f }; //###################################################################################################################### static unsigned int stuiClearColor = 0xB2B2B2; //###################################################################################################################### static GLint staiWinSize[2]; static GLint staiWinPosition[2]; static bool stbFullScreen = false; //###################################################################################################################### static clock_t stiStart, stiEnd; static float stfElapsed; static unsigned int stiNbFrames = 0; static float stfFps = 0.0f; //###################################################################################################################### static A3DUTF8Char stpcWinTitle[_MAX_PATH]; //###################################################################################################################### static bool stbDisplayHelp = false; static bool stbDisplayInfos = false; //static bool stbDisplayMarkups = true; static bool stbDisplaySection = false; static bool stbDisplayHLR = false; static bool stbDisplayHLRHidden = true; static bool stbDisplayHLRTanEdge = true; static bool stbDisplayHLRSection = true; static bool stbDoubleSideRendering = true; static A3DVector3dData origin3d; static A3DVector3dData direction3d; static A3DVector3dData stHLROrigin; //###################################################################################################################### #define TRIEDRON_SIZE 40.0 //###################################################################################################################### #define A3DGL_MIN(a,b) (((a) < (b)) ? (a) : (b)) #define A3DGL_MAX(a,b) (((a) > (b)) ? (a) : (b)) static int stTraverseSet(A3DRiSet* pSet, A3DRiSet ** ppRISectionElements); //###################################################################################################################### class A3DPRCViewerGLInfo { public: A3DBoundingBoxData sBoundingBox; double dBoundingBoxRadius; A3DVector3dData sBoundingBoxCenter; public: //################################################################################################################## A3DPRCViewerGLInfo() { Init(); } //################################################################################################################## void Init() { A3D_INITIALIZE_DATA(A3DBoundingBoxData, sBoundingBox); A3D_INITIALIZE_DATA(A3DVector3dData, sBoundingBoxCenter); dBoundingBoxRadius = 0.0; } //################################################################################################################## void operator=(const A3DPRCViewerGLInfo& sOther) { sBoundingBox.m_sMin.m_dX = sOther.sBoundingBox.m_sMin.m_dX; sBoundingBox.m_sMin.m_dY = sOther.sBoundingBox.m_sMin.m_dY; sBoundingBox.m_sMin.m_dZ = sOther.sBoundingBox.m_sMin.m_dZ; sBoundingBox.m_sMax.m_dX = sOther.sBoundingBox.m_sMax.m_dX; sBoundingBox.m_sMax.m_dY = sOther.sBoundingBox.m_sMax.m_dY; sBoundingBox.m_sMax.m_dZ = sOther.sBoundingBox.m_sMax.m_dZ; dBoundingBoxRadius = sOther.dBoundingBoxRadius; sBoundingBoxCenter.m_dX = sOther.sBoundingBoxCenter.m_dX; sBoundingBoxCenter.m_dY = sOther.sBoundingBoxCenter.m_dY; sBoundingBoxCenter.m_dZ = sOther.sBoundingBoxCenter.m_dZ; } //################################################################################################################## void Calculate() { A3DVector3dData sMin; A3DVector3dData sMax; sMin.m_dX = sBoundingBox.m_sMin.m_dX; sMin.m_dY = sBoundingBox.m_sMin.m_dY; sMin.m_dZ = sBoundingBox.m_sMin.m_dZ; sMax.m_dX = sBoundingBox.m_sMax.m_dX; sMax.m_dY = sBoundingBox.m_sMax.m_dY; sMax.m_dZ = sBoundingBox.m_sMax.m_dZ; A3DDouble dBX = sMax.m_dX - sMin.m_dX; A3DDouble dBY = sMax.m_dY - sMin.m_dY; A3DDouble dBZ = sMax.m_dZ - sMin.m_dZ; dBoundingBoxRadius = (float) sqrt(dBX*dBX + dBY*dBY + dBZ*dBZ) / 2.0f; sBoundingBoxCenter.m_dX = (sMin.m_dX + sMax.m_dX) / 2.0; sBoundingBoxCenter.m_dY = (sMin.m_dY + sMax.m_dY) / 2.0; sBoundingBoxCenter.m_dZ = (sMin.m_dZ + sMax.m_dZ) / 2.0; } //################################################################################################################## A3DPRCViewerGLInfo operator+(const A3DPRCViewerGLInfo& sOther) { A3DPRCViewerGLInfo sSum; ExtentUnion(&sBoundingBox, &sOther.sBoundingBox, &sSum.sBoundingBox); sSum.Calculate(); return sSum; } private: //################################################################################################################## void ExtentUnion(const A3DBoundingBoxData* e1, const A3DBoundingBoxData* e2, A3DBoundingBoxData* r) { r->m_sMin.m_dX = A3DGL_MIN(e1->m_sMin.m_dX, e2->m_sMin.m_dX); r->m_sMax.m_dX = A3DGL_MAX(e1->m_sMax.m_dX, e2->m_sMax.m_dX); r->m_sMin.m_dY = A3DGL_MIN(e1->m_sMin.m_dY, e2->m_sMin.m_dY); r->m_sMax.m_dY = A3DGL_MAX(e1->m_sMax.m_dY, e2->m_sMax.m_dY); r->m_sMin.m_dZ = A3DGL_MIN(e1->m_sMin.m_dZ, e2->m_sMin.m_dZ); r->m_sMax.m_dZ = A3DGL_MAX(e1->m_sMax.m_dZ, e2->m_sMax.m_dZ); } }; //###################################################################################################################### static A3DSDKHOOPSExchangeLoader* stpHOOPSExchangeLoader = nullptr; static A3DAsmModelFile* pSectionnedModelFile = nullptr; //###################################################################################################################### static A3DPRCViewerGLInfo stsInfo; static A3DPRCViewerGLInfo stsInfo3D; static A3DPRCViewerGLInfo stsInfoMarkups; //###################################################################################################################### #define HEX_TO_RED(hexcolor) ((GLclampf) ((hexcolor & 0xFF0000) >> 16) / 255.0f) #define HEX_TO_GREEN(hexcolor) ((GLclampf) ((hexcolor & 0x00FF00) >> 8) / 255.0f) #define HEX_TO_BLUE(hexcolor) ((GLclampf) (hexcolor & 0x0000FF) / 255.0f) //###################################################################################################################### static enum { KE_NONE = 0, KE_ZOOMING, KE_PANNING } eMotionType; //###################################################################################################################### void Reshape(GLsizei w, GLsizei h) { tbReshape(w, h); glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); // gluPerspective(FOVY, (float)w / (h == 0.0 ? 1.0: (float)h), stsInfo.dBoundingBoxRadius * 0.1, // stsInfo.dBoundingBoxRadius * 100.0); // glOrtho(-w/2., w/2., -h/2., h/2., stsInfo.dBoundingBoxRadius * 0.1,stsInfo.dBoundingBoxRadius * 100.0); glOrtho( -stsInfo.dBoundingBoxRadius * (float)w / (h == 0.0 ? 1.0: (float)h), stsInfo.dBoundingBoxRadius * (float)w / (h == 0.0 ? 1.0: (float)h), -stsInfo.dBoundingBoxRadius, stsInfo.dBoundingBoxRadius, -stsInfo.dBoundingBoxRadius-100,stsInfo.dBoundingBoxRadius * 100.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glGetIntegerv(GL_VIEWPORT, staiViewport); if(!stbFullScreen) { staiWinSize[0] = w; staiWinSize[1] = h; } } //###################################################################################################################### void InitGL(void) { glClearColor(HEX_TO_RED(stuiClearColor), HEX_TO_GREEN(stuiClearColor), HEX_TO_BLUE(stuiClearColor), 1.0f); glPointSize(5.0f); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); glEnable(GL_NORMALIZE); glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); glShadeModel(GL_SMOOTH); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glLightfv(GL_LIGHT0, GL_DIFFUSE, stafLightDiffuse); glLightfv(GL_LIGHT0, GL_AMBIENT, stafLightAmbient); //glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, stafMaterialDiffuse); //glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, stafMaterialSpecular); //glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, stafMaterialShininess); stuiTriedronDisplayList = glGenLists(1); glNewList(stuiTriedronDisplayList, GL_COMPILE); { glPushAttrib(GL_LIGHTING_BIT | GL_LINE_BIT); glDisable(GL_LIGHTING); glLineWidth(2.0); glBegin(GL_LINES); glColor3f(1.0f, 0.0f, 0.0f); glVertex3f(0.0f, 0.0f, 0.0f); glVertex3f(TRIEDRON_SIZE, 0.0f, 0.0f); glColor3f(0.0f, 1.0f, 0.0f); glVertex3f(0.0f, 0.0f, 0.0f); glVertex3f(0.0f, TRIEDRON_SIZE, 0.0f); glColor3f(0.0f, 0.0f, 1.0f); glVertex3f(0.0f, 0.0f, 0.0f); glVertex3f(0.0f, 0.0f, TRIEDRON_SIZE); glEnd(); glPopAttrib(); } glEndList(); stdZoom = 1.0; stdXPan = 0.0; stdYPan = 0.0; #ifdef _DEBUG stiStart = clock(); #endif } //###################################################################################################################### void DrawTriedron(void) { glMatrixMode(GL_PROJECTION); glPushMatrix(); { glLoadIdentity(); glOrtho(0.0, staiViewport[2], 0.0, staiViewport[3], -100.0, 100.0); glMatrixMode(GL_MODELVIEW); glPushMatrix(); { glLoadIdentity(); glTranslated(TRIEDRON_SIZE*1.5, TRIEDRON_SIZE*1.5, 0.0); tbMatrix(); glCallList(stuiTriedronDisplayList); } glPopMatrix(); } glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); } //###################################################################################################################### static float stfX = 1.0f, stfY = 97.0f, stfLineH = 2.0f; //###################################################################################################################### static char stpcMsg[2048]; //###################################################################################################################### void PrintString(const char* format, ...) { va_list args; va_start(args, format); vsprintf(stpcMsg, format, args); va_end(args); glRasterPos2f(stfX, stfY); char* pcPos = &stpcMsg[0]; while(*pcPos) { if(*pcPos == '\n') { stfY -= stfLineH; glRasterPos2f(stfX, stfY); } else glutBitmapCharacter(GLUT_BITMAP_8_BY_13, *pcPos); pcPos++; } } //###################################################################################################################### void DrawError(char const * acMessage, A3DStatus sStatus) { glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); gluOrtho2D(0.0, 100.0, 0.0, 100.0); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glDisable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); glColor3fv(stafErrorTextColor); stfX = 1.0f; stfY = 85.0f; if (acMessage) PrintString("%s %d\n", acMessage, sStatus); else PrintString("ERROR %d\n", sStatus); glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); } //##################################################################################################################### void DrawStrings(void) { glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); gluOrtho2D(0.0, 100.0, 0.0, 100.0); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glDisable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); glColor3fv(stafTextColor); if (stbDrawView) { stfX = 1.0f; stfY = 80.0f; PrintString("VIEWS\n"); PrintString("Total of views: %d \n",mNumberOfViews); PrintString(" View number: %d\n", mCurrentViewIndex); } if(stbDisplayInfos) { stfX = 1.0f; stfY = 97.0f; stiNbFrames++; stiEnd = clock(); stfElapsed = (float)(stiEnd - stiStart) / CLOCKS_PER_SEC; if(stfElapsed >= 1.0) { stfFps = stiNbFrames/stfElapsed; stiStart = stiEnd; stiNbFrames = 0; } PrintString("%.2f fps\n", stfFps); PrintString("Bounding box\n"); A3DVector3dData& sMin = stsInfo.sBoundingBox.m_sMin; A3DVector3dData& sMax = stsInfo.sBoundingBox.m_sMax; PrintString(" Extent: [%.3f, %.3f, %.3f] -> [%.3f, %.3f, %.3f]\n", sMin.m_dX, sMin.m_dY, sMin.m_dZ, sMax.m_dX, sMax.m_dY, sMax.m_dZ); PrintString(" Radius: %.3f\n", stsInfo.dBoundingBoxRadius); } if(stbDisplayHelp) { stfX = 1.0f; stfY = 70.0f; PrintString("HELP\n"); PrintString(" MOUSE:\n"); PrintString(" Left button: rotating\n"); PrintString(" Right button: zooming\n"); PrintString(" Right+Left button: panning\n"); PrintString("\n"); PrintString(" KEYBOARD:\n"); PrintString(" F1: print this help\n"); PrintString(" F2: open a file (in the console)\n"); PrintString(" F3: toggle markup display\n"); PrintString(" F4: toggle full screen\n"); PrintString(" F5: change background color\n"); PrintString(" F6: toggle render mode %s\n", DisplayTriangles() == 1 ? "[SHADING]" : DisplayTriangles() == 2 ? "[WIREFRAME]" : DisplayTriangles() == 3 ? "[SHADING&WIREFRAME]":"NONE"); PrintString(" F7: toggle normals display %s\n", DisplayTriangleNormals() == 0 ? "[NONE]" : DisplayTriangleNormals() == 1 ? "[TRIANGLE PLANE NORMALS (blue)]" : DisplayTriangleNormals() == 2 ? "[NORMALS (green)]" : DisplayTriangleNormals() == 3 ? "[TRIANGLE PLANE NORMALS (blue) & NORMALS (green)]" : "?"); PrintString(" (Up and down keys to change normals display length) %lf\n", DisplayTriangleNormalLength()); PrintString(" F8: toggle rotation animation\n"); PrintString(" F9: toggle double-side rendering %s\n", stbDoubleSideRendering ? "[ON]" : "[OFF]"); PrintString(" F10: compute a planar section. Use the page up and page down keys to change the origin coordinates of the section\n"); PrintString(" F11: toggle information display\n"); PrintString(" h: toggle computed HLR\n"); PrintString(" s: in HLR mode, hide/show section\n"); PrintString(" t: in HLR mode, hide/show tangent edge\n"); PrintString(" v: in HLR mode, hide/show hidden element\n"); PrintString(" Use the RIGHT and LEFT keys to toggle the views\n"); } glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); } //###################################################################################################################### void DrawHLR() { glPushMatrix(); { glLoadIdentity(); glTranslated(-stsInfo.dBoundingBoxRadius*stdXPan, -stsInfo.dBoundingBoxRadius*stdYPan, 0.); glScalef(stdZoom, stdZoom, stdZoom); if (stbDisplayHLRHidden) glCallList(stuiHLRHiddenDisplayList); if (stbDisplayHLRHidden && stbDisplayHLRTanEdge) glCallList(stuiHLRHiddenTanEdgeDisplayList); glCallList(stuiHLRDisplayList); if (stbDisplayHLRTanEdge) glCallList(stuiHLRTanEdgeDisplayList); if (stbDisplayHLRSection) glCallList(stuiHLRSectionDisplayList); } glPopMatrix(); } //###################################################################################################################### void Display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); if (stbDisplayHLR) { DrawHLR(); } else { glPushMatrix(); { glLoadIdentity(); glLightfv(GL_LIGHT0, GL_POSITION, stafLightPosition); glTranslated(0.0f, 0.0f, -3.0*stsInfo.dBoundingBoxRadius); glTranslated(-stsInfo.dBoundingBoxRadius*stdXPan, -stsInfo.dBoundingBoxRadius*stdYPan, 0); tbMatrix(); glTranslated(-stsInfo.sBoundingBoxCenter.m_dX, -stsInfo.sBoundingBoxCenter.m_dY, 0); glScalef(stdZoom, stdZoom, stdZoom); // scale the matrix #ifdef DIRECT_RENDERING Draw(stpHOOPSExchangeLoader->m_psModelFile); if (GetstbDrawMarkups()) { constexpr bool bIncludeMarkups = true; Draw(stpHOOPSExchangeLoader->m_psModelFile, bIncludeMarkups); } #else glCallList(stuiModelFileDisplayList); if(GetstbDrawMarkups()) glCallList(stuiMarkupsDisplayList); #endif } glPopMatrix(); DrawTriedron(); } if(stbDisplayInfos || stbDisplayHelp || stbDrawView) DrawStrings(); glFlush(); glFinish(); glutSwapBuffers(); } void GetOpenGLMatrix(A3DDouble adModelView[16], A3DDouble adProjectMatrix[16]) { glPushMatrix(); { glLoadIdentity(); glLightfv(GL_LIGHT0, GL_POSITION, stafLightPosition); glTranslated(0.0f, 0.0f, -3.0*stsInfo.dBoundingBoxRadius); glTranslated(-stsInfo.dBoundingBoxRadius*stdXPan, -stsInfo.dBoundingBoxRadius*stdYPan, 0.); tbMatrix(); glTranslated(-stsInfo.sBoundingBoxCenter.m_dX, -stsInfo.sBoundingBoxCenter.m_dY, 0.); glScalef(stdZoom, stdZoom, stdZoom); // scale the matrix glGetDoublev(GL_MODELVIEW_MATRIX, adModelView); glGetDoublev(GL_PROJECTION_MATRIX , adProjectMatrix); } glPopMatrix(); } //###################################################################################################################### static bool stbTBRunning = false; //###################################################################################################################### void MouseButton(int button, int state, GLsizei x, GLsizei y) { //GLboolean bActiveShift = glutGetModifiers() & GLUT_ACTIVE_SHIFT; //GLboolean bActiveCtrl = glutGetModifiers() & GLUT_ACTIVE_CTRL; //GLboolean bDownState = (state == GLUT_DOWN); if(button == GLUT_LEFT_BUTTON) { if(state == GLUT_DOWN) stbLButtonDown = true; else if(state == GLUT_UP) stbLButtonDown = false; } else if(button == GLUT_RIGHT_BUTTON) { if(state == GLUT_DOWN) stbRButtonDown = true; else if(state == GLUT_UP) stbRButtonDown = false; } if(!stbLButtonDown && !stbRButtonDown) glutSetCursor(GLUT_CURSOR_LEFT_ARROW); eMotionType = KE_NONE; if(stbLButtonDown) { if(!stbRButtonDown) { tbMouse(button, state, x, y); stbTBRunning = true; } else { if(stbTBRunning) tbMouse(GLUT_LEFT_BUTTON, GLUT_UP, x, y); eMotionType = KE_PANNING; glutSetCursor(GLUT_CURSOR_SPRAY); } } else { if(stbRButtonDown) { eMotionType = KE_ZOOMING; glutSetCursor(GLUT_CURSOR_UP_DOWN); } else { tbMouse(button, state, x, y); stbTBRunning = false; } } stiXScreen = x; stiYScreen = y; glutPostRedisplay(); } //###################################################################################################################### //void MouseWheel(int /* number */, int direction, int /* x */, int /* y */) //{ // // TODO // stdZoom += stsReadModelResult.dBoundingBoxRadius * 0.001 * direction; // glutPostRedisplay(); //} //###################################################################################################################### void Motion(GLsizei x, GLsizei y) { tbMotion(x, y); switch(eMotionType) { case KE_PANNING: { stdXPan -= (GLdouble)(x - stiXScreen)/(GLdouble)staiViewport[2] * 2.0; stdYPan += (GLdouble)(y - stiYScreen)/(GLdouble)staiViewport[3] * 2.0; break; } case KE_ZOOMING: { stdZoom -= (GLdouble)(y - stiYScreen)/(GLdouble)staiViewport[3] * 10.0; if (stdZoom<0) stdZoom = 0; break; } default: break; } stiXScreen = x; stiYScreen = y; glutPostRedisplay(); } //###################################################################################################################### A3DStatus OpenFile(const A3DUTF8Char* pcCADFile); //###################################################################################################################### A3DStatus CloseFile(); //###################################################################################################################### static void stRebuildGenList() { glDeleteLists(stuiModelFileDisplayList, 1); stuiModelFileDisplayList = glGenLists(1); glNewList(stuiModelFileDisplayList, GL_COMPILE); if(!stbDisplaySection) Draw(stpHOOPSExchangeLoader->m_psModelFile); else Draw(pSectionnedModelFile); glEndList(); Reshape(staiWinSize[0], staiWinSize[1]); glutPostRedisplay(); } static void stRebuildGenListHLR() { // Get active View A3DAsmModelFileData sData; A3D_INITIALIZE_DATA(A3DAsmModelFileData, sData); A3DAsmModelFileGet(stpHOOPSExchangeLoader->m_psModelFile, &sData); A3DAsmProductOccurrenceData sPOData; A3D_INITIALIZE_DATA(A3DAsmProductOccurrenceData, sPOData); A3DAsmProductOccurrenceGet(sData.m_ppPOccurrences[0], &sPOData); A3DMkpView const *pActiveView = nullptr; if (sPOData.m_uiViewsSize > 0) { mNumberOfViews = sPOData.m_uiViewsSize; if (mCurrentViewIndex != -1) { pActiveView = sPOData.m_ppViews[mCurrentViewIndex]; } } else if (sPOData.m_pPart != nullptr) { A3DAsmPartDefinitionData sPartData; A3D_INITIALIZE_DATA(A3DAsmPartDefinitionData, sPartData); if (A3DAsmPartDefinitionGet(sPOData.m_pPart, &sPartData) == A3D_SUCCESS) { mNumberOfViews = sPartData.m_uiViewsSize; if (mCurrentViewIndex != -1) { pActiveView = sPartData.m_ppViews[mCurrentViewIndex]; } A3DAsmPartDefinitionGet(nullptr, &sPartData); } } A3DDouble adModelView[16], adProjectMatrix[16]; GetOpenGLMatrix( adModelView, adProjectMatrix); A3DMatrix4x4 sModelViewMat(adModelView), sCameraMat; sModelViewMat.Invert(sCameraMat); A3DHLRViewPlaneData sHLRViewPlaneData; A3D_INITIALIZE_DATA(A3DHLRViewPlaneData,sHLRViewPlaneData); sHLRViewPlaneData.m_adOrigin[0] = stHLROrigin.m_dX = sCameraMat[12]; sHLRViewPlaneData.m_adOrigin[1] = stHLROrigin.m_dY = sCameraMat[13]; sHLRViewPlaneData.m_adOrigin[2] = stHLROrigin.m_dZ = sCameraMat[14]; double dLength = stsInfo.dBoundingBoxRadius / 2.; sHLRViewPlaneData.m_adAxis1[0] = sCameraMat[0] * dLength; sHLRViewPlaneData.m_adAxis1[1] = sCameraMat[1] * dLength; sHLRViewPlaneData.m_adAxis1[2] = sCameraMat[2] * dLength; sHLRViewPlaneData.m_adAxis2[0] = sCameraMat[4] * dLength; sHLRViewPlaneData.m_adAxis2[1] = sCameraMat[5] * dLength; sHLRViewPlaneData.m_adAxis2[2] = sCameraMat[6] * dLength; sHLRViewPlaneData.m_bUseClipBox = false; ComputeHLR(stpHOOPSExchangeLoader->m_psModelFile, pActiveView, sHLRViewPlaneData, stuiHLRDisplayList, stuiHLRTanEdgeDisplayList, stuiHLRHiddenDisplayList, stuiHLRHiddenTanEdgeDisplayList, stuiHLRSectionDisplayList); stbDisplayHLR = true; Reshape(staiWinSize[0], staiWinSize[1]); A3DAsmModelFileGet(nullptr, &sData); A3DAsmProductOccurrenceGet(nullptr, &sPOData); } //###################################################################################################################### void SpecialKey(int key, int /* x */, int /* y */) { switch(key) { case 27: exit(0); case GLUT_KEY_F1: stbDisplayHelp = !stbDisplayHelp; glutPostRedisplay(); break; case GLUT_KEY_F2: { A3DUTF8Char pcFilePath[_MAX_PATH]; fprintf(stdout, "\nFile path: "); scanf("%s", pcFilePath); CloseFile(); if(OpenFile(pcFilePath) == A3D_SUCCESS) { mCurrentViewIndex=~0U; stbDrawView = false; Reshape(staiWinSize[0], staiWinSize[1]); stdZoom = 1.; stdYPan = 0.0; } Display(); } break; case GLUT_KEY_F3: SetstbDrawMarkups(!GetstbDrawMarkups()); if(GetstbDrawMarkups()) stsInfo = stsInfo3D + stsInfoMarkups; else stsInfo = stsInfo3D; Reshape(staiWinSize[0], staiWinSize[1]); glutPostRedisplay(); break; case GLUT_KEY_F4: stbFullScreen = !stbFullScreen; if(stbFullScreen) glutFullScreen(); else { glutPositionWindow(staiWinPosition[0], staiWinPosition[1]); glutReshapeWindow(staiWinSize[0], staiWinSize[1]); } break; case GLUT_KEY_F5: { char pcNewColor[_MAX_PATH]; fprintf(stdout, "\nNew color (0xHHHHHH): "); scanf("%s", pcNewColor); sscanf(pcNewColor, "%x", &stuiClearColor); glClearColor(HEX_TO_RED(stuiClearColor), HEX_TO_GREEN(stuiClearColor), HEX_TO_BLUE(stuiClearColor), 1.0f); glutPostRedisplay(); } break; case GLUT_KEY_F6: DisplayTriangles()++; if(DisplayTriangles() > 3) DisplayTriangles() = 1; stRebuildGenList(); break; case GLUT_KEY_F7: DisplayTriangleNormals()++; if(DisplayTriangleNormals() > 3) DisplayTriangleNormals() = 0; DisplayTriangleNormalLength() = stsInfo3D.dBoundingBoxRadius*2 / 100; stRebuildGenList(); break; case GLUT_KEY_F8: tbMouse(GLUT_LEFT_BUTTON, GLUT_UP, 0, 0); stbTBRunning = false; stbTrackBallAnimate = !stbTrackBallAnimate; tbAnimate(stbTrackBallAnimate); break; case GLUT_KEY_F9: stbDoubleSideRendering = !stbDoubleSideRendering; if(stbDoubleSideRendering) { glDisable(GL_CULL_FACE); glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); } else { glEnable(GL_CULL_FACE); glCullFace(GL_BACK); glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE); } stRebuildGenList(); break; case GLUT_KEY_F10: { stbDisplaySection = !stbDisplaySection; fprintf(stdout, "DisplaySection = %s\n", (stbDisplaySection) ? "true" : "false"); if(stbDisplaySection) { A3D_INITIALIZE_DATA(A3DVector3dData, origin3d); origin3d.m_dX = stsInfo.sBoundingBoxCenter.m_dX; origin3d.m_dY = stsInfo.sBoundingBoxCenter.m_dY; origin3d.m_dZ = stsInfo.sBoundingBoxCenter.m_dZ; A3D_INITIALIZE_DATA(A3DVector3dData, direction3d); char Direction[20] = "Direction"; int nb1 = 0; int nb2 = 0; int nb3 = 0; fprintf(stdout, "\nEnter the x direction of your section: \n"); scanf("%s", Direction); sscanf(Direction, "%d", &nb1); fprintf(stdout, "\nEnter the y direction of your section: \n"); scanf("%s", Direction); sscanf(Direction, "%d", &nb2); fprintf(stdout, "\nEnter the z direction of your section: \n"); scanf("%s", Direction); sscanf(Direction, "%d", &nb3); direction3d.m_dX = (A3DDouble) nb1; direction3d.m_dY = (A3DDouble) nb2; direction3d.m_dZ = (A3DDouble) nb3; A3DPlanarSectionData sSectionParametersData; A3D_INITIALIZE_DATA(A3DPlanarSectionData, sSectionParametersData); sSectionParametersData.m_sOrigin = origin3d; sSectionParametersData.m_sDirection = direction3d; sSectionParametersData.m_bColor = true; sSectionParametersData.m_bCreateFaces = true; pSectionnedModelFile = ComputeSection(stpHOOPSExchangeLoader->m_psModelFile, sSectionParametersData); stRebuildGenList(); } else stRebuildGenList(); } break; case GLUT_KEY_F11: stbDisplayInfos = !stbDisplayInfos; glutPostRedisplay(); break; case GLUT_KEY_UP: DisplayTriangleNormalLength() *= 2; stRebuildGenList(); break; case GLUT_KEY_DOWN: DisplayTriangleNormalLength() /= 2; stRebuildGenList(); break; case GLUT_KEY_RIGHT: { if (mCurrentViewIndex==mNumberOfViews-1) mCurrentViewIndex = ~0U; else mCurrentViewIndex++; stbDrawView = (mCurrentViewIndex != ~0U); stRebuildGenList(); glutPostRedisplay(); } break; case GLUT_KEY_INSERT: { stRebuildGenList(); glutPostRedisplay(); } break; case GLUT_KEY_LEFT: { if (mCurrentViewIndex==~0U) mCurrentViewIndex = mNumberOfViews-1; else mCurrentViewIndex--; stbDrawView = (mCurrentViewIndex != ~0U); stRebuildGenList(); glutPostRedisplay(); } break; case GLUT_KEY_PAGE_UP: { if(stbDisplaySection) { origin3d.m_dX = origin3d.m_dX+direction3d.m_dX*0.1; origin3d.m_dY = origin3d.m_dY+direction3d.m_dY*0.1; origin3d.m_dZ = origin3d.m_dZ+direction3d.m_dZ*0.1; A3DPlanarSectionData sSectionParametersData; A3D_INITIALIZE_DATA(A3DPlanarSectionData, sSectionParametersData); sSectionParametersData.m_sOrigin = origin3d; sSectionParametersData.m_sDirection = direction3d; sSectionParametersData.m_bColor = true; sSectionParametersData.m_bCreateFaces = true; pSectionnedModelFile = ComputeSection(stpHOOPSExchangeLoader->m_psModelFile, sSectionParametersData); stRebuildGenList(); } } break; case GLUT_KEY_PAGE_DOWN: { if(stbDisplaySection) { origin3d.m_dX = origin3d.m_dX-direction3d.m_dX*0.1; origin3d.m_dY = origin3d.m_dY-direction3d.m_dY*0.1; origin3d.m_dZ = origin3d.m_dZ-direction3d.m_dZ*0.1; A3DPlanarSectionData sSectionParametersData; A3D_INITIALIZE_DATA(A3DPlanarSectionData, sSectionParametersData); sSectionParametersData.m_sOrigin = origin3d; sSectionParametersData.m_sDirection = direction3d; sSectionParametersData.m_bColor = true; sSectionParametersData.m_bCreateFaces = true; pSectionnedModelFile = ComputeSection(stpHOOPSExchangeLoader->m_psModelFile, sSectionParametersData); stRebuildGenList(); } } break; } } //###################################################################################################################### A3DStatus DrawGetBoundingBox(const A3DAsmModelFile* pModelFile, A3DBoundingBoxData* psBoundingBox, const A3DBool bIncludeMarkups) { A3DStatus iRet = A3D_SUCCESS; if (pModelFile == nullptr) return A3D_INVALID_ENTITY_NULL; if (psBoundingBox == nullptr) return A3D_INVALID_DATA_STRUCT_NULL; stLoadIdentity(); stExtentInit(psBoundingBox); SetstbDrawMarkups(bIncludeMarkups); SetstpsBoundingBox(psBoundingBox); SetstbUseCallbacks(false); CHECK_RET(DrawModel(pModelFile)); return iRet; } //###################################################################################################################### void Key( unsigned char key, int /*x*/, int /*y*/) { switch (key) { case 's': stbDisplayHLRSection = !stbDisplayHLRSection; glutPostRedisplay(); break; case 't': stbDisplayHLRTanEdge = !stbDisplayHLRTanEdge; glutPostRedisplay(); break; case 'v': stbDisplayHLRHidden = !stbDisplayHLRHidden; glutPostRedisplay(); break; case 'h': { if( !stbDisplayHLR) { stRebuildGenListHLR(); stbDisplayHLR = true; stdXPan_Save = stdXPan; stdXPan = 0.; stdYPan_Save = stdYPan; stdYPan = 0.; stdZoom_Save = stdZoom; } else { stbDisplayHLR = false; stdXPan = stdXPan_Save; stdYPan = stdYPan_Save; stdZoom = stdZoom_Save; } } glutPostRedisplay(); break; case 27: exit(0); break; default: break; } } //###################################################################################################################### static A3DStatus DrawModel(const A3DAsmModelFile* pModelFile) { A3DAsmModelFileData sData; A3D_INITIALIZE_DATA(A3DAsmModelFileData, sData); CHECK_RET(A3DAsmModelFileGet(pModelFile, &sData)); // Creation of the ModelFile Connector A3DModelFileConnector sModelFileConnector(pModelFile); A3DVisitorContainer sCadVisitorContainer(CONNECT_TRANSFO); sCadVisitorContainer.SetTraverseInstance(true); A3DAsmProductOccurrenceData sPOData; A3D_INITIALIZE_DATA(A3DAsmProductOccurrenceData, sPOData); CHECK_RET(A3DAsmProductOccurrenceGet(sData.m_ppPOccurrences[0], &sPOData)); if (sPOData.m_uiViewsSize > 0) { mNumberOfViews = sPOData.m_uiViewsSize; if (mCurrentViewIndex != -1 && mCurrentViewIndexImport(sImport); if(iRet != A3D_SUCCESS && iRet != A3D_LOAD_MULTI_MODELS_CADFILE && iRet != A3D_LOAD_MISSING_COMPONENTS) return iRet; // Traverse the model once to retrieve the bounding box CHECK_RET(DrawGetBoundingBox(stpHOOPSExchangeLoader->m_psModelFile, &stsInfo3D.sBoundingBox)); stsInfo3D.Calculate(); #ifndef DIRECT_RENDERING stuiModelFileDisplayList = glGenLists(1); glNewList(stuiModelFileDisplayList, GL_COMPILE); { if(!stbDisplaySection) { // Traverse the model a second time to draw the items CHECK_RET(Draw(stpHOOPSExchangeLoader->m_psModelFile)); } else { // Draw the section CHECK_RET(Draw(pSectionnedModelFile)); } } glEndList(); #endif Reshape(staiWinSize[0], staiWinSize[1]); // Traverse the model once to retrieve the bounding box with the markups constexpr bool bIncludeMarkups = true; CHECK_RET(DrawGetBoundingBox(stpHOOPSExchangeLoader->m_psModelFile, &stsInfoMarkups.sBoundingBox, bIncludeMarkups)); stsInfoMarkups.Calculate(); #ifndef DIRECT_RENDERING stuiMarkupsDisplayList = glGenLists(1); glNewList(stuiMarkupsDisplayList, GL_COMPILE_AND_EXECUTE); { if(!stbDisplaySection) { // Traverse the model a second time to draw the items (including the markups) CHECK_RET(Draw(stpHOOPSExchangeLoader->m_psModelFile, bIncludeMarkups)); } } glEndList(); #endif Reshape(staiWinSize[0], staiWinSize[1]); fprintf(stdout, "Done.\n"); if(GetstbDrawMarkups()) stsInfo = stsInfo3D + stsInfoMarkups; else stsInfo = stsInfo3D; sprintf(stpcWinTitle, "HOOPS Exchange Viewer - %s", pcCADFileName); glutSetWindowTitle(stpcWinTitle); return A3D_SUCCESS; } //###################################################################################################################### A3DStatus CloseFile() { #ifndef DIRECT_RENDERING glDeleteLists(stuiModelFileDisplayList, 1); glDeleteLists(stuiMarkupsDisplayList, 1); glDeleteLists(stuiHLRDisplayList, 1); glDeleteLists(stuiHLRTanEdgeDisplayList, 1); glDeleteLists(stuiHLRHiddenDisplayList,1); glDeleteLists(stuiHLRHiddenTanEdgeDisplayList,1); glDeleteLists(stuiHLRSectionDisplayList, 1); //glDeleteLists(stuiTriedronDisplayList, 1); stuiModelFileDisplayList = stuiMarkupsDisplayList = stuiHLRDisplayList = stuiHLRTanEdgeDisplayList = stuiHLRHiddenDisplayList = stuiHLRHiddenTanEdgeDisplayList = stuiHLRSectionDisplayList = 0; #endif return A3D_SUCCESS; } //###################################################################################################################### void terminate2() { CloseFile(); delete stpHOOPSExchangeLoader; stpHOOPSExchangeLoader = nullptr; ListLeaks(); } static MY_CHAR acSrcFileName[_MAX_PATH * 2]; static MY_CHAR acLogFileName[_MAX_PATH * 2]; //###################################################################################################################### // Main function #ifdef _MSC_VER int wmain(A3DInt32 iArgc, A3DUniChar** ppcArgv) #else int main(A3DInt32 iArgc, A3DUTF8Char** ppcArgv) #endif { // // ### COMMAND LINE ARGUMENTS // if (iArgc > 4) { MY_PRINTF2("Usage:\n %s [input CAD file] [Clear color value] [output LOG file]\n", ppcArgv[0]); MY_PRINTF(" Default output LOG file is [input CAD file]_Log.txt\n\n"); return A3D_ERROR; } if (iArgc > 1) MY_STRCPY(acSrcFileName, ppcArgv[1]); else MY_STRCPY(acSrcFileName, DEFAULT_INPUT_CAD); if (iArgc > 2) MY_SSCANF(ppcArgv[2], "%x", &stuiClearColor); else stuiClearColor = 0xB2B2B2; if (iArgc > 3) MY_STRCPY(acLogFileName, ppcArgv[3]); else MY_SPRINTF(acLogFileName, "%s_Log.txt", acSrcFileName); GetLogFile(acLogFileName); // Initialize log file // // ### INITIALIZE HOOPS EXCHANGE // stpHOOPSExchangeLoader = new A3DSDKHOOPSExchangeLoader(_T(HOOPS_BINARY_DIRECTORY), HOOPS_LICENSE); if (stpHOOPSExchangeLoader->m_eSDKStatus != A3D_SUCCESS) { A3DStatus eSDKStatus = stpHOOPSExchangeLoader->m_eSDKStatus; delete stpHOOPSExchangeLoader; stpHOOPSExchangeLoader = nullptr; return eSDKStatus; } CHECK_RET(A3DDllSetCallbacksMemory(CheckMalloc, CheckFree)); CHECK_RET(A3DDllSetCallbacksReport(PrintLogMessage, PrintLogWarning, PrintLogError)); // // ### PROCESS SAMPLE CODE // glutInit((int*)(&iArgc), (char**)ppcArgv); GLsizei iScreenW = glutGet(GLUT_SCREEN_WIDTH); GLsizei iScreenH = glutGet(GLUT_SCREEN_HEIGHT); staiWinSize[0] = (GLsizei)((double)iScreenW * 0.7); staiWinSize[1] = (GLsizei)((double)iScreenH * 0.7); staiWinPosition[0] = (iScreenW - staiWinSize[0]) / 2; staiWinPosition[1] = (iScreenH - staiWinSize[1]) / 2; glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); glutInitWindowPosition(staiWinPosition[0], staiWinPosition[1]); glutInitWindowSize(staiWinSize[0], staiWinSize[1]); glutCreateWindow("A3DPRCViewerGL"); glViewport(0, 0, staiWinSize[0], staiWinSize[1]); tbInit(GLUT_LEFT_BUTTON); tbAnimate(stbTrackBallAnimate); stsInfo.Init(); stsInfo3D.Init(); stsInfoMarkups.Init(); A3DUTF8Char sSrcFileNameUTF8[_MAX_PATH]; #ifdef _MSC_VER A3DMiscUTF16ToUTF8(acSrcFileName, sSrcFileNameUTF8); #else MY_STRCPY(sSrcFileNameUTF8, acSrcFileName); #endif CHECK_RET_TERM(OpenFile(sSrcFileNameUTF8)); InitGL(); glutReshapeFunc(Reshape); glutDisplayFunc(Display); glutKeyboardFunc(Key); glutSpecialFunc(SpecialKey); glutMouseFunc(MouseButton); //glutMouseWheelFunc(MouseWheel); glutMotionFunc(Motion); glutIdleFunc(nullptr); fprintf(stdout, "\nF1 for help\n"); // glut call exit(0) when closing windows, so set atexit to properly close the DLL atexit(terminate2); glutMainLoop(); // // ### TERMINATE HOOPS EXCHANGE // return 0; }