/*********************************************************************************************************************** * * 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. ***********************************************************************************************************************/ #define A3DAPI_DEPRECATED #include #include "callback_opengl.h" #if !defined _MSC_VER && !defined CALLBACK #define CALLBACK #endif #define _USE_MATH_DEFINES #include #include #define IS_EQUAL(A, B) (fabs(A-B) < 1e-12 * (1 + (fabs(A) > fabs(B) ? fabs(A) : fabs(B)))) //###################################################################################################################### static int stiDisplayTriangles = 1; static int stiDisplayTriangleNormals = 0; static double stdDisplayTriangleNormalLength = 1; //###################################################################################################################### int& DisplayTriangles() { return stiDisplayTriangles; } //###################################################################################################################### int& DisplayTriangleNormals() { return stiDisplayTriangleNormals; } //###################################################################################################################### double& DisplayTriangleNormalLength() { return stdDisplayTriangleNormalLength; } //###################################################################################################################### A3DStatus DrawInitCallbacks(deprecated_A3DDrawCallbacksData* psCallbacks); //###################################################################################################################### static double stDeterminant4x4(double const m[16]) { return m[12]*m[9]*m[6]*m[3] - m[8]*m[13]*m[6]*m[3] - m[12]*m[5]*m[10]*m[3] + m[4]*m[13]*m[10]*m[3] + m[8]*m[5]*m[14]*m[3] - m[4]*m[9]*m[14]*m[3] - m[12]*m[9]*m[2]*m[7] + m[8]*m[13]*m[2]*m[7] + m[12]*m[1]*m[10]*m[7] - m[0]*m[13]*m[10]*m[7] - m[8]*m[1]*m[14]*m[7] + m[0]*m[9]*m[14]*m[7] + m[12]*m[5]*m[2]*m[11] - m[4]*m[13]*m[2]*m[11] - m[12]*m[1]*m[6]*m[11] + m[0]*m[13]*m[6]*m[11] + m[4]*m[1]*m[14]*m[11] - m[0]*m[5]*m[14]*m[11] - m[8]*m[5]*m[2]*m[15] + m[4]*m[9]*m[2]*m[15] + m[8]*m[1]*m[6]*m[15] - m[0]*m[9]*m[6]*m[15] - m[4]*m[1]*m[10]*m[15] + m[0]*m[5]*m[10]*m[15]; } //###################################################################################################################### static bool stGenerateInverseMatrix4x4(const double m[16], double r[16]) { double d = stDeterminant4x4(m); if(d == 0.) return false; r[0] = (-m[13]*m[10]*m[7] +m[9]*m[14]*m[7] +m[13]*m[6]*m[11]-m[5]*m[14]*m[11] -m[9]*m[6]*m[15] +m[5]*m[10]*m[15])/d; r[4] = (m[12]*m[10]*m[7] -m[8]*m[14]*m[7] -m[12]*m[6]*m[11]+m[4]*m[14]*m[11] +m[8]*m[6]*m[15] -m[4]*m[10]*m[15])/d; r[8] = (-m[12]*m[9]*m[7] +m[8]*m[13]*m[7] +m[12]*m[5]*m[11]-m[4]*m[13]*m[11] -m[8]*m[5]*m[15] +m[4]*m[9]* m[15])/d; r[12] = (m[12]*m[9]*m[6] -m[8]*m[13]*m[6] -m[12]*m[5]*m[10]+m[4]*m[13]*m[10] +m[8]*m[5]*m[14] -m[4]*m[9]* m[14])/d; r[1] = (m[13]*m[10]*m[3] -m[9]*m[14]*m[3] -m[13]*m[2]*m[11]+m[1]*m[14]*m[11] +m[9]*m[2]*m[15] -m[1]*m[10]*m[15])/d; r[5] = (-m[12]*m[10]*m[3] +m[8]*m[14]*m[3] +m[12]*m[2]*m[11]-m[0]*m[14]*m[11] -m[8]*m[2]*m[15] +m[0]*m[10]*m[15])/d; r[9] = (m[12]*m[9]*m[3] -m[8]*m[13]*m[3] -m[12]*m[1]*m[11]+m[0]*m[13]*m[11] +m[8]*m[1]*m[15] -m[0]*m[9]* m[15])/d; r[13] = (-m[12]*m[9]*m[2] +m[8]*m[13]*m[2] +m[12]*m[1]*m[10]-m[0]*m[13]*m[10] -m[8]*m[1]*m[14] +m[0]*m[9]*m[14])/d; r[2] = (-m[13]*m[6]*m[3] +m[5]*m[14]*m[3] +m[13]*m[2]*m[7]-m[1]*m[14]*m[7] -m[5]*m[2]*m[15] +m[1]*m[6]*m[15])/d; r[6] = (m[12]*m[6]*m[3] -m[4]*m[14]*m[3] -m[12]*m[2]*m[7]+m[0]*m[14]*m[7] +m[4]*m[2]*m[15] -m[0]*m[6]*m[15])/d; r[10] = (-m[12]*m[5]*m[3] +m[4]*m[13]*m[3] +m[12]*m[1]*m[7]-m[0]*m[13]*m[7] -m[4]*m[1]*m[15] +m[0]*m[5]*m[15])/d; r[14] = (m[12]*m[5]*m[2] -m[4]*m[13]*m[2] -m[12]*m[1]*m[6]+m[0]*m[13]*m[6] +m[4]*m[1]*m[14] -m[0]*m[5]*m[14])/d; r[3] = (m[9]*m[6]*m[3] -m[5]*m[10]*m[3] -m[9]*m[2]*m[7]+m[1]*m[10]*m[7] +m[5]*m[2]*m[11] -m[1]*m[6]*m[11])/d; r[7] = (-m[8]*m[6]*m[3] +m[4]*m[10]*m[3] +m[8]*m[2]*m[7]-m[0]*m[10]*m[7] -m[4]*m[2]*m[11] +m[0]*m[6]*m[11])/d; r[11] = (m[8]*m[5]*m[3] -m[4]*m[9]*m[3] -m[8]*m[1]*m[7]+m[0]*m[9]*m[7] +m[4]*m[1]*m[11] -m[0]*m[5]*m[11])/d; r[15] = (-m[8]*m[5]*m[2] +m[4]*m[9]*m[2] +m[8]*m[1]*m[6]-m[0]*m[9]*m[6] -m[4]*m[1]*m[10] +m[0]*m[5]*m[10])/d; return true; } //###################################################################################################################### static void stTranfoPt(A3DDouble adMatrix[16], A3DDouble* adPt) { A3DDouble adTmp[4]; adTmp[0] = adPt[0] * adMatrix[0] + adPt[1] * adMatrix[4] + adPt[2] * adMatrix[8] + adMatrix[12]; adTmp[1] = adPt[0] * adMatrix[1] + adPt[1] * adMatrix[5] + adPt[2] * adMatrix[9] + adMatrix[13]; adTmp[2] = adPt[0] * adMatrix[2] + adPt[1] * adMatrix[6] + adPt[2] * adMatrix[10] + adMatrix[14]; adTmp[3] = 1. * adMatrix[3] + 1. * adMatrix[7] + 1. * adMatrix[11] + adMatrix[15]; adTmp[0] /= adTmp[3]; adTmp[1] /= adTmp[3]; adTmp[2] /= adTmp[3]; memcpy(adPt, adTmp, 3*sizeof(A3DDouble)); } //###################################################################################################################### void OpenGL_PushMatrix() { glPushMatrix(); } //###################################################################################################################### void OpenGL_PopMatrix() { glPopMatrix(); } //###################################################################################################################### void OpenGL_MultMatrix(const A3DDouble adMatrix[16]) { glMultMatrixd(adMatrix); } //###################################################################################################################### void OpenGL_GetMatrix(A3DDouble adMatrix[16]) { glGetDoublev(GL_MODELVIEW_MATRIX, adMatrix); } //###################################################################################################################### static void stOpenGL_TreatColorIndex(A3DUns32 uiRgbColorIndex, A3DBool* pbPush) { if(uiRgbColorIndex != A3D_DEFAULT_COLOR_INDEX) { if(pbPush != NULL) { OpenGL_BeginMaterial(); *pbPush = TRUE; } A3DGraphRgbColorData sRgbColorData; A3D_INITIALIZE_DATA(A3DGraphRgbColorData, sRgbColorData); if(A3DGlobalGetGraphRgbColorData(uiRgbColorIndex,&sRgbColorData) == A3D_SUCCESS) { A3DDouble adColor[3] = { sRgbColorData.m_dRed, sRgbColorData.m_dGreen, sRgbColorData.m_dBlue }; OpenGL_Material(kA3DDrawMaterialDiffuse, adColor, 3); } A3DGlobalGetGraphRgbColorData(A3D_DEFAULT_COLOR_INDEX, &sRgbColorData); } else if(pbPush != NULL) *pbPush = FALSE; } //###################################################################################################################### static void stOpenGL_TreatLinePattern(A3DUns32 uiLinePatternIndex) { if(uiLinePatternIndex != A3D_DEFAULT_LINEPATTERN_INDEX) { A3DGraphLinePatternData sPatternData; A3D_INITIALIZE_DATA(A3DGraphLinePatternData, sPatternData); if(A3DGlobalGetGraphLinePatternData(uiLinePatternIndex,&sPatternData) == A3D_SUCCESS) { glEnable(GL_LINE_STIPPLE); A3DDouble dLength = 0.; A3DUns32 i, j, p = 0; for(i=0; i < sPatternData.m_uiNumberOfLengths; ++i) { dLength += sPatternData.m_pdLengths[i]; } //std::vector asByte; unsigned short usLineStipple = 0; for(i=0; i < sPatternData.m_uiNumberOfLengths; ++i) { A3DUns8 ucValue = (A3DUns8) floor(sPatternData.m_pdLengths[i]*16/dLength + 0.5); if(!(i%2)) { for(j=0;jm_dX, pasNormals->m_dY, pasNormals->m_dZ); for(A3DUns32 ui = 0; ui < uiPointSize; ++ui) glVertex3d(pasPoints[ui].m_dX, pasPoints[ui].m_dY, pasPoints[ui].m_dZ); glEnd(); } glStartLineDrawing(); for(A3DUns32 ui = 0; ui < uiPointSize/3; ++ui) { glTriangleAndNormalDisplay(pasPoints [ui*3 ],pasPoints [ui*3+1],pasPoints [ui*3+2], pasNormals[0], pasNormals[0], pasNormals[0], true); } glEndLineDrawing(); } //###################################################################################################################### void OpenGL_TriangleFanOneNormal(const A3DVector3dData* psNormal, const A3DVector3dData* pasPoints, A3DUns32 uiPointSize) { if(stiDisplayTriangles&1) { glBegin(GL_TRIANGLE_FAN); glNormal3d(psNormal->m_dX, psNormal->m_dY, psNormal->m_dZ); for(A3DUns32 ui = 0; ui < uiPointSize; ++ui) { glVertex3d(pasPoints[ui].m_dX, pasPoints[ui].m_dY, pasPoints[ui].m_dZ); } glEnd(); } glStartLineDrawing(); for(A3DUns32 ui = 2; ui < uiPointSize; ++ui) { glTriangleAndNormalDisplay(pasPoints[ui-1], pasPoints[ui], pasPoints[0], psNormal[0], psNormal[0], psNormal[0], true); } glEndLineDrawing(); } //###################################################################################################################### void OpenGL_TriangleStripeOneNormal(const A3DVector3dData* psNormal, const A3DVector3dData* pasPoints, A3DUns32 uiPointSize) { if(stiDisplayTriangles&1) { glBegin(GL_TRIANGLE_STRIP); glNormal3d(psNormal->m_dX, psNormal->m_dY, psNormal->m_dZ); for(A3DUns32 ui = 0; ui < uiPointSize; ++ui) { glVertex3d(pasPoints[ui].m_dX, pasPoints[ui].m_dY, pasPoints[ui].m_dZ); } glEnd(); } glStartLineDrawing(); for(A3DUns32 ui = 2; ui < uiPointSize; ++ui) { if(ui%2 == 0) { glTriangleAndNormalDisplay(pasPoints[ui-2], pasPoints[ui-1], pasPoints[ui], psNormal[0], psNormal[0], psNormal[0]); } else { glTriangleAndNormalDisplay(pasPoints[ui-1], pasPoints[ui-2], pasPoints[ui], psNormal[0], psNormal[0], psNormal[0]); } } glEndLineDrawing(); } //###################################################################################################################### void OpenGL_TriangleTextured(const A3DVector3dData* pasNormals, const A3DVector3dData* pasPoints, A3DUns32 uiPointSize) { OpenGL_Triangle(pasNormals, pasPoints, uiPointSize); } //###################################################################################################################### void OpenGL_TriangleFanTextured(const A3DVector3dData* pasNormals, const A3DVector3dData* pasPoints, A3DUns32 uiPointSize) { OpenGL_TriangleFan(pasNormals, pasPoints, uiPointSize); } //###################################################################################################################### void OpenGL_TriangleStripeTextured(const A3DVector3dData* pasNormals, const A3DVector3dData* pasPoints, A3DUns32 uiPointSize) { OpenGL_TriangleStripe(pasNormals, pasPoints, uiPointSize); } //###################################################################################################################### void OpenGL_TriangleOneNormalTextured(const A3DVector3dData* pasNormals, const A3DVector3dData* pasPoints, A3DUns32 uiPointSize) { OpenGL_TriangleOneNormal(pasNormals, pasPoints, uiPointSize); } //###################################################################################################################### void OpenGL_TriangleFanOneNormalTextured(const A3DVector3dData* psNormal, const A3DVector3dData* pasPoints, A3DUns32 uiPointSize) { OpenGL_TriangleFanOneNormal(psNormal, pasPoints, uiPointSize); } //###################################################################################################################### void OpenGL_TriangleStripeOneNormalTextured(const A3DVector3dData* psNormal, const A3DVector3dData* pasPoints, A3DUns32 uiPointSize) { OpenGL_TriangleStripeOneNormal(psNormal, pasPoints, uiPointSize); } //###################################################################################################################### void OpenGL_Color(const A3DDouble adValues[3]) { GLfloat afValues[3] = { static_cast(adValues[0]), static_cast(adValues[1]), static_cast(adValues[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_BeginMaterial(void) { glPushAttrib(GL_LIGHTING_BIT | GL_CURRENT_BIT); } //###################################################################################################################### void OpenGL_EndMaterial(void) { glPopAttrib(); } //###################################################################################################################### void OpenGL_GetDrawContext(A3DDouble /*adProjection*/[16], A3DDouble /*adModelView*/[16], A3DInt32 /*aiViewport*/[4]) { } //###################################################################################################################### void OpenGL_MarkupTriangle(const 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_UnProject(const A3DVector3dData* psPoint, A3DVector3dData* psResult) { double adProjection[16], adModelView[16]; int aiViewport[4]; glGetDoublev(GL_MODELVIEW_MATRIX, adModelView); glGetDoublev(GL_PROJECTION_MATRIX, adProjection); glGetIntegerv(GL_VIEWPORT, aiViewport); gluUnProject(psPoint->m_dX, psPoint->m_dY, psPoint->m_dZ, adModelView, adProjection, aiViewport, &psResult->m_dX, &psResult->m_dY, &psResult->m_dZ); } //###################################################################################################################### void OpenGL_BeginFrameDraw(const A3DVector3dData* psPoint3d, A3DBool bIsZoomable, A3DDouble dFixedSize) { double adProjection[16], adModelView[16]; int aiViewport[4]; glGetDoublev(GL_MODELVIEW_MATRIX, adModelView); glGetDoublev(GL_PROJECTION_MATRIX, adProjection); glGetIntegerv(GL_VIEWPORT, aiViewport); double dXProj, dYProj, dZProj; gluProject(psPoint3d->m_dX, psPoint3d->m_dY, psPoint3d->m_dZ, adModelView, adProjection, aiViewport, &dXProj, &dYProj, &dZProj); glPushAttrib(GL_TRANSFORM_BIT | GL_VIEWPORT_BIT); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); gluOrtho2D(0.0, aiViewport[2], 0.0, aiViewport[3]); glTranslated(dXProj, dYProj, 0.0); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); if(bIsZoomable) glScaled(1.0/dFixedSize, 1.0/dFixedSize, 1.0/dFixedSize); } //###################################################################################################################### void OpenGL_EndFrameDraw(void) { glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); glPopAttrib(); } //###################################################################################################################### static double stGetFixedSize(double dPX, double dPY, double dPZ) { double adMv[16], adPj[16]; int aiVp[4]; glGetDoublev(GL_MODELVIEW_MATRIX, adMv); glGetDoublev(GL_PROJECTION_MATRIX, adPj); glGetIntegerv(GL_VIEWPORT, aiVp); double xProj, yProj, zProj; gluProject(dPX, dPY, dPZ, adMv, adPj, aiVp, &xProj, &yProj, &zProj); double x0, y0, z0; double x1, y1, z1; gluUnProject(aiVp[0], aiVp[2], zProj, adMv, adPj, aiVp, &x0, &y0, &z0); gluUnProject(aiVp[1], aiVp[3], zProj, adMv, adPj, aiVp, &x1, &y1, &z1); double dL = sqrt((x1-x0) * (x1-x0) + (y1-y0) * (y1-y0) + (z1-z0) * (z1-z0)); double dD = dL/500.0; return dD; } //###################################################################################################################### void OpenGL_BeginFixedSize(const A3DVector3dData* psPoint3d) { #define SIZE_ARROW 15.0 double dFixedSize = stGetFixedSize(psPoint3d->m_dX, psPoint3d->m_dY, psPoint3d->m_dZ); double dFixedSizeArrow = dFixedSize * SIZE_ARROW; glPushMatrix(); glTranslated(psPoint3d->m_dX, psPoint3d->m_dY, psPoint3d->m_dZ); glScaled(dFixedSizeArrow, dFixedSizeArrow, dFixedSizeArrow); } //###################################################################################################################### void OpenGL_EndFixedSize(void) { glPopMatrix(); } //###################################################################################################################### void OpenGL_Cylinder(A3DDouble dBaseRadius, A3DDouble dTopRadius, A3DDouble dHeight) { GLUquadricObj* qCylinder = gluNewQuadric(); gluQuadricDrawStyle(qCylinder, GLU_FILL); gluCylinder(qCylinder, dBaseRadius, dTopRadius, dHeight, 8, 8); gluDeleteQuadric(qCylinder); } //###################################################################################################################### void OpenGL_Polygon(const A3DDouble* pdPoints, A3DUns32 uiPointSize) { const A3DDouble* pdData = &pdPoints[0]; glBegin(GL_POLYGON); for(A3DUns32 ui = 0; ui < uiPointSize; ++ui) { glVertex3dv(pdData); pdData += 3; } glEnd(); } //###################################################################################################################### void OpenGL_BeginLineWidth(A3DDouble dWidth) { glPushAttrib(GL_LINE_BIT); glLineWidth((GLfloat)dWidth); } //###################################################################################################################### void OpenGL_EndLineWidth(void) { glPopAttrib(); } //###################################################################################################################### 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_BeginLineStipple(const A3DGraphStyleData* psGraphStyleData ) { glPushAttrib(GL_ENABLE_BIT | GL_LIGHTING_BIT | GL_CURRENT_BIT); glEnable(GL_LINE_STIPPLE); if(!psGraphStyleData->m_bVPicture) { stOpenGL_TreatLinePattern(psGraphStyleData->m_uiLinePatternIndex); } } //###################################################################################################################### void OpenGL_EndLineStipple(void) { glDisable(GL_LINE_STIPPLE); glPopAttrib(); } //###################################################################################################################### void OpenGL_Symbol(const A3DGraphVPicturePatternData* /* psPatternData */, const A3DVector3dData* /* psPosition */) { } //###################################################################################################################### void OpenGL_PolyLine(const 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(); } //###################################################################################################################### void OpenGL_Text(const A3DUTF8Char* /* pcBuffer */, A3DDouble dWidth, A3DDouble dHeight) { // Draw only frame text if(dWidth > 0.0) { glBegin(GL_LINE_STRIP); glVertex2f(0.0f, 0.0f); glVertex2f((GLfloat) dWidth, 0.0f); glVertex2f((GLfloat) dWidth, (GLfloat) dHeight); glVertex2f(0.0f, (GLfloat) dHeight); glVertex2f(0.0f, 0.0f); glEnd(); } } //###################################################################################################################### static void stOpenGL_Pattern_Start(A3DUns32 uiLoopsSize, const A3DDouble* pdPoints, const A3DUns32* puiLoopsPointSize, A3DDouble* adMin, A3DDouble* adMax) { adMin[0] = adMin[1] = adMin[2] = DBL_MAX; adMax[0] = adMax[1] = adMax[2] = -DBL_MAX; glPushAttrib(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_ENABLE_BIT | GL_CURRENT_BIT); glEnable(GL_STENCIL_TEST); glClearStencil(~2); glClear(GL_STENCIL_BUFFER_BIT); glStencilMask(2); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); glDisable(GL_DEPTH_TEST); glStencilFunc(GL_NOTEQUAL, 0x2, 0x2); glStencilOp(GL_ZERO, GL_REPLACE, GL_REPLACE); // Clipping glDisable(GL_CULL_FACE); A3DDouble const* psCurPt = pdPoints; A3DUns32 uiLoop; for(uiLoop = 0; uiLoop < uiLoopsSize; ++uiLoop) { A3DUns32 uiPt, uiNbPt = puiLoopsPointSize[uiLoop]; if(uiNbPt > 0) { GLUtesselator* tobj = gluNewTess(); gluTessCallback(tobj, GLU_TESS_BEGIN, (void (CALLBACK*) ()) glBegin); gluTessCallback(tobj, GLU_TESS_VERTEX, (void (CALLBACK*) ()) glVertex3dv); gluTessCallback(tobj, GLU_TESS_END, (void (CALLBACK*) ()) glEnd); gluTessEndPolygon(tobj); gluTessBeginContour(tobj); for(uiPt = 0; uiPt < uiNbPt; uiPt++, psCurPt += 3) { gluTessVertex(tobj, (GLdouble*) psCurPt, (void*) psCurPt); if(*psCurPt < adMin[0]) adMin[0] = *psCurPt; else if(*psCurPt > adMax[0]) adMax[0] = *psCurPt; if(*(psCurPt+1) < adMin[1]) adMin[1] = *(psCurPt+1); else if(*(psCurPt+1) > adMax[1]) adMax[1] = *(psCurPt+1); if(*(psCurPt+2) < adMin[2]) adMin[2] = *(psCurPt+2); else if(*(psCurPt+2) > adMax[2]) adMax[2] = *(psCurPt+2); } gluTessEndContour(tobj); gluTessEndPolygon(tobj); gluDeleteTess(tobj); } } glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glStencilFunc(GL_EQUAL, 0x3, 0x3); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); } //###################################################################################################################### static void stOpenGL_Pattern_End() { glPopAttrib(); } //###################################################################################################################### static void stOpenGL_Pattern_HatchingLine_ComputeStep(A3DGraphHatchingPatternLineData const* psData, A3DDouble& dStepX, A3DDouble& dStepY) { double dTan = tan(psData->m_dAngle); if(!IS_EQUAL(psData->m_dAngle, 0.) && !IS_EQUAL(psData->m_dAngle, M_PI)) { dStepX = psData->m_sOffset.m_dX; if(!IS_EQUAL(fabs(psData->m_dAngle), M_PI/2)) dStepX -= psData->m_sOffset.m_dY / dTan; } else { dStepX = 0.f; } if(!IS_EQUAL(fabs(psData->m_dAngle), M_PI/2.)) { dStepY = psData->m_sOffset.m_dY - psData->m_sOffset.m_dX * dTan; } else { dStepY = 0.f; } } //###################################################################################################################### static void stOpenGL_Pattern_HatchingLine_ComputeOccurrence(A3DGraphHatchingPatternLineData const* psData, A3DDouble const* adMin, A3DDouble const* adMax, A3DInt32& iOcLgMin, A3DInt32& iOcLgMax) { A3DDouble dStepX, dStepY; stOpenGL_Pattern_HatchingLine_ComputeStep(psData, dStepX, dStepY); A3DInt32 iXMin = 0, iXMax = 0; if(fabs(dStepX) > 1e-12) { iXMax = -(int) ((psData->m_sStart.m_dX - adMin[0]) / dStepX); iXMin = -(int) ((psData->m_sStart.m_dX - adMax[0]) / dStepX); if(iXMin > iXMax) { int iTmp = iXMin; iXMin = iXMax; iXMax = iTmp; } } A3DInt32 iYMin = 0, iYMax = 0; if(fabs(dStepY) > 1e-12) { iYMax = -(int) ((psData->m_sStart.m_dY - adMin[1]) / dStepY); iYMin = -(int) ((psData->m_sStart.m_dY - adMax[1]) / dStepY); if(iYMin > iYMax) { int iTmp = iYMin; iYMin = iYMax; iYMax = iTmp; } } iOcLgMin = iXMin + iYMin - 1; iOcLgMax = iXMax + iYMax + 1; } //###################################################################################################################### static void stOpenGL_Pattern_HatchingLine(A3DGraphHatchingPatternLineData* psData, A3DUns32 /*uiBehavior*/, A3DDouble const* adMin, A3DDouble const* adMax) { bool bWithStipple = false; if(psData->m_uiStyleIndex != A3D_DEFAULT_STYLE_INDEX) { A3DGraphStyleData sStyleData; A3D_INITIALIZE_DATA(A3DGraphStyleData, sStyleData); if(A3DGlobalGetGraphStyleData(psData->m_uiStyleIndex, &sStyleData) == A3D_SUCCESS) { OpenGL_BeginLineStipple(&sStyleData); bWithStipple = true; } } A3DInt32 iOcLgMin, iOcLgMax, iOcLg; stOpenGL_Pattern_HatchingLine_ComputeOccurrence(psData, adMin, adMax, iOcLgMin, iOcLgMax); double dStartX = (psData->m_sStart.m_dX + iOcLgMin * psData->m_sOffset.m_dX); double dStartY = (psData->m_sStart.m_dY + iOcLgMin * psData->m_sOffset.m_dY); double dCos = cos(psData->m_dAngle); double dSin = sin(psData->m_dAngle); double dPatMin, dPatMax; bool bCosSupSin = fabs(dCos) > fabs(dSin); glBegin(GL_LINES); for(iOcLg = iOcLgMin; iOcLg < iOcLgMax; ++iOcLg) { if(bCosSupSin) { dPatMax = (adMin[0] - dStartX) / dCos; dPatMin = (adMax[0] - dStartX) / dCos; } else { dPatMax = (adMin[1] - dStartY) / dSin; dPatMin = (adMax[1] - dStartY) / dSin; } if(dPatMin>dPatMax) { double dTmp = dPatMin; dPatMin = dPatMax; dPatMax = dTmp; } glVertex2f(dStartX + dPatMin * dCos, dStartY + dPatMin * dSin); glVertex2f(dStartX + dPatMax * dCos, dStartY + dPatMax * dSin); dStartX += psData->m_sOffset.m_dX; dStartY += psData->m_sOffset.m_dY; } glEnd(); if(bWithStipple) { OpenGL_EndLineStipple(); } } //###################################################################################################################### static void stOpenGL_Pattern_Hatching(A3DUns32 uiPatternId, A3DUns32 uiBehavior, A3DDouble* adMin, A3DDouble* adMax) { A3DGraphHatchingPatternData sData; A3D_INITIALIZE_DATA(A3DGraphHatchingPatternData, sData); if(A3DGlobalGetGraphHatchingPatternData(uiPatternId, &sData) != A3D_SUCCESS) { A3DGlobalGetGraphHatchingPatternData(A3D_DEFAULT_PATTERN_INDEX, &sData); return; } A3DUns32 uiLine; for(uiLine = 0; uiLine < sData.m_uiSize; ++uiLine) { stOpenGL_Pattern_HatchingLine(&sData.m_psHatchLines[uiLine], uiBehavior, adMin, adMax); } A3DGlobalGetGraphHatchingPatternData(A3D_DEFAULT_PATTERN_INDEX, &sData); } //###################################################################################################################### static void stOpenGL_Pattern_Solid(A3DUns32 uiPatternId, A3DUns32 /*uiBehavior*/, A3DDouble* adMin, A3DDouble* adMax) { A3DGraphSolidPatternData sData; A3D_INITIALIZE_DATA(A3DGraphSolidPatternData, sData); if(A3DGlobalGetGraphSolidPatternData(uiPatternId, &sData) != A3D_SUCCESS) return; A3DBool bPush = FALSE; if(!sData.m_bMaterial) { stOpenGL_TreatColorIndex(sData.m_uiRgbColorIndex, &bPush); } else { // TODO ... } glBegin(GL_QUADS); glVertex3d(adMin[0], adMin[1], adMin[2]); glVertex3d(adMin[0], adMax[1], adMin[2]); glVertex3d(adMax[0], adMax[1], adMin[2]); glVertex3d(adMax[0], adMin[1], adMin[2]); glEnd(); if(bPush) OpenGL_EndMaterial(); } //###################################################################################################################### static void stOpenGL_Pattern_Dotting(A3DUns32 uiPatternId, A3DUns32 /*uiBehavior*/, A3DDouble* adMin, A3DDouble* adMax) { A3DGraphDottingPatternData sData; A3D_INITIALIZE_DATA(A3DGraphDottingPatternData, sData); if(A3DGlobalGetGraphDottingPatternData(uiPatternId, &sData) != A3D_SUCCESS) return; A3DBool bPush; stOpenGL_TreatColorIndex(sData.m_uiColorIndex, &bPush); double dPitch = sData.m_dPitch; double dX, dY = adMin[1]; double dXMax = adMax[0]; double dYMax = adMax[1]; glPointSize(0.5f); glBegin(GL_POINTS); if(sData.m_bZigZag) { double dPitch2 = dPitch * 2.f; double dXStart = adMin[0]; for(; dY < dYMax; dY += dPitch2) { for(dX = dXStart; dX < dXMax; dX += dPitch) { glVertex2d(dX, dY); } } dXStart += dPitch/2.; dY = adMin[1] + dPitch; for(; dY < dYMax; dY += dPitch2) { for(dX = dXStart; dX < dXMax; dX += dPitch) { glVertex2d(dX, dY); } } } else { for(; dY < dYMax; dY += dPitch) { dX = adMin[0]; for(; dX