/*********************************************************************************************************************** * * 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 callback_opengl.cpp This file demonstrates how to programmatically visualize a PRC file from a basic OpenGL program using HOOPS Exchange. ***********************************************************************************************************************/ #include #include "callback_opengl.h" #include "A3DVector.h" #if !defined _MSC_VER && !defined CALLBACK #define CALLBACK #endif #define _USE_MATH_DEFINES #include #include #include #define IS_EQUAL(A, B) (fabs(A-B) < 1e-12 * (1 + (fabs(A) > fabs(B) ? fabs(A) : fabs(B)))) static bool stbUseCallbacks = true; static bool stbCallbacksInitialized = true; static A3DBoundingBoxData* stpsBoundingBox = nullptr; static bool stbDrawMarkups = false; //###################################################################################################################### bool GetstbUseCallbacks() { return stbUseCallbacks; } void SetstbUseCallbacks(bool UseCallBack) { stbUseCallbacks = UseCallBack; } bool GetstbCallbacksInitialized() { return stbCallbacksInitialized; } // *** Bounding Box A3DBoundingBoxData* GetstpsBoundingBox() { return stpsBoundingBox; } void SetstpsBoundingBox(A3DBoundingBoxData* sBoudingBoxData) { stpsBoundingBox = sBoudingBoxData; } // *** Draw Markups bool GetstbDrawMarkups() { return stbDrawMarkups; } void SetstbDrawMarkups(bool bDrawMarkups) { stbDrawMarkups = bDrawMarkups; } //###################################################################################################################### static double staadStack[32][16]; static unsigned int uiPos = 0; static double stadMatrix[16]; //###################################################################################################################### void stVectoriel(const A3DVector3dData* X, const A3DVector3dData* Y, A3DVector3dData* Z) { Z->m_dX=X->m_dY*Y->m_dZ - X->m_dZ*Y->m_dY; Z->m_dY=X->m_dZ*Y->m_dX - X->m_dX*Y->m_dZ; Z->m_dZ=X->m_dX*Y->m_dY - X->m_dY*Y->m_dX; } //###################################################################################################################### void stMatrixMatrixMult(double m[16], const double o[16]) { memcpy(stadMatrix, m, 16*sizeof(double)); m[0] = stadMatrix[0] * o[0] + stadMatrix[4] * o[1] + stadMatrix[8] * o[2] + stadMatrix[12] * o[3]; m[1] = stadMatrix[1] * o[0] + stadMatrix[5] * o[1] + stadMatrix[9] * o[2] + stadMatrix[13] * o[3]; m[2] = stadMatrix[2] * o[0] + stadMatrix[6] * o[1] + stadMatrix[10] * o[2] + stadMatrix[14] * o[3]; m[3] = stadMatrix[3] * o[0] + stadMatrix[7] * o[1] + stadMatrix[11] * o[2] + stadMatrix[15] * o[3]; m[4] = stadMatrix[0] * o[4] + stadMatrix[4] * o[5] + stadMatrix[8] * o[6] + stadMatrix[12] * o[7]; m[5] = stadMatrix[1] * o[4] + stadMatrix[5] * o[5] + stadMatrix[9] * o[6] + stadMatrix[13] * o[7]; m[6] = stadMatrix[2] * o[4] + stadMatrix[6] * o[5] + stadMatrix[10] * o[6] + stadMatrix[14] * o[7]; m[7] = stadMatrix[3] * o[4] + stadMatrix[7] * o[5] + stadMatrix[11] * o[6] + stadMatrix[15] * o[7]; m[8] = stadMatrix[0] * o[8] + stadMatrix[4] * o[9] + stadMatrix[8] * o[10] + stadMatrix[12] * o[11]; m[9] = stadMatrix[1] * o[8] + stadMatrix[5] * o[9] + stadMatrix[9] * o[10] + stadMatrix[13] * o[11]; m[10]= stadMatrix[2] * o[8] + stadMatrix[6] * o[9] + stadMatrix[10] * o[10] + stadMatrix[14] * o[11]; m[11]= stadMatrix[3] * o[8] + stadMatrix[7] * o[9] + stadMatrix[11] * o[10] + stadMatrix[15] * o[11]; m[12]= stadMatrix[0] * o[12] + stadMatrix[4] * o[13] + stadMatrix[8] * o[14] + stadMatrix[12] * o[15]; m[13]= stadMatrix[1] * o[12] + stadMatrix[5] * o[13] + stadMatrix[9] * o[14] + stadMatrix[13] * o[15]; m[14]= stadMatrix[2] * o[12] + stadMatrix[6] * o[13] + stadMatrix[10] * o[14] + stadMatrix[14] * o[15]; m[15]= stadMatrix[3] * o[12] + stadMatrix[7] * o[13] + stadMatrix[11] * o[14] + stadMatrix[15] * o[15]; } //###################################################################################################################### void stLoadIdentity() { memset(staadStack[uiPos], 0, 16*sizeof(double)); staadStack[uiPos][0] = 1.0; staadStack[uiPos][5] = 1.0; staadStack[uiPos][10] = 1.0; staadStack[uiPos][15] = 1.0; } //###################################################################################################################### void stMultMatrix(const double m[16]) { stMatrixMatrixMult(staadStack[uiPos], m); } //###################################################################################################################### void stPushMatrix() { if(uiPos < 7) { uiPos++; memcpy(staadStack[uiPos], staadStack[uiPos-1], 16*sizeof(double)); } } //###################################################################################################################### void stPopMatrix() { if(uiPos > 0) { uiPos--; } } //###################################################################################################################### void stExtentInit(A3DBoundingBoxData* e) { e->m_sMin.m_dX = 1e10; e->m_sMin.m_dY = 1e10; e->m_sMin.m_dZ = 1e10; e->m_sMax.m_dX = -1e10; e->m_sMax.m_dY = -1e10; e->m_sMax.m_dZ = -1e10; } //###################################################################################################################### void stBoundingBoxAddPoint(A3DBoundingBoxData* e, double x, double y, double z) { if (e == nullptr) return; if(x < e->m_sMin.m_dX) e->m_sMin.m_dX = x; if(y < e->m_sMin.m_dY) e->m_sMin.m_dY = y; if(z < e->m_sMin.m_dZ) e->m_sMin.m_dZ = z; if(x > e->m_sMax.m_dX) e->m_sMax.m_dX = x; if(y > e->m_sMax.m_dY) e->m_sMax.m_dY = y; if(z > e->m_sMax.m_dZ) e->m_sMax.m_dZ = z; } //###################################################################################################################### static int stiDisplayTriangles = 1; static int stiDisplayTriangleNormals = 0; static double stdDisplayTriangleNormalLength = 1; //###################################################################################################################### int& DisplayTriangles() { return stiDisplayTriangles; } //###################################################################################################################### int& DisplayTriangleNormals() { return stiDisplayTriangleNormals; } //###################################################################################################################### double& DisplayTriangleNormalLength() { return stdDisplayTriangleNormalLength; } //###################################################################################################################### void OpenGL_PushMatrix() { glPushMatrix(); } //###################################################################################################################### void OpenGL_PopMatrix() { glPopMatrix(); } //###################################################################################################################### void OpenGL_MultMatrix(const A3DDouble adMatrix[16]) { glMultMatrixd(adMatrix); } //###################################################################################################################### void OpenGL_Begin(A3DEDrawBeginEndType eType, const A3DUTF8Char* /* pcName */, A3DUns32 /* uiTrianglesCount */) { switch(eType) { case kA3DDrawBeginEndMarkup : glPushAttrib(GL_LIGHTING_BIT | GL_COLOR_BUFFER_BIT ); glDisable(GL_LIGHTING); break; case kA3DDrawBeginEndProductOccurrence: case kA3DDrawBeginEndRepresentationItem: break; default: break; } } //###################################################################################################################### void OpenGL_End(A3DEDrawBeginEndType eType) { switch(eType) { case kA3DDrawBeginEndMarkup : glPopAttrib(); break; default: break; } } //###################################################################################################################### inline void glStartLineDrawing() { glPushAttrib(GL_LIGHTING_BIT | GL_LINE_BIT | GL_TEXTURE_BIT); glDisable(GL_TEXTURE); glDisable(GL_LIGHTING); glLineWidth(2); glBegin(GL_LINES); } //###################################################################################################################### inline void glEndLineDrawing() { glEnd(); glPopAttrib(); } //###################################################################################################################### inline void glVertex3d(const A3DVector3dData& aPoint) { glVertex3d(aPoint.m_dX, aPoint.m_dY, aPoint.m_dZ); } //###################################################################################################################### inline void glNormal3d(const A3DVector3dData& aNormal) { glNormal3d(aNormal.m_dX, aNormal.m_dY, aNormal.m_dZ); } //###################################################################################################################### void OpenGL_Triangle(const double* pasNormals, A3DUns32 /*uiNormalSize*/, const double* pasPoints, A3DUns32 /*uiPointSize*/, std::vector auIndiceTrianglePerFace, unsigned uTextureCount) { size_t uIndiceTriangleSize = auIndiceTrianglePerFace.size(); unsigned int uIncr = 2 + uTextureCount; unsigned int uIncrPt = 1 + uTextureCount; unsigned* pCurrentTriangleIndice = &auIndiceTrianglePerFace[0]; unsigned* pCurrentTriangleIndiceTemp; unsigned* pEndTriangleIndice = &auIndiceTrianglePerFace[uIndiceTriangleSize - 1]; A3DVector3d sP1, sP2, sP3, sNormal; unsigned int uPt2Indice = uIncr + uIncrPt; unsigned int uPt3Indice = uIncr*2 + uIncrPt; if(stiDisplayTriangles&1) { glBegin(GL_TRIANGLES); while (pCurrentTriangleIndice <= pEndTriangleIndice) { // Draw triangles pCurrentTriangleIndiceTemp = pCurrentTriangleIndice; for(unsigned uI = 0; uI < 3; uI++) { // In case there is no normal if (pasNormals) { if (pasNormals[*pCurrentTriangleIndice] == 0 && pasNormals[*(pCurrentTriangleIndice)+1] == 0 && pasNormals[*(pCurrentTriangleIndice)+2] == 0) { sP1.set(pasPoints[*(pCurrentTriangleIndiceTemp + uIncrPt)], pasPoints[*(pCurrentTriangleIndiceTemp + uIncrPt) + 1], pasPoints[*(pCurrentTriangleIndiceTemp + uIncrPt) + 2]); sP2.set(pasPoints[*(pCurrentTriangleIndiceTemp + uPt2Indice)], pasPoints[*(pCurrentTriangleIndiceTemp + uPt2Indice) + 1], pasPoints[*(pCurrentTriangleIndiceTemp + uPt2Indice) + 2]); sP3.set(pasPoints[*(pCurrentTriangleIndiceTemp + uPt3Indice)], pasPoints[*(pCurrentTriangleIndiceTemp + uPt3Indice) + 1], pasPoints[*(pCurrentTriangleIndiceTemp + uPt3Indice) + 2]); sNormal = (sP2 - sP1).Cross(sP3 - sP2); sNormal.normalize(); glNormal3d(sNormal.x, sNormal.y, sNormal.z); } // if normals are defined, we draw the normals else glNormal3d(pasNormals[*pCurrentTriangleIndice], pasNormals[*(pCurrentTriangleIndice)+1], pasNormals[*(pCurrentTriangleIndice)+2]); } else { sP1.set(pasPoints[*(pCurrentTriangleIndiceTemp + uIncrPt)], pasPoints[*(pCurrentTriangleIndiceTemp + uIncrPt) + 1], pasPoints[*(pCurrentTriangleIndiceTemp + uIncrPt) + 2]); sP2.set(pasPoints[*(pCurrentTriangleIndiceTemp + uPt2Indice)], pasPoints[*(pCurrentTriangleIndiceTemp + uPt2Indice) + 1], pasPoints[*(pCurrentTriangleIndiceTemp + uPt2Indice) + 2]); sP3.set(pasPoints[*(pCurrentTriangleIndiceTemp + uPt3Indice)], pasPoints[*(pCurrentTriangleIndiceTemp + uPt3Indice) + 1], pasPoints[*(pCurrentTriangleIndiceTemp + uPt3Indice) + 2]); sNormal = (sP2 - sP1).Cross(sP3 - sP2); sNormal.normalize(); glNormal3d(sNormal.x, sNormal.y, sNormal.z); } glVertex3d(pasPoints[*(pCurrentTriangleIndice + uIncrPt)], pasPoints[*(pCurrentTriangleIndice + uIncrPt) + 1], pasPoints[*(pCurrentTriangleIndice + uIncrPt) + 2]); pCurrentTriangleIndice+=uIncr; } } glEnd(); } glStartLineDrawing(); // Draw wireframe if(stiDisplayTriangles&2) { glColor3d(0, 0, 0); pCurrentTriangleIndice = &auIndiceTrianglePerFace[0]; while (pCurrentTriangleIndice <= pEndTriangleIndice) { pCurrentTriangleIndiceTemp = pCurrentTriangleIndice; glVertex3d(pasPoints[*(pCurrentTriangleIndiceTemp + uIncrPt)], pasPoints[*(pCurrentTriangleIndiceTemp + uIncrPt) + 1], pasPoints[*(pCurrentTriangleIndiceTemp + uIncrPt) + 2]); glVertex3d(pasPoints[*(pCurrentTriangleIndiceTemp + uPt2Indice)], pasPoints[*(pCurrentTriangleIndiceTemp + uPt2Indice) + 1], pasPoints[*(pCurrentTriangleIndiceTemp + uPt2Indice) + 2]); glVertex3d(pasPoints[*(pCurrentTriangleIndiceTemp+uPt2Indice)], pasPoints[*(pCurrentTriangleIndiceTemp+uPt2Indice)+1], pasPoints[*(pCurrentTriangleIndiceTemp+uPt2Indice)+2]); glVertex3d(pasPoints[*(pCurrentTriangleIndiceTemp+uPt3Indice)], pasPoints[*(pCurrentTriangleIndiceTemp+uPt3Indice)+1], pasPoints[*(pCurrentTriangleIndiceTemp+uPt3Indice)+2]); glVertex3d(pasPoints[*(pCurrentTriangleIndiceTemp + uPt3Indice)], pasPoints[*(pCurrentTriangleIndiceTemp + uPt3Indice) + 1], pasPoints[*(pCurrentTriangleIndiceTemp + uPt3Indice) + 2]); glVertex3d(pasPoints[*(pCurrentTriangleIndiceTemp + uIncrPt)], pasPoints[*(pCurrentTriangleIndiceTemp + uIncrPt) + 1], pasPoints[*(pCurrentTriangleIndiceTemp + uIncrPt) + 2]); pCurrentTriangleIndice += uIncr * 3; } } //Draw triangle plane normal if(stiDisplayTriangleNormals&1) { glColor3d(0, 0, 1); pCurrentTriangleIndice = &auIndiceTrianglePerFace[0]; while (pCurrentTriangleIndice <= pEndTriangleIndice) { pCurrentTriangleIndiceTemp = pCurrentTriangleIndice; for(unsigned uI = 0; uI < 3; uI++) { sP1.set(pasPoints[*(pCurrentTriangleIndiceTemp + uIncrPt)], pasPoints[*(pCurrentTriangleIndiceTemp + uIncrPt) + 1], pasPoints[*(pCurrentTriangleIndiceTemp + uIncrPt) + 2]); sP2.set(pasPoints[*(pCurrentTriangleIndiceTemp+uPt2Indice)], pasPoints[*(pCurrentTriangleIndiceTemp+uPt2Indice)+1], pasPoints[*(pCurrentTriangleIndiceTemp+uPt2Indice)+2]); sP3.set(pasPoints[*(pCurrentTriangleIndiceTemp+uPt3Indice)], pasPoints[*(pCurrentTriangleIndiceTemp+uPt3Indice)+1], pasPoints[*(pCurrentTriangleIndiceTemp+uPt3Indice)+2]); sNormal = (sP2-sP1).Cross(sP3-sP2); sNormal.normalize(); glVertex3d((pasPoints[*(pCurrentTriangleIndiceTemp + uIncrPt)] + pasPoints[*(pCurrentTriangleIndiceTemp + uPt2Indice)] + pasPoints[*(pCurrentTriangleIndiceTemp + uPt3Indice)]) / 3, (pasPoints[*(pCurrentTriangleIndiceTemp + uIncrPt) + 1] + pasPoints[*(pCurrentTriangleIndiceTemp + uPt2Indice) + 1] + pasPoints[*(pCurrentTriangleIndiceTemp + uPt3Indice) + 1]) / 3, (pasPoints[*(pCurrentTriangleIndiceTemp + uIncrPt) + 2] + pasPoints[*(pCurrentTriangleIndiceTemp + uPt2Indice) + 2] + pasPoints[*(pCurrentTriangleIndiceTemp + uPt3Indice) + 2]) / 3); glVertex3d((pasPoints[*(pCurrentTriangleIndiceTemp + uIncrPt)] + pasPoints[*(pCurrentTriangleIndiceTemp + uPt2Indice)] + pasPoints[*(pCurrentTriangleIndiceTemp + uPt3Indice)]) / 3 + sNormal.x * stdDisplayTriangleNormalLength, (pasPoints[*(pCurrentTriangleIndiceTemp + uIncrPt) + 1] + pasPoints[*(pCurrentTriangleIndiceTemp + uPt2Indice) + 1] + pasPoints[*(pCurrentTriangleIndiceTemp + uPt3Indice) + 1]) / 3 + sNormal.y * stdDisplayTriangleNormalLength, (pasPoints[*(pCurrentTriangleIndiceTemp + uIncrPt) + 2] + pasPoints[*(pCurrentTriangleIndiceTemp + uPt2Indice) + 2] + pasPoints[*(pCurrentTriangleIndiceTemp + uPt3Indice) + 2]) / 3 + sNormal.z * stdDisplayTriangleNormalLength); pCurrentTriangleIndice+=uIncr; } } } //Draw normals if(stiDisplayTriangleNormals&2) { glColor3d(0, 1, 0); pCurrentTriangleIndice = &auIndiceTrianglePerFace[0]; while (pCurrentTriangleIndice < pEndTriangleIndice) { pCurrentTriangleIndiceTemp = pCurrentTriangleIndice; for(unsigned uI = 0; uI < 3; uI++) { glVertex3d(pasPoints[*(pCurrentTriangleIndice+uIncrPt)],pasPoints[*(pCurrentTriangleIndice+uIncrPt)+1],pasPoints[*(pCurrentTriangleIndice+uIncrPt)+2]); glVertex3d(pasPoints[*(pCurrentTriangleIndice+uIncrPt)]+pasNormals[*(pCurrentTriangleIndice)]*stdDisplayTriangleNormalLength, pasPoints[*(pCurrentTriangleIndice+uIncrPt)+1]+pasNormals[*(pCurrentTriangleIndice)+1]*stdDisplayTriangleNormalLength, pasPoints[*(pCurrentTriangleIndice+uIncrPt)+2]+pasNormals[*(pCurrentTriangleIndice)+2]*stdDisplayTriangleNormalLength); pCurrentTriangleIndice+=uIncr; } } } glEndLineDrawing(); } //###################################################################################################################### void OpenGL_Color(const double a_adRGB[3]) { GLfloat afValues[3] = { static_cast(a_adRGB[0]), static_cast(a_adRGB[1]), static_cast(a_adRGB[2]) }; glColor3fv(afValues); } //###################################################################################################################### void OpenGL_Material(A3DEDrawMaterialType eType, const A3DDouble* pdValues, A3DUns32 uiSize) { if(uiSize == 1 && eType == kA3DDrawMaterialShininess) { GLfloat afValues[] = { static_cast(pdValues[0]) }; glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, afValues); } else { GLfloat afValues[4] = { static_cast(pdValues[0]), static_cast(pdValues[1]), static_cast(pdValues[2]), static_cast((uiSize == 4) ? pdValues[3] : 1) }; GLenum glMaterialType = GL_AMBIENT; switch(eType) { case kA3DDrawMaterialDiffuse: glMaterialType = GL_DIFFUSE; break; case kA3DDrawMaterialAmbient: glMaterialType = GL_AMBIENT; break; case kA3DDrawMaterialEmission: glMaterialType = GL_EMISSION; break; case kA3DDrawMaterialShininess: return; default: break; } glMaterialfv(GL_FRONT_AND_BACK, glMaterialType, afValues); } } //###################################################################################################################### void OpenGL_Point(const A3DDouble* pdPoints, A3DUns32 uiPointSize) { const A3DDouble* pdData = &pdPoints[0]; glBegin(GL_POINTS); for(A3DUns32 ui = 0; ui < uiPointSize; ++ui) { glVertex3dv(pdData); pdData += 3; } glEnd(); } //###################################################################################################################### void OpenGL_Font(const A3DFontKeyData* /*psFontKeyData*/) { } //###################################################################################################################### void OpenGL_MarkupTriangle(A3DDouble* pdPoints, A3DUns32 uiPointSize) { const A3DDouble* pdData = &pdPoints[0]; glBegin(GL_TRIANGLES); for(A3DUns32 ui = 0; ui < uiPointSize/3; ++ui) { glVertex3dv(pdData); pdData += 3; glVertex3dv(pdData); pdData += 3; glVertex3dv(pdData); pdData += 3; } glEnd(); } //###################################################################################################################### void OpenGL_PolyLine(A3DDouble* pdPoints, A3DUns32 uiPointSize) { const A3DDouble* pdData = &pdPoints[0]; glBegin(GL_LINE_STRIP); for(A3DUns32 ui = 0; ui < uiPointSize; ++ui) { glVertex3dv(pdData); pdData += 3; } glEnd(); }