Files
2025-12-15 23:22:33 +08:00

1262 lines
43 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.
***********************************************************************************************************************/
#define A3DAPI_DEPRECATED
#include <A3DSDKIncludes.h>
#include "callback_opengl.h"
#if !defined _MSC_VER && !defined CALLBACK
#define CALLBACK
#endif
#define _USE_MATH_DEFINES
#include <math.h>
#include <float.h>
#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<A3DUns8> 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;j<ucValue;j++)
{
usLineStipple |= 1<<p;
p++;
}
}
else
{
p += ucValue;
}
}
glLineStipple(2, usLineStipple);
}
A3DGlobalGetGraphLinePatternData(A3D_DEFAULT_LINEPATTERN_INDEX, &sPatternData);
}
}
//######################################################################################################################
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;
default:
break;
}
}
//######################################################################################################################
void OpenGL_End(A3DEDrawBeginEndType eType)
{
switch(eType)
{
case kA3DDrawBeginEndMarkup :
glPopAttrib();
break;
default:
break;
}
}
//######################################################################################################################
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);
}
//######################################################################################################################
// compute and call glNormal3d with a triangle normal
inline void glNormal3d_Triangle(const A3DVector3dData& sP1, const A3DVector3dData& sP2, const A3DVector3dData& sP3)
{
A3DVector3dData sNormal;
sNormal.m_dX = (sP2.m_dY - sP1.m_dY) * (sP3.m_dZ - sP2.m_dZ) - (sP2.m_dZ - sP1.m_dZ) * (sP3.m_dY - sP2.m_dY);
sNormal.m_dY = (sP2.m_dZ - sP1.m_dZ) * (sP3.m_dX - sP2.m_dX) - (sP2.m_dX - sP1.m_dX) * (sP3.m_dZ - sP2.m_dZ);
sNormal.m_dZ = (sP2.m_dX - sP1.m_dX) * (sP3.m_dY - sP2.m_dY) - (sP2.m_dY - sP1.m_dY) * (sP3.m_dX - sP2.m_dX);
A3DDouble dLength = sqrt(sNormal.m_dX*sNormal.m_dX + sNormal.m_dY*sNormal.m_dY + sNormal.m_dZ*sNormal.m_dZ);
sNormal.m_dX /= dLength;
sNormal.m_dY /= dLength;
sNormal.m_dZ /= dLength;
glNormal3d(sNormal);
}
//######################################################################################################################
// call glNormal3d or compute the triangle normal if normal is null
inline void glNormal3d_OrTriangleNormalIfNull(const A3DVector3dData& aNormal, const A3DVector3dData& sP1,
const A3DVector3dData& sP2, const A3DVector3dData& sP3)
{
if(aNormal.m_dX == 0 && aNormal.m_dY == 0 && aNormal.m_dZ == 0)
glNormal3d_Triangle(sP1, sP2, sP3);
else
glNormal3d(aNormal);
}
//######################################################################################################################
inline void glTriangleNormal(const A3DVector3dData& sP1, const A3DVector3dData& sP2, const A3DVector3dData& sP3,
const A3DVector3dData* pN = NULL)
{
A3DVector3dData sCenter;
sCenter.m_dX = (sP1.m_dX+sP2.m_dX+sP3.m_dX)/3.;
sCenter.m_dY = (sP1.m_dY+sP2.m_dY+sP3.m_dY)/3.;
sCenter.m_dZ = (sP1.m_dZ+sP2.m_dZ+sP3.m_dZ)/3.;
A3DVector3dData sNormal;
if(pN)
{
sNormal.m_dX = (*pN).m_dX;
sNormal.m_dY = (*pN).m_dY;
sNormal.m_dZ = (*pN).m_dZ;
}
else
{
sNormal.m_dX = (sP2.m_dY - sP1.m_dY) * (sP3.m_dZ - sP2.m_dZ) - (sP2.m_dZ - sP1.m_dZ) * (sP3.m_dY - sP2.m_dY);
sNormal.m_dY = (sP2.m_dZ - sP1.m_dZ) * (sP3.m_dX - sP2.m_dX) - (sP2.m_dX - sP1.m_dX) * (sP3.m_dZ - sP2.m_dZ);
sNormal.m_dZ = (sP2.m_dX - sP1.m_dX) * (sP3.m_dY - sP2.m_dY) - (sP2.m_dY - sP1.m_dY) * (sP3.m_dX - sP2.m_dX);
A3DDouble dLength = sqrt(sNormal.m_dX*sNormal.m_dX + sNormal.m_dY*sNormal.m_dY + sNormal.m_dZ*sNormal.m_dZ);
sNormal.m_dX /= dLength;
sNormal.m_dY /= dLength;
sNormal.m_dZ /= dLength;
}
glVertex3d(sCenter.m_dX, sCenter.m_dY, sCenter.m_dZ);
glVertex3d(sCenter.m_dX + sNormal.m_dX * stdDisplayTriangleNormalLength,
sCenter.m_dY + sNormal.m_dY * stdDisplayTriangleNormalLength,
sCenter.m_dZ + sNormal.m_dZ * stdDisplayTriangleNormalLength);
}
//######################################################################################################################
inline void glNormal(const A3DVector3dData& sP, const A3DVector3dData& sN)
{
A3DVector3dData sPPlusN;
sPPlusN.m_dX = sP.m_dX + sN.m_dX * stdDisplayTriangleNormalLength;
sPPlusN.m_dY = sP.m_dY + sN.m_dY * stdDisplayTriangleNormalLength;
sPPlusN.m_dZ = sP.m_dZ + sN.m_dZ * stdDisplayTriangleNormalLength;
glVertex3d(sP);
glVertex3d(sPPlusN);
}
//######################################################################################################################
inline void glTriangleNormals(const A3DVector3dData& sP1, const A3DVector3dData& sP2, const A3DVector3dData& sP3,
const A3DVector3dData& sN1, const A3DVector3dData& sN2, const A3DVector3dData& sN3)
{
glNormal(sP1, sN1);
glNormal(sP2, sN2);
glNormal(sP3, sN3);
}
//######################################################################################################################
inline void glTriangleAndNormalDisplay(const A3DVector3dData& sP1, const A3DVector3dData& sP2,
const A3DVector3dData& sP3, const A3DVector3dData& sN1,
const A3DVector3dData& sN2, const A3DVector3dData& sN3,
bool bOneNormal = false)
{
if(stiDisplayTriangles&2)
{
glColor3d(0, 0, 0);
glVertex3d(sP1);
glVertex3d(sP2);
glVertex3d(sP2);
glVertex3d(sP3);
glVertex3d(sP3);
glVertex3d(sP1);
}
if(stiDisplayTriangleNormals&1)
{
glColor3d(0, 0, 1);
glTriangleNormal(sP1, sP2, sP3);
}
if(stiDisplayTriangleNormals&2)
{
glColor3d(0, 1, 0);
if(bOneNormal)
glTriangleNormal(sP1, sP2, sP3, &sN1);
else
glTriangleNormals(sP1, sP2, sP3, sN1, sN2, sN3);
}
}
//######################################################################################################################
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();
}
//######################################################################################################################
void OpenGL_Triangle(const A3DVector3dData* pasNormals, const A3DVector3dData* pasPoints, A3DUns32 uiPointSize)
{
if(stiDisplayTriangles&1)
{
glBegin(GL_TRIANGLES);
for(A3DUns32 ui = 0; ui < uiPointSize; ++ui)
{
unsigned int uiTriangle = 3*(ui/3);
glNormal3d_OrTriangleNormalIfNull(pasNormals[ui], pasPoints[uiTriangle], pasPoints[uiTriangle+1],
pasPoints[uiTriangle+2]);
glVertex3d(pasPoints[ui]);
}
glEnd();
}
glStartLineDrawing();
for(A3DUns32 ui = 0; ui < uiPointSize/3; ++ui)
{
glTriangleAndNormalDisplay(pasPoints[ui*3], pasPoints[ui*3+1], pasPoints[ui*3+2], pasNormals[ui*3],
pasNormals[ui*3+1], pasNormals[ui*3+2]);
}
glEndLineDrawing();
}
//######################################################################################################################
void OpenGL_TriangleFan(const A3DVector3dData* pasNormals, const A3DVector3dData* pasPoints, A3DUns32 uiPointSize)
{
if(stiDisplayTriangles&1)
{
glBegin(GL_TRIANGLE_FAN);
for(A3DUns32 ui = 0; ui < uiPointSize; ++ui)
{
glNormal3d(pasNormals[ui].m_dX, pasNormals[ui].m_dY, pasNormals[ui].m_dZ);
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], pasNormals[ui-1], pasNormals[ui],
pasNormals[0]);
}
glEndLineDrawing();
}
//######################################################################################################################
void OpenGL_TriangleStripe(const A3DVector3dData* pasNormals, const A3DVector3dData* pasPoints, A3DUns32 uiPointSize)
{
if(stiDisplayTriangles&1)
{
glBegin(GL_TRIANGLE_STRIP);
for(A3DUns32 ui = 0; ui < uiPointSize; ++ui)
{
glNormal3d(pasNormals[ui].m_dX, pasNormals[ui].m_dY, pasNormals[ui].m_dZ);
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], pasNormals[ui-2],
pasNormals[ui-1], pasNormals[ui]);
}
else
{
glTriangleAndNormalDisplay(pasPoints[ui-1], pasPoints[ui-2], pasPoints[ui], pasNormals[ui-1],
pasNormals[ui-2], pasNormals[ui]);
}
}
glEndLineDrawing();
}
//######################################################################################################################
void OpenGL_TriangleOneNormal(const A3DVector3dData* pasNormals, const A3DVector3dData* pasPoints, A3DUns32 uiPointSize)
{
if(stiDisplayTriangles&1)
{
glBegin(GL_TRIANGLES);
glNormal3d(pasNormals->m_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<GLfloat>(adValues[0]), static_cast<GLfloat>(adValues[1]), static_cast<GLfloat>(adValues[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_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<dXMax; dX += dPitch)
{
glVertex2d(dX, dY);
}
}
}
glEnd();
if(bPush)
OpenGL_EndMaterial();
}
//######################################################################################################################
static void stOpenGL_Pattern_VPicture(A3DUns32 /*uiPatternId*/, A3DUns32 /*uiBehavior*/, A3DDouble* /*adMin*/, A3DDouble* /*adMax*/)
{
}
//######################################################################################################################
void OpenGL_Pattern(A3DUns32 uiLoopsSize, A3DUns32 uiPatternId, A3DUns32 /* uiFilledMode */, A3DUns32 uiBehavior,
const A3DDouble* pdPoints, const A3DUns32* puiLoopsPointSize)
{
A3DDouble adMin[3], adMax[3];
stOpenGL_Pattern_Start(uiLoopsSize, pdPoints, puiLoopsPointSize, adMin, adMax);
if(uiBehavior == 1)
{
A3DDouble adViewTransfo[16], adReverseViewTransfo[16];
OpenGL_GetMatrix(adViewTransfo);
adViewTransfo[12] = adViewTransfo[13] = adViewTransfo[14] = 0.;
stGenerateInverseMatrix4x4(adViewTransfo, adReverseViewTransfo);
OpenGL_PushMatrix();
OpenGL_MultMatrix(adReverseViewTransfo);
stTranfoPt(adViewTransfo, adMin);
stTranfoPt(adViewTransfo, adMax);
}
A3DEEntityType ePatternType = kA3DTypeUnknown;
A3DGlobalGetFillPatternType(uiPatternId, &ePatternType);
switch(ePatternType)
{
case kA3DTypeGraphHatchingPattern:
stOpenGL_Pattern_Hatching(uiPatternId, uiBehavior, adMin, adMax);
break;
case kA3DTypeGraphSolidPattern:
stOpenGL_Pattern_Solid(uiPatternId, uiBehavior, adMin, adMax);
break;
case kA3DTypeGraphDottingPattern:
stOpenGL_Pattern_Dotting(uiPatternId, uiBehavior, adMin, adMax);
break;
case kA3DTypeGraphVPicturePattern:
stOpenGL_Pattern_VPicture(uiPatternId, uiBehavior, adMin, adMax);
break;
default:
break;
}
if(uiBehavior == 1)
{
OpenGL_PopMatrix();
}
stOpenGL_Pattern_End();
}
//######################################################################################################################
void OpenGL_Picture(const A3DGraphPictureData* /* psPictureData */)
{
}
//######################################################################################################################
A3DStatus OpenGL_SetAndInitCallBack(deprecated_A3DDrawCallbacksData &sDrawCallbacksData)
{
A3D_INITIALIZE_DATA(deprecated_A3DDrawCallbacksData, sDrawCallbacksData);
sDrawCallbacksData.m_pfuncPushMatrix = OpenGL_PushMatrix;
sDrawCallbacksData.m_pfuncPopMatrix = OpenGL_PopMatrix;
sDrawCallbacksData.m_pfuncMultMatrix = OpenGL_MultMatrix;
sDrawCallbacksData.m_pfuncBegin = OpenGL_Begin;
sDrawCallbacksData.m_pfuncEnd = OpenGL_End;
sDrawCallbacksData.m_pfuncTriangle = OpenGL_Triangle;
sDrawCallbacksData.m_pfuncTriangleFan = OpenGL_TriangleFan;
sDrawCallbacksData.m_pfuncTriangleStripe = OpenGL_TriangleStripe;
sDrawCallbacksData.m_pfuncTriangleOneNormal = OpenGL_TriangleOneNormal;
sDrawCallbacksData.m_pfuncTriangleFanOneNormal = OpenGL_TriangleFanOneNormal;
sDrawCallbacksData.m_pfuncTriangleStripeOneNormal = OpenGL_TriangleStripeOneNormal;
sDrawCallbacksData.m_pfuncTriangleTextured = OpenGL_TriangleTextured;
sDrawCallbacksData.m_pfuncTriangleFanTextured = OpenGL_TriangleFanTextured;
sDrawCallbacksData.m_pfuncTriangleStripeTextured = OpenGL_TriangleStripeTextured;
sDrawCallbacksData.m_pfuncTriangleOneNormalTextured = OpenGL_TriangleOneNormal;
sDrawCallbacksData.m_pfuncTriangleFanOneNormalTextured = OpenGL_TriangleFanOneNormalTextured;
sDrawCallbacksData.m_pfuncTriangleStripeOneNormalTextured = OpenGL_TriangleStripeOneNormalTextured;
sDrawCallbacksData.m_pfuncMaterial = OpenGL_Material;
sDrawCallbacksData.m_pfuncColor = OpenGL_Color;
sDrawCallbacksData.m_pfuncGetDrawContext = OpenGL_GetDrawContext;
sDrawCallbacksData.m_pfuncMarkupTriangle = OpenGL_MarkupTriangle;
sDrawCallbacksData.m_pfuncUnProject = OpenGL_UnProject;
sDrawCallbacksData.m_pfuncBeginFrameDraw = OpenGL_BeginFrameDraw;
sDrawCallbacksData.m_pfuncEndFrameDraw = OpenGL_EndFrameDraw;
sDrawCallbacksData.m_pfuncBeginFixedSize = OpenGL_BeginFixedSize;
sDrawCallbacksData.m_pfuncEndFixedSize = OpenGL_EndFixedSize;
sDrawCallbacksData.m_pfuncCylinder = OpenGL_Cylinder;
sDrawCallbacksData.m_pfuncPolygon = OpenGL_Polygon;
sDrawCallbacksData.m_pfuncBeginLineWidth = OpenGL_BeginLineWidth;
sDrawCallbacksData.m_pfuncEndLineWidth = OpenGL_EndLineWidth;
sDrawCallbacksData.m_pfuncPoint = OpenGL_Point;
sDrawCallbacksData.m_pfuncFont = OpenGL_Font;
sDrawCallbacksData.m_pfuncBeginLineStipple = OpenGL_BeginLineStipple;
sDrawCallbacksData.m_pfuncEndLineStipple = OpenGL_EndLineStipple;
sDrawCallbacksData.m_pfuncSymbol = OpenGL_Symbol;
sDrawCallbacksData.m_pfuncPolyLine = OpenGL_PolyLine;
sDrawCallbacksData.m_pfuncText = OpenGL_Text;
sDrawCallbacksData.m_pfuncPattern = OpenGL_Pattern;
sDrawCallbacksData.m_pfuncPicture = OpenGL_Picture;
sDrawCallbacksData.m_pfuncBeginMaterial = OpenGL_BeginMaterial;
sDrawCallbacksData.m_pfuncEndMaterial = OpenGL_EndMaterial;
return A3DORNOTDrawInitCallbacks(&sDrawCallbacksData);
}