Files
Hoops_Exchange/exchange/exchangesource/Viewer/callback_opengl.cpp
2025-12-15 23:22:33 +08:00

439 lines
19 KiB
C++

/***********************************************************************************************************************
*
* 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 <A3DSDKIncludes.h>
#include "callback_opengl.h"
#include "A3DVector.h"
#if !defined _MSC_VER && !defined CALLBACK
#define CALLBACK
#endif
#define _USE_MATH_DEFINES
#include <math.h>
#include <float.h>
#include <vector>
#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<unsigned> 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<GLfloat>(a_adRGB[0]), static_cast<GLfloat>(a_adRGB[1]), static_cast<GLfloat>(a_adRGB[2]) };
glColor3fv(afValues);
}
//######################################################################################################################
void OpenGL_Material(A3DEDrawMaterialType eType, const A3DDouble* pdValues, A3DUns32 uiSize)
{
if(uiSize == 1 && eType == kA3DDrawMaterialShininess)
{
GLfloat afValues[] = { static_cast<GLfloat>(pdValues[0]) };
glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, afValues);
}
else
{
GLfloat afValues[4] = { static_cast<GLfloat>(pdValues[0]), static_cast<GLfloat>(pdValues[1]), static_cast<GLfloat>(pdValues[2]), static_cast<GLfloat>((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();
}