// GraphCtl.cpp : Implementation of CGraphCtl
//
// Autor : Nikolai Teofilov nteofilov@yahoo.de
//
// Comment : Use with your own risk !
//
// Copyright (c) 2003.
#include "stdafx.h"
#include "NTGraph3D.h"
#include "GraphCtl.h"
static const FONTDESC _fontdesc =
{sizeof(FONTDESC), OLESTR("times new roman"), FONTSIZE( 14 ),
FW_BOLD, ANSI_CHARSET, TRUE, FALSE, FALSE };
/////////////////////////////////////////////////////////////////////////////
// CGraphCtl
unsigned char threeto8[8] =
{
0, 0111>>1, 0222>>1, 0333>>1, 0444>>1, 0555>>1, 0666>>1, 0377
};
unsigned char twoto8[4] =
{
0, 0x55, 0xaa, 0xff
};
unsigned char oneto8[2] =
{
0, 255
};
static int defaultOverride[13] =
{
0, 3, 24, 27, 64, 67, 88, 173, 181, 236, 247, 164, 91
};
static PALETTEENTRY defaultPalEntry[20] =
{
{ 0, 0, 0, 0 },
{ 0x80,0, 0, 0 },
{ 0, 0x80,0, 0 },
{ 0x80,0x80,0, 0 },
{ 0, 0, 0x80, 0 },
{ 0x80,0, 0x80, 0 },
{ 0, 0x80,0x80, 0 },
{ 0xC0,0xC0,0xC0, 0 },
{ 192, 220, 192, 0 },
{ 166, 202, 240, 0 },
{ 255, 251, 240, 0 },
{ 160, 160, 164, 0 },
{ 0x80,0x80,0x80, 0 },
{ 0xFF,0, 0, 0 },
{ 0, 0xFF,0, 0 },
{ 0xFF,0xFF,0, 0 },
{ 0, 0, 0xFF, 0 },
{ 0xFF,0, 0xFF, 0 },
{ 0, 0xFF,0xFF, 0 },
{ 0xFF,0xFF,0xFF, 0 }
};
void CGraphCtl::CreateContext(HDC hdc, RECT& rc)
{
PIXELFORMATDESCRIPTOR pfd;
GLfloat fMaxObjSize, fAspect;
GLfloat fNearPlane, fFarPlane;
if (!bSetupPixelFormat(hdc))
return;
CreateRGBPalette(hdc);
::SelectPalette(hdc, m_hPal, FALSE);
::RealizePalette(hdc);
int n = ::GetPixelFormat(hdc);
::DescribePixelFormat(hdc, n, sizeof(pfd), &pfd);
m_hrc = wglCreateContext(hdc);
wglMakeCurrent(hdc, m_hrc);
glClearDepth(10.0f);
glEnable(GL_DEPTH_TEST);
if (rc.bottom)
fAspect = (GLfloat)rc.right/rc.bottom;
else // don't divide by zero, not that we should ever run into that...
fAspect = 1.0f;
fNearPlane = 3.0f;
fFarPlane = 20.0f;
fMaxObjSize = 3.0f;
m_fRadius = fNearPlane + fMaxObjSize / 2.0f;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// update the camera
if (m_nProjection == Orthographic)
glOrtho(-1,1,-1,1,fNearPlane,fFarPlane);
else
gluPerspective(30.0f, fAspect, fNearPlane, fFarPlane);
glMatrixMode(GL_MODELVIEW);
}
LRESULT CGraphCtl::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
// Won't be here unless we just got activated and created a window
HDC hdc = GetDC();
RECT rc;
GetClientRect(&rc);
CreateContext(hdc, rc);
return 0;
}
LRESULT CGraphCtl::OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
::wglMakeCurrent(NULL, NULL);
if (m_hrc)
{
::wglDeleteContext(m_hrc);
m_hrc = NULL;
}
return 0;
}
LRESULT CGraphCtl::OnLButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
SetCapture();
m_bMouseCaptured = TRUE;
m_xPos = (short)LOWORD(lParam); // horizontal position of cursor
m_yPos = (short)HIWORD(lParam); // vertical position of cursor
return 0;
}
LRESULT CGraphCtl::OnLButtonUP(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
m_bMouseCaptured = FALSE;
ReleaseCapture();
FireViewChange();
return 0;
}
LRESULT CGraphCtl::OnMouseMove(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
if (m_bMouseCaptured)
{
int xPos = (short)LOWORD(lParam); // horizontal position of cursor
int yPos = (short)HIWORD(lParam); // vertical position of cursor
GLfloat fNearPlane = 3.0f;
GLfloat fFarPlane = 7.0f;
GLfloat fMaxObjSize = 3.0f;
if (m_nTrackState == Zoom)
{
m_fRadius += (float)(m_xPos - xPos)/100.0f;
FireViewChange();
}
else if (m_nTrackState == Rotate)
{
m_wAngleX -= (float)(m_yPos - yPos)/2.0f;
m_wAngleY -= (float)(m_xPos - xPos)/2.0f;
FireViewChange();
}
else if (m_nTrackState == Pan)
{
DoPan(xPos,yPos);
}
m_xPos = xPos;
m_yPos = yPos;
}
return 0;
}
void CGraphCtl::DoPan(int x, int y)
{
double Y1 = y + dRangeY[MIN]/(dRangeY[MAX]-dRangeY[MIN]) + 0.5;
double Y2 = m_yPos + dRangeY[MIN]/(dRangeY[MAX]-dRangeY[MIN]) + 0.5;
double yOffset = (Y1 - Y2)/100.0;
double X1 = x + dRangeX[MIN]/(dRangeX[MAX]-dRangeX[MIN]) + 0.5;
double X2 = m_xPos + dRangeX[MIN]/(dRangeX[MAX]-dRangeX[MIN]) + 0.5;
double xOffset = (X1 - X2)/100.0;
SetRange(dRangeX[MIN] - xOffset, dRangeX[MAX] - xOffset,
dRangeY[MIN] + yOffset, dRangeY[MAX] + yOffset,
dRangeZ[MIN] + xOffset, dRangeZ[MAX] + xOffset);
}
HRESULT CGraphCtl::OnDraw(ATL_DRAWINFO& di)
{
HDC hdc = di.hdcDraw;
RECT& rc = *(RECT*)di.prcBounds;
DrawGraph(hdc, rc);
return 1;
}
STDMETHODIMP CGraphCtl::CopyToClipboard()
{
HDC hdc = GetDC();
// Get client geometry
RECT rc;
GetClientRect(&rc);
LONG
width = rc.right - rc.left,
height = rc.bottom - rc.top;
int bitsPerPixel = ::GetDeviceCaps(hdc, BITSPIXEL);
switch(bitsPerPixel)
{
case 8:
case 24:
width -= width % 4;
break;
case 16:
width -= width % 2;
break;
case 32:
default:
break;
}
// Alloc pixel bytes
int NbBytes = bitsPerPixel/8 * width * height;
// Fill header
BITMAPINFOHEADER header;
header.biWidth = width;
header.biHeight = height;
header.biSizeImage = NbBytes;
header.biSize = 40;
header.biPlanes = 1;
header.biBitCount = 3 * 8; // RGB
header.biCompression = 0;
header.biXPelsPerMeter = 0;
header.biYPelsPerMeter = 0;
header.biClrUsed = 0;
header.biClrImportant = 0;
// Generate handle
HANDLE handle = (HANDLE)::GlobalAlloc (GHND,sizeof(BITMAPINFOHEADER) + NbBytes);
if(handle != NULL)
{
// Lock handle
char *pData = (char *) ::GlobalLock((HGLOBAL)handle);
// Copy header and data
memcpy(pData,&header,sizeof(BITMAPINFOHEADER));
::glReadPixels(0,0,width,height,GL_BGR_EXT,GL_UNSIGNED_BYTE,pData+sizeof(BITMAPINFOHEADER));
// Unlock
::GlobalUnlock((HGLOBAL)handle);
// Push DIB in clipboard
OpenClipboard();
EmptyClipboard();
SetClipboardData(CF_DIB,handle);
CloseClipboard();
}
ReleaseDC(hdc);
return S_OK;
}
void CGraphCtl::DrawBorder(HDC hdc, RECT rc)
{
if (m_bBorderVisible)
switch(m_nBorderStyle)
{
case bump:
if(m_nAppearance)
::DrawEdge(hdc, &rc, EDGE_BUMP|EDGE_SUNKEN, BF_RECT);
else
::DrawEdge(hdc, &rc, EDGE_BUMP, BF_RECT);
break;
case etched:
if(m_nAppearance)
::DrawEdge(hdc, &rc, EDGE_ETCHED|EDGE_SUNKEN, BF_RECT);
else
::DrawEdge(hdc, &rc, EDGE_ETCHED, BF_RECT);
break;
case raised:
if(m_nAppearance)
::DrawEdge(hdc, &rc, EDGE_RAISED|EDGE_SUNKEN, BF_RECT);
else
::DrawEdge(hdc, &rc, EDGE_RAISED, BF_RECT);
break;
default:
::DrawEdge(hdc, &rc, EDGE_SUNKEN, BF_RECT);
break;
}
else if(m_nAppearance && !m_bBorderVisible)
::DrawEdge(hdc, &rc, EDGE_SUNKEN, BF_RECT);
}
void CGraphCtl::DrawGraph(HDC hdc, RECT rc)
{
::SelectPalette(hdc, m_hPal, FALSE);
::RealizePalette(hdc);
wglMakeCurrent(hdc, m_hrc);
COLORREF colBkgn;
OleTranslateColor(m_clrBackColor, m_hPal, &colBkgn);
SetTextColor(hdc, colBkgn);
SetBkColor(colBkgn);
glPushMatrix();
glTranslatef(0.0f, 0.0f, -m_fRadius);
glRotatef(m_wAngleX, 1.0f, 0.0f, 0.0f);
glRotatef(m_wAngleY, 0.0f, 1.0f, 0.0f);
glRotatef(m_wAngleZ, 0.0f, 0.0f, 1.0f);
if(m_bMouseCaptured && m_nTrackState != Pan)
DrawAxis();
else
{
DrawAxisBox();
DrawAxisGrid();
DrawAxisLabels(hdc);
PlotElement();
}
glPopMatrix();
glFinish();
SwapBuffers(wglGetCurrentDC());
DrawGraphTitle(hdc,rc);
DrawBorder(hdc,rc);
}
void CGraphCtl::DrawGraphTitle(HDC hdc, RECT rc)
{
COLORREF colT;
OleTranslateColor(m_clrCaptionColor, m_hPal, &colT);
SetTextColor(hdc, colT);
SetBkMode(hdc, TRANSPARENT);
USES_CONVERSION;
LPCTSTR lpsz = OLE2T(m_bstrCaption);
DrawText(hdc, lpsz, -1, &rc, DT_CENTER | DT_TOP | DT_SINGLELINE);
}
void CGraphCtl::DrawAxis()
{
// draw carthesian axes
glBegin(GL_LINES);
// red x axis
glColor3f(1.f,0.f,0.f);
glVertex3f(-0.5f,-0.5f,-0.5f);
glVertex3f(0.5f,-0.5f,-0.5f);
glVertex3f(0.4f, -0.4f, -0.5f);
glVertex3f(0.5f, -0.5f, -0.5f);
glVertex3f(0.4f, -0.6f, -0.5f);
glVertex3f(0.5f,-0.5f,-0.5f);
glVertex3f(0.6f,-0.6f,-0.5f);
glVertex3f(0.7f,-0.4f,-0.5f);
glVertex3f(0.7f,-0.6f,-0.5f);
glVertex3f(0.6f,-0.4f,-0.5f);
// green y axis
glColor3f(0.0f, 1.0f, 0.0f);
glVertex3f(-0.5f,-0.5f,-0.5f);
glVertex3f(-0.5f,0.5f,-0.5f);
glVertex3f(-0.5f,0.5f,-0.5f);
glVertex3f(-0.4f,0.4f,-0.5f);
glVertex3f(-0.5f,0.5f,-0.5f);
glVertex3f(-0.6f,0.4f,-0.5f);
glVertex3f(-0.5f,0.6f,-0.5f);
glVertex3f(-0.5f,0.7f,-0.5f);
glVertex3f(-0.5f,0.7f,-0.5f);
glVertex3f(-0.6f,0.8f,-0.5f);
glVertex3f(-0.6f,0.8f,-0.5f);
glVertex3f(-0.5f,0.7f,-0.5f);
glVertex3f(-0.5f,0.7f,-0.5f);
glVertex3f(-0.4f,0.8f,-0.5f);
// blue z axis
glColor3f(0.f,0.f,1.f);
glVertex3f(-0.5f, -0.5f, -0.5f);
glVertex3f(-0.5f, -0.5f, 0.5f);
glVertex3f(-0.5f, -0.5f, 0.5f);
glVertex3f(-0.5f, -0.6f, 0.4f);
glVertex3f(-0.5f, -0.5f, 0.5f);
glVertex3f(-0.5f, -0.4f, 0.4f);
glVertex3f(-0.5f,-0.4f,0.7f);
glVertex3f(-0.5f,-0.4f,0.6f);
glVertex3f(-0.5f,-0.4f,0.6f);
glVertex3f(-0.5f,-0.6f,0.7f);
glVertex3f(-0.5f,-0.6f,0.7f);
glVertex3f(-0.5f,-0.6f,0.6f);
glEnd();
// glColor3f(1.0f, 0.0f, 0.0f);
// auxWireSphere(2.5);
}
void CGraphCtl::DrawAxisBox()
{
COLORREF colX,colY,colZ;
OleTranslateColor(m_clrXGridColor, m_hPal, &colX);
OleTranslateColor(m_clrYGridColor, m_hPal, &colY);
OleTranslateColor(m_clrZGridColor, m_hPal, &colZ);
glLineWidth(1.0f);
glBegin(GL_LINE_STRIP);
// x axis
SetColor(colX);
glVertex3f(-0.5f, -0.5f, -0.5f);
glVertex3f(0.5f, -0.5f, -0.5f);
glVertex3f(0.5f, -0.5f, -0.5f);
glVertex3f(0.5f, 0.5f, -0.5f);
glVertex3f(0.5f, 0.5f, -0.5f);
glVertex3f(-0.5f, 0.5f, -0.5f);
// y axis
SetColor(colY);
glVertex3f(-0.5f, -0.5f, -0.5f);
glVertex3f(-0.5f, 0.5f, -0.5f);
glVertex3f(-0.5f, 0.5f, -0.5f);
glVertex3f(-0.5f, 0.5f, 0.5f);
glVertex3f(-0.5f, 0.5f, 0.5f);
glVertex3f(-0.5f, -0.5f, 0.5f);
// z axis
SetColor(colZ);
glVertex3f(-0.5f, -0.5f, -0.5f);
glVertex3f(-0.5f, -0.5f, 0.5f);
glVertex3f(-0.5f, -0.5f, 0.5f);
glVertex3f(0.5f, -0.5f, 0.5f);
glVertex3f(0.5f, -0.5f, 0.5f);
glVertex3f(0.5f, -0.5f, 0.5f);
glVertex3f(0.5f, -0.5f, -0.5f);
glEnd();
}
void CGraphCtl::DrawAxisGrid()
{
glBegin(GL_LINES);
float X,Y,Z;
int i;
COLORREF colX, colY, colZ;
OleTranslateColor(m_clrXGridColor, m_hPal, &colX);
OleTranslateColor(m_clrYGridColor, m_hPal, &colY);
OleTranslateColor(m_clrZGridColor, m_hPal, &colZ);
// Draw X Grid
for ( i = 0 ; i <= m_nGridX ; i++)
{
X = ((float)i)/m_nGridX;
// x axis
SetColor(colX);
glVertex3f(X-0.5f, -0.5f, -0.5f);
glVertex3f(X-0.5f, 0.5f, -0.5f);
SetColor(colZ);
glVertex3f(X-0.5f, -0.5f, -0.5f);
glVertex3f(X-0.5f, -0.5f, 0.5f);
}
// Draw Y Grid
for ( i = 0 ; i <= m_nGridY ; i++)
{
Y = ((float)i)/m_nGridY;
// y axis
SetColor(colX);
glVertex3f(-0.5f, Y-0.5f, -0.5f);
glVertex3f( 0.5f, Y-0.5f, -0.5f);
SetColor(colY);
glVertex3f(-0.5f, Y-0.5f, -0.5f);
glVertex3f(-0.5f, Y-0.5f, 0.5f);
}
// Draw Z Grid
for ( i = 0 ; i <= m_nGridZ ; i++)
{
Z = ((float)i)/m_nGridZ;
// z axis
SetColor(colZ);
glVertex3f(-0.5f ,-0.5f ,Z-0.5f);
glVertex3f( 0.5f ,-0.5f ,Z-0.5f);
SetColor(colY);
glVertex3f(-0.5f ,-0.5f ,Z-0.5f);
glVertex3f(-0.5f , 0.5f ,Z-0.5f);
}
glEnd();
}
void CGraphCtl::DrawAxisLabels(HDC hdc)
{
float X,Y,Z,res;
int i;
char str[50];
CPoint3D pt;
COLORREF colX, colY, colZ;
OleTranslateColor(m_clrXGridColor, m_hPal, &colX);
OleTranslateColor(m_clrYGridColor, m_hPal, &colY);
OleTranslateColor(m_clrZGridColor, m_hPal, &colZ);
// Draw X Grid Label
res = (dRangeX[MAX] - dRangeX[MIN]) / m_nGridX ;
for ( i = 0 ; i <= m_nGridX ; i++)
{
X = dRangeX[MIN] + (res * (float)i);
sprintf(str,"%g",X);
X = ((float)i)/m_nGridX;
// red x axis
//glColor3f(1.f,0.f,0.f);
SetColor(colX);
pt=CPoint3D(-0.5,-0.5,0.5);
pt.Translate(X,0.0,0.3);
PrintText(hdc, pt, str);
}
// Draw Y Grid Label
res = (dRangeY[MAX] - dRangeY[MIN]) / m_nGridY ;
for ( i = 0 ; i <= m_nGridY ; i++)
{
Y = dRangeY[MIN] + (res * (float)i) ;
sprintf(str,"%g",Y);
Y = ((float)i)/m_nGridY;
// green y axis
//glColor3f(0.f,1.f,0.f);
SetColor(colY);
pt = CPoint3D(-0.5,-0.5,0.5);
pt.Translate(0.0,Y,0.3);
PrintText(hdc, pt, str);
}
// Draw Z Grid Label
res = (dRangeZ[MAX] - dRangeZ[MIN]) / m_nGridZ ;
for ( i = 0 ; i <= m_nGridZ ; i++)
{
Z = dRangeZ[MIN] + (res * (float)i) ;
sprintf(str,"%g",Z);
Z = ((float)i)/m_nGridZ;
// blue z axis
//glColor3f(0.f,0.f,1.f);
SetColor(colZ);
pt = CPoint3D(0.5,-0.5,-0.5);
pt.Translate (0.2,0.0,Z);
PrintText(hdc, pt, str);
}
// Draw Axis Titles
SetColor(RGB(0,0,0));
// Native C++ compiler COM support
// BSTR, VARIANT wrappers header
using namespace _com_util;
SetColor(colX);
PrintText(hdc,CPoint3D(0.0f,0.7f,-0.5f),
ConvertBSTRToString(m_bstrXLabel));
SetColor(colY);
PrintText(hdc,CPoint3D(0.7f,0.0f,-0.5f),
ConvertBSTRToString(m_bstrYLabel));
SetColor(colZ);
PrintText(hdc,CPoint3D(-0.5f,0.7f,0.0f),
ConvertBSTRToString(m_bstrZLabel));
glEnd();
}
BOOL CGraphCtl::bSetupPixelFormat(HDC hdc)
{
static PIXELFORMATDESCRIPTOR pfd =
{
sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd
1, // version number
PFD_DRAW_TO_WINDOW | // support window
PFD_SUPPORT_OPENGL | // support OpenGL
PFD_DOUBLEBUFFER, // double buffered
PFD_TYPE_RGBA, // RGBA type
24, // 24-bit color depth
0, 0, 0, 0, 0, 0, // color bits ignored
0, // no alpha buffer
0, // shift bit ignored
0, // no accumulation buffer
0, 0, 0, 0, // accum bits ignored
32, // 32-bit z-buffer
0, // no stencil buffer
0, // no auxiliary buffer
PFD_MAIN_PLANE, // main layer
0, // reserved
0, 0, 0 // layer masks ignored
};
int pixelformat;
if ( (pixelformat = ChoosePixelFormat(hdc, &pfd)) == 0 )
{
ATLASSERT(FALSE);
return FALSE;
}
if (SetPixelFormat(hdc, pixelformat, &pfd) == FALSE)
{
ATLASSERT(FALSE);
return FALSE;
}
return TRUE;
}
void CGraphCtl::PrintText(HDC hdc, CPoint3D pt, const char *str)
{
HFONT hOldFont = NULL;
if (m_pFont)
{
CComPtr<IFont> pFont;
m_pFont->QueryInterface(IID_IFont, (void**)&pFont);
HFONT hfont;
pFont->get_hFont(&hfont);
hOldFont = (HFONT) SelectObject(hdc, hfont);
}
else
SelectObject (hdc, GetStockObject (SYSTEM_FONT));
// create bitmaps for the device context font's first 256 glyphs
wglUseFontBitmaps(hdc, 0, 256, 1000);
// move to position
glRasterPos3f(pt.x,pt.y,pt.z);
// set up for a string-drawing display list call
glListBase(1000);
// draw a string using font display lists
glCallLists(strlen(str), GL_UNSIGNED_BYTE, (GLubyte*)str);
// get all those commands to execute
glFlush();
// delete our 256 glyph display lists
glDeleteLists(1000, 256) ;
if (hOldFont)
SelectObject(hdc, hOldFont);
}
unsigned char CGraphCtl::ComponentFromIndex(int i, UINT nbits, UINT shift)
{
unsigned char val;
val = (unsigned char) (i >> shift);
switch (nbits)
{
case 1:
val &= 0x1;
return oneto8[val];
case 2:
val &= 0x3;
return twoto8[val];
case 3:
val &= 0x7;
return threeto8[val];
default:
return 0;
}
}
void CGraphCtl::CreateRGBPalette(HDC hdc)
{
PIXELFORMATDESCRIPTOR pfd;
int n, i;
if (m_pPal)
return;
n = ::GetPixelFormat(hdc);
::DescribePixelFormat(hdc, n, sizeof(pfd), &pfd);
if (pfd.dwFlags & PFD_NEED_PALETTE)
{
n = 1 << pfd.cColorBits;
m_pPal = (PLOGPALETTE) new char[sizeof(LOGPALETTE) + n * sizeof(PALETTEENTRY)];
ATLASSERT(m_pPal != NULL);
m_pPal->palVersion = 0x300;
m_pPal->palNumEntries = n;
for (i=0; i<n; i++)
{
m_pPal->palPalEntry[i].peRed =
ComponentFromIndex(i, pfd.cRedBits, pfd.cRedShift);
m_pPal->palPalEntry[i].peGreen =
ComponentFromIndex(i, pfd.cGreenBits, pfd.cGreenShift);
m_pPal->palPalEntry[i].peBlue =
ComponentFromIndex(i, pfd.cBlueBits, pfd.cBlueShift);
m_pPal->palPalEntry[i].peFlags = 0;
}
/* fix up the palette to include the default GDI palette */
if ((pfd.cColorBits == 8) &&
(pfd.cRedBits == 3) && (pfd.cRedShift == 0) &&
(pfd.cGreenBits == 3) && (pfd.cGreenShift == 3) &&
(pfd.cBlueBits == 2) && (pfd.cBlueShift == 6)
)
{
for (i = 1 ; i <= 12 ; i++)
m_pPal->palPalEntry[defaultOverride[i]] = defaultPalEntry[i];
}
m_hPal = ::CreatePalette((LPLOGPALETTE)m_pPal);
// delete pPal;
::SelectPalette(hdc, m_hPal, FALSE);
::RealizePalette(hdc);
}
}
STDMETHODIMP CGraphCtl::get_CaptionColor(OLE_COLOR *pVal)
{
*pVal = m_clrCaptionColor;
return S_OK;
}
STDMETHODIMP CGraphCtl::put_CaptionColor(OLE_COLOR newVal)
{
m_clrCaptionColor = newVal;
SetDirty(TRUE);
FireViewChange();
return S_OK;
}
STDMETHODIMP CGraphCtl::SetRange(double xmin, double xmax, double ymin, double ymax, double zmin, double zmax)
{
if (xmin==xmax || ymin==ymax || zmin==zmax)
return S_OK;
else if (xmin>xmax || ymin>ymax || zmin>zmax)
return S_OK;
else
{
dRangeX[MIN]=xmin;
dRangeX[MAX]=xmax;
dRangeY[MIN]=ymin;
dRangeY[MAX]=ymax;
dRangeZ[MIN]=zmin;
dRangeZ[MAX]=zmax;
}
FireViewChange(); // call the InvalidateRect API directly!
SetDirty(TRUE);
return S_OK;
}
STDMETHODIMP CGraphCtl::AutoRange()
{
if (!bIsPlotAvailable) {
SetRange(0,1,0,1,0,1);
return S_OK;
}
SetRange(dAutoRangeX[MIN],dAutoRangeX[MAX],
dAutoRangeY[MIN],dAutoRangeY[MAX],
dAutoRangeZ[MIN],dAutoRangeZ[MAX]);
return S_OK;
}
STDMETHODIMP CGraphCtl::ShowPropertyPages()
{
DoVerbProperties(NULL,NULL);
return S_OK;
}
STDMETHODIMP CGraphCtl::get_TrackMode(short *pVal)
{
*pVal = m_nTrackState;
return S_OK;
}
STDMETHODIMP CGraphCtl::put_TrackMode(short newVal)
{
if (newVal >= 0 && newVal < 4)
{
m_nTrackState = newVal;
SetDirty(TRUE);
return S_OK;
}
else
return Error(_T("Track State must have between 0 and 3"));
return S_OK;
}
STDMETHODIMP CGraphCtl::put_Projection(short newVal)
{
newVal = newVal < 0 ? 0: newVal;
newVal = newVal > 1 ? 1: newVal;
m_nProjection = newVal;
SetDirty(TRUE);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// update the camera
if (m_nProjection == Orthographic)
glOrtho(-1,1,-1,1,3.0f,20.0f);
else
gluPerspective(30.0f, 1.0f, 3.0f, 20.0f);
glMatrixMode(GL_MODELVIEW);
FireViewChange();
return S_OK;
}
STDMETHODIMP CGraphCtl::get_Projection(short *pVal)
{
*pVal = m_nProjection;
return S_OK;
}
STDMETHODIMP CGraphCtl::get_XLabel(BSTR *pVal)
{
ATLTRACE(_T("IGraph3D::get_XLabel\n"));
*pVal = m_bstrXLabel.Copy();
return S_OK;
}
STDMETHODIMP CGraphCtl::put_XLabel(BSTR newVal)
{
USES_CONVERSION;
ATLTRACE(_T("IGraph3D::put_XLabel\n"));
m_bstrXLabel = newVal;
SetDirty(TRUE);
FireViewChange();
return S_OK;
}
STDMETHODIMP CGraphCtl::get_YLabel(BSTR *pVal)
{
ATLTRACE(_T("IGraph3D::get_YLabel\n"));
*pVal = m_bstrYLabel.Copy();
return S_OK;
}
STDMETHODIMP CGraphCtl::put_YLabel(BSTR newVal)
{
USES_CONVERSION;
ATLTRACE(_T("IGraph3D::put_YLabel\n"));
m_bstrYLabel = newVal;
SetDirty(TRUE);
FireViewChange();
return S_OK;
}
STDMETHODIMP CGraphCtl::get_ZLabel(BSTR *pVal)
{
ATLTRACE(_T("IGraph3D::get_ZLabel\n"));
*pVal = m_bstrZLabel.Copy();
return S_OK;
}
STDMETHODIMP CGraphCtl::put_ZLabel(BSTR newVal)
{
USES_CONVERSION;
ATLTRACE(_T("IGraph3D::put_ZLabel\n"));
m_bstrZLabel = newVal;
SetDirty(TRUE);
FireViewChange();
return S_OK;
}
STDMETHODIMP CGraphCtl::get_XGridNumber(short *pVal)
{
*pVal = m_nGridX;
return S_OK;
}
STDMETHODIMP CGraphCtl::put_XGridNumber(short newVal)
{
newVal = newVal < 0 ? 1: newVal;
newVal = newVal > 10 ? 10: newVal;
m_nGridX = newVal;
SetDirty(TRUE);
FireViewChange(); // call the InvalidateRect API directly!
return S_OK;
}
STDMETHODIMP CGraphCtl::get_YGridNumber(short *pVal)
{
*pVal = m_nGridY;
return S_OK;
}
STDMETHODIMP CGraphCtl::put_YGridNumber(short newVal)
{
newVal = newVal < 0 ? 1: newVal;
newVal = newVal > 10 ? 10: newVal;
m_nGridY = newVal;
SetDirty(TRUE);
FireViewChange(); // call the InvalidateRect API directly!
return S_OK;
}
STDMETHODIMP CGraphCtl::get_ZGridNumber(short *pVal)
{
*pVal = m_nGridZ;
return S_OK;
}
STDMETHODIMP CGraphCtl::put_ZGridNumber(short newVal)
{
newVal = newVal < 0 ? 1: newVal;
newVal = newVal > 10 ? 10: newVal;
m_nGridZ = newVal;
SetDirty(TRUE);
FireViewChange(); // call the InvalidateRect API directly!
return S_OK;
}
STDMETHODIMP CGraphCtl::get_XGridColor(OLE_COLOR *pVal)
{
*pVal = m_clrXGridColor;
return S_OK;
}
STDMETHODIMP CGraphCtl::put_XGridColor(OLE_COLOR newVal)
{
m_clrXGridColor = newVal;
SetDirty(TRUE);
FireViewChange();
return S_OK;
}
STDMETHODIMP CGraphCtl::get_YGridColor(OLE_COLOR *pVal)
{
*pVal = m_clrYGridColor;
return S_OK;
}
STDMETHODIMP CGraphCtl::put_YGridColor(OLE_COLOR newVal)
{
m_clrYGridColor = newVal;
SetDirty(TRUE);
FireViewChange();
return S_OK;
}
STDMETHODIMP CGraphCtl::get_ZGridColor(OLE_COLOR *pVal)
{
*pVal = m_clrZGridColor;
return S_OK;
}
STDMETHODIMP CGraphCtl::put_ZGridColor(OLE_COLOR newVal)
{
m_clrZGridColor = newVal;
SetDirty(TRUE);
FireViewChange();
return S_OK;
}
void CGraphCtl::PlotElement()
{
ELEMENTVECTOR::iterator theElement;
for (theElement = m_ElementList.begin();
theElement != m_ElementList.end();
theElement++)
{
// Prevent plotting of non-existing data
if (! theElement->bIsPlotAvailable )
continue;
//////////////////////////////////
// Check show state of the element
if (! theElement->m_bShow )
continue;
if (theElement->m_bLights)
{
SetLight(theElement);
glEnable(GL_LIGHTING); // Lighting will be used
glEnable(GL_LIGHT0); // Only one (first) source of light
glEnable(GL_DEPTH_TEST);// The depth of the Z-buffer will be taken into account
glEnable(GL_COLOR_MATERIAL);// Material colors will be taken into account
}
POINTVECTOR::iterator aPoint;
// Draw Lines
if (theElement->m_nType == Lines || theElement->m_nType == LinePoint)
{
glLineWidth(theElement->m_LineWidth);
glBegin(GL_LINE_STRIP);
SetColor(theElement->m_LineColor);
aPoint = theElement->m_PointList.begin();
for (aPoint; aPoint != theElement->m_PointList.end(); aPoint++)
{
if (PtInRange(aPoint))
{
CPoint3D pt = Corrdinate(aPoint);
glVertex3f(pt.x,pt.y,pt.z);
}
}
glEnd();
}
// Now draw points.
if ( theElement->m_nType == Points || theElement->m_nType == LinePoint )
{
glPointSize(theElement->m_PointSize);
glBegin(GL_POINTS);
SetColor(theElement->m_PointColor);
aPoint = theElement->m_PointList.begin();
for (aPoint; aPoint != theElement->m_PointList.end(); aPoint++)
{
if (PtInRange(aPoint))
{
CPoint3D pt = Corrdinate(aPoint);
glVertex3f(pt.x,pt.y,pt.z);
}
}
glEnd();
}
if ( theElement->m_nType == Surface )
{
// Set the polygon filling mode
if (theElement->m_bFill)
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
else
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
if (theElement->m_bFlat)
glShadeModel(GL_FLAT);
else
glShadeModel(GL_SMOOTH);
// Turn on the primitive connection mode (not connected)
glBegin (GL_QUADS);
int i, npt = sqrt(theElement->m_PointList.size());
aPoint = theElement->m_PointList.begin();
for (aPoint, i=0; aPoint != theElement->m_PointList.end(); aPoint++,i++)
{
int j,k,n;
if (PtInRange(&(theElement->m_PointList[i])))
{
// i, j, k, n � 4 indices of a quad
// Counter Clockwise direction
j = i + npt; // Other vertices indices
k = j+1;
n = i+1;
// Get coordinates of 4 vertices
CPoint3D
iPt = Corrdinate(&(theElement->m_PointList[i])),
jPt = Corrdinate(&(theElement->m_PointList[j])),
kPt = Corrdinate(&(theElement->m_PointList[k])),
nPt = Corrdinate(&(theElement->m_PointList[n]));
float
// Quad side lines vectors coordinates
ax = iPt.x-nPt.x,
ay = iPt.y-nPt.y,
by = jPt.y-iPt.y,
bz = jPt.z-iPt.z,
// Normal vector coordinates
vx = ay*bz,
vy = -bz*ax,
vz = ax*by,
// Normal vector length
v = float(sqrt(vx*vx + vy*vy + vz*vz));
// Scale to unity
vx /= v;
vy /= v;
vz /= v;
// Set the normal vector
glNormal3f (vx,vy,vz);
glColor3f (0.2f, 0.8f, 1.f);
if (PtInAxisBox(&iPt))
glVertex3f (iPt.x, iPt.y, iPt.z);
glColor3f (0.6f, 0.7f, 1.f);
if (PtInAxisBox(&jPt))
glVertex3f (jPt.x, jPt.y, jPt.z);
glColor3f (0.7f, 0.9f, 1.f);
if (PtInAxisBox(&kPt))
glVertex3f (kPt.x, kPt.y, kPt.z);
glColor3f (0.7f, 0.8f, 1.f);
if (PtInAxisBox(&nPt))
glVertex3f (nPt.x, nPt.y, nPt.z);
}
}
glEnd();
}
if(glIsEnabled(GL_LIGHTING))
glDisable(GL_LIGHTING);
}
}
BOOL CGraphCtl::PtInRange(CPoint3D *pt)
{
if (pt->x>=dRangeX[MIN] && pt->x<=dRangeX[MAX] &&
pt->y>=dRangeY[MIN] && pt->y<=dRangeY[MAX] &&
pt->z>=dRangeZ[MIN] && pt->z<=dRangeZ[MAX])
return TRUE;
return FALSE;
}
BOOL CGraphCtl::PtInAxisBox(CPoint3D* pt)
{
float xF=dRangeX[MAX]-dRangeX[MIN];
float yF=dRangeY[MAX]-dRangeY[MIN];
float zF=dRangeZ[MAX]-dRangeZ[MIN];
CPoint3D point;
point.x = (pt->x+dRangeX[MIN])/xF + 0.5f;
point.y = (pt->y+dRangeY[MIN])/yF + 0.5f;
point.z = (pt->z+dRangeZ[MIN])/zF + 0.5f;
return (PtInRange(&point));
}
void CGraphCtl::SetLight(CElement *pElement)
{
//====== Both surface sides are considered when calculating
//====== each pixel color with the lighting formula
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,1);
//====== Light source position depends on the object sizes scaled to (0,100)
float fPos[] =
{
((pElement->m_LightParam[0])-50)*m_fRadius/100,
((pElement->m_LightParam[1])-50)*m_fRadius/100,
((pElement->m_LightParam[2])-50)*m_fRadius/100,
1.f
};
glLightfv(GL_LIGHT0, GL_POSITION, fPos);
//====== Ambient light intensity
float f = (pElement->m_LightParam[3])/100.f;
float fAmbient[4] = { f, f, f, 0.f };
glLightfv(GL_LIGHT0, GL_AMBIENT, fAmbient);
//====== Diffuse light intensity
f = (pElement->m_LightParam[4])/100.f;
float fDiffuse[4] = { f, f, f, 0.f };
glLightfv(GL_LIGHT0, GL_DIFFUSE, fDiffuse);
//====== Specular light intensity
f = (pElement->m_LightParam[5])/100.f;
float fSpecular[4] = { f, f, f, 0.f };
glLightfv(GL_LIGHT0, GL_SPECULAR, fSpecular);
//====== Surface material reflection properties for each light component
f = (pElement->m_LightParam[6])/100.f;
float fAmbMat[4] = { f, f, f, 0.f };
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, fAmbMat);
f = (pElement->m_LightParam[7])/100.f;
float fDifMat[4] = { f, f, f, 1.f };
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, fDifMat);
f = (pElement->m_LightParam[8])/100.f;
float fSpecMat[4] = { f, f, f, 0.f };
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, fSpecMat);
//====== Material shininess
float fShine = 128 * (pElement->m_LightParam[9])/100.f;
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, fShine);
//====== Material light emission property
f = (pElement->m_LightParam[10])/100.f;
float fEmission[4] = { f, f, f, 0.f };
glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, fEmission);
}
CPoint3D CGraphCtl::Corrdinate(CPoint3D *point)
{
float xF=dRangeX[MAX]-dRangeX[MIN];
float yF=dRangeY[MAX]-dRangeY[MIN];
float zF=dRangeZ[MAX]-dRangeZ[MIN];
CPoint3D result;
result.x = (point->x-dRangeX[MIN])/xF - 0.5f;
result.y = (point->y-dRangeY[MIN])/yF - 0.5f;
result.z = (point->z-dRangeZ[MIN])/zF - 0.5f;
return result;
}
STDMETHODIMP CGraphCtl::AddElement()
{
CElement Element ;
m_ElementList.push_back(Element);
SetDirty(TRUE);
return S_OK;
}
STDMETHODIMP CGraphCtl::DeleteElement(short ElementID)
{
if (m_ElementList.empty() || m_ElementList.size() < ElementID - 1)
return Error (_T("Well I never ...!"));
else
m_ElementList.erase (m_ElementList.begin() + ElementID - 1);
return S_OK;
}
STDMETHODIMP CGraphCtl::ClearGraph()
{
if (m_ElementList.empty())
return S_OK;
else
m_ElementList.clear ();
bIsPlotAvailable = FALSE;
return S_OK;
}
STDMETHODIMP CGraphCtl::PlotXYZ(double x, double y, double z, short ElementID)
{
if (m_ElementList.empty())
return Error(_T("You didn't say please first."));
if(bIsPlotAvailable)
{
if(x<dAutoRangeX[MIN]) dAutoRangeX[MIN]=floor(x);
if(y<dAutoRangeY[MIN]) dAutoRangeY[MIN]=floor(y);
if(z<dAutoRangeZ[MIN]) dAutoRangeZ[MIN]=floor(z);
if(x>dAutoRangeX[MAX]) dAutoRangeX[MAX]=ceil(x);
if(y>dAutoRangeY[MAX]) dAutoRangeY[MAX]=ceil(y);
if(z>dAutoRangeZ[MAX]) dAutoRangeZ[MAX]=ceil(z);
} else {
dAutoRangeX[MIN] = floor(x);
dAutoRangeY[MIN] = floor(y);
dAutoRangeZ[MIN] = floor(z);
dAutoRangeX[MAX] = ceil(x);
dAutoRangeY[MAX] = ceil(y);
dAutoRangeZ[MAX] = ceil(z);
bIsPlotAvailable= TRUE ;
}
CPoint3D point(x,y,z);
// Gets the position of the element by index.
m_ElementList[ElementID].m_PointList.push_back(point);
if(m_ElementList[ElementID].min.x > point.x)
m_ElementList[ElementID].min.x=point.x ;
if(m_ElementList[ElementID].min.y > point.y)
m_ElementList[ElementID].min.y=point.y ;
if(m_ElementList[ElementID].min.z > point.z)
m_ElementList[ElementID].min.z=point.z ;
if(m_ElementList[ElementID].max.x < point.x)
m_ElementList[ElementID].max.x=point.x ;
if(m_ElementList[ElementID].max.y < point.y)
m_ElementList[ElementID].max.y=point.y ;
if(m_ElementList[ElementID].max.z < point.z)
m_ElementList[ElementID].max.z=point.z ;
m_ElementList[ElementID].bIsPlotAvailable = TRUE ;
FireViewChange(); // call the InvalidateRect API directly!
return S_OK;
}
STDMETHODIMP CGraphCtl::get_ElementLineColor(short ElementID, OLE_COLOR *pVal)
{
if (m_ElementList.empty() || m_ElementList.size() - 1 < ElementID)
return Error(_T("Yo ho ho and a bottle of rum for that!"));
*pVal = m_ElementList[ElementID].m_LineColor;
return S_OK;
}
STDMETHODIMP CGraphCtl::put_ElementLineColor(short ElementID, OLE_COLOR newVal)
{
if (m_ElementList.empty() || m_ElementList.size() - 1 < ElementID)
return Error(_T("Your mother never allows you that!"));
m_ElementList[ElementID].m_LineColor = newVal;
SetDirty(TRUE);
FireViewChange();
return S_OK;
}
STDMETHODIMP CGraphCtl::get_ElementPointColor(short ElementID, OLE_COLOR *pVal)
{
if (m_ElementList.empty() || m_ElementList.size() - 1 < ElementID)
return Error(_T("Yo ho ho and a bottle of rum for that!"));
*pVal = m_ElementList[ElementID].m_PointColor;
return S_OK;
}
STDMETHODIMP CGraphCtl::put_ElementPointColor(short ElementID, OLE_COLOR newVal)
{
if (m_ElementList.empty() || m_ElementList.size() - 1 < ElementID)
return Error(_T("Your mother never allows you that!"));
m_ElementList[ElementID].m_PointColor = newVal;
SetDirty(TRUE);
FireViewChange();
return S_OK;
}
STDMETHODIMP CGraphCtl::get_ElementLineWidth(short ElementID, float *pVal)
{
if (m_ElementList.empty() || m_ElementList.size() - 1 < ElementID)
return Error(_T("Yo ho ho and a bottle of rum for that!"));
*pVal = m_ElementList[ElementID].m_LineWidth;
return S_OK;
}
STDMETHODIMP CGraphCtl::put_ElementLineWidth(short ElementID, float newVal)
{
if (m_ElementList.empty() || m_ElementList.size() - 1 < ElementID)
return Error(_T("Your mother never allows you that!"));
m_ElementList[ElementID].m_LineWidth = newVal;
SetDirty(TRUE);
FireViewChange();
return S_OK;
}
STDMETHODIMP CGraphCtl::get_ElementPointSize(short ElementID, float *pVal)
{
if (m_ElementList.empty() || m_ElementList.size() - 1 < ElementID)
return Error(_T("Yo ho ho and a bottle of rum for that!"));
*pVal = m_ElementList[ElementID].m_PointSize;
return S_OK;
}
STDMETHODIMP CGraphCtl::put_ElementPointSize(short ElementID, float newVal)
{
if (m_ElementList.empty() || m_ElementList.size() - 1 < ElementID)
return Error(_T("Your mother never allows you that!"));
m_ElementList[ElementID].m_PointSize = newVal;
SetDirty(TRUE);
FireViewChange();
return S_OK;
}
STDMETHODIMP CGraphCtl::get_ElementType(short ElementID, short *pVal)
{
if (m_ElementList.empty() || m_ElementList.size() - 1 < ElementID)
return Error(_T("Yo ho ho and a bottle of rum for that!"));
*pVal = m_ElementList[ElementID].m_nType;
return S_OK;
}
STDMETHODIMP CGraphCtl::put_ElementType(short ElementID, short newVal)
{
if (m_ElementList.empty() || m_ElementList.size() - 1 < ElementID)
return Error(_T("Your mother never allows you that!"));
m_ElementList[ElementID].m_nType = (LineType)newVal;
SetDirty(TRUE);
FireViewChange();
return S_OK;
}
STDMETHODIMP CGraphCtl::get_ElementShow(short ElementID, BOOL *pVal)
{
if (m_ElementList.empty() || m_ElementList.size() - 1 < ElementID)
return Error(_T("Yo ho ho and a bottle of rum for that!"));
*pVal = m_ElementList[ElementID].m_bShow;
return S_OK;
}
STDMETHODIMP CGraphCtl::put_ElementShow(short ElementID, BOOL newVal)
{
if (m_ElementList.empty() || m_ElementList.size() - 1 < ElementID)
return Error(_T("Your mother never allows you that!"));
m_ElementList[ElementID].m_bShow = newVal;
SetDirty(TRUE);
FireViewChange();
return S_OK;
}
STDMETHODIMP CGraphCtl::get_ElementSurfaceFill(short ElementID, BOOL *pVal)
{
if (m_ElementList.empty() || m_ElementList.size() - 1 < ElementID)
return Error(_T("Yo ho ho and a bottle of rum for that!"));
*pVal = m_ElementList[ElementID].m_bFill;
return S_OK;
}
STDMETHODIMP CGraphCtl::put_ElementSurfaceFill(short ElementID, BOOL newVal)
{
if (m_ElementList.empty() || m_ElementList.size() - 1 < ElementID)
return Error(_T("Your mother never allows you that!"));
m_ElementList[ElementID].m_bFill = newVal;
SetDirty(TRUE);
FireViewChange();
return S_OK;
}
STDMETHODIMP CGraphCtl::get_ElementSurfaceFlat(short ElementID, BOOL *pVal)
{
if (m_ElementList.empty() || m_ElementList.size() - 1 < ElementID)
return Error(_T("Yo ho ho and a bottle of rum for that!"));
*pVal = m_ElementList[ElementID].m_bFlat;
return S_OK;
}
STDMETHODIMP CGraphCtl::put_ElementSurfaceFlat(short ElementID, BOOL newVal)
{
if (m_ElementList.empty() || m_ElementList.size() - 1 < ElementID)
return Error(_T("Your mother never allows you that!"));
m_ElementList[ElementID].m_bFlat = newVal;
SetDirty(TRUE);
FireViewChange();
return S_OK;
}
STDMETHODIMP CGraphCtl::get_ElementLight(short ElementID, BOOL *pVal)
{
if (m_ElementList.empty() || m_ElementList.size() - 1 < ElementID)
return Error(_T("Yo ho ho and a bottle of rum for that!"));
*pVal = m_ElementList[ElementID].m_bLights;
return S_OK;
}
STDMETHODIMP CGraphCtl::put_ElementLight(short ElementID, BOOL newVal)
{
if (m_ElementList.empty() || m_ElementList.size() - 1 < ElementID)
return Error(_T("Your mother never allows you that!"));
m_ElementList[ElementID].m_bLights = newVal;
SetDirty(TRUE);
FireViewChange();
return S_OK;
}
STDMETHODIMP CGraphCtl::get_ElementLightingAmbient(short ElementID, short *pVal)
{
if (m_ElementList.empty() || m_ElementList.size() - 1 < ElementID)
return Error(_T("Yo ho ho and a bottle of rum for that!"));
*pVal = m_ElementList[ElementID].m_LightParam[3];
return S_OK;
}
STDMETHODIMP CGraphCtl::put_ElementLightingAmbient(short ElementID, short newVal)
{
if (m_ElementList.empty() || m_ElementList.size() - 1 < ElementID)
return Error(_T("Your mother never allows you that!"));
m_ElementList[ElementID].m_LightParam[3] = newVal;
SetDirty(TRUE);
FireViewChange();
return S_OK;
}
STDMETHODIMP CGraphCtl::get_ElementLightingDiffuse(short ElementID, short *pVal)
{
if (m_ElementList.empty() || m_ElementList.size() - 1 < ElementID)
return Error(_T("Yo ho ho and a bottle of rum for that!"));
*pVal = m_ElementList[ElementID].m_LightParam[4];
return S_OK;
}
STDMETHODIMP CGraphCtl::put_ElementLightingDiffuse(short ElementID, short newVal)
{
if (m_ElementList.empty() || m_ElementList.size() - 1 < ElementID)
return Error(_T("Your mother never allows you that!"));
m_ElementList[ElementID].m_LightParam[4] = newVal;
SetDirty(TRUE);
FireViewChange();
return S_OK;
}
STDMETHODIMP CGraphCtl::get_ElementLightingSpecular(short ElementID, short *pVal)
{
if (m_ElementList.empty() || m_ElementList.size() - 1 < ElementID)
return Error(_T("Yo ho ho and a bottle of rum for that!"));
*pVal = m_ElementList[ElementID].m_LightParam[5];
return S_OK;
}
STDMETHODIMP CGraphCtl::put_ElementLightingSpecular(short ElementID, short newVal)
{
if (m_ElementList.empty() || m_ElementList.size() - 1 < ElementID)
return Error(_T("Your mother never allows you that!"));
m_ElementList[ElementID].m_LightParam[5] = newVal;
SetDirty(TRUE);
FireViewChange();
return S_OK;
}
STDMETHODIMP CGraphCtl::get_ElementMaterialAmbient(short ElementID, short *pVal)
{
if (m_ElementList.empty() || m_ElementList.size() - 1 < ElementID)
return Error(_T("Yo ho ho and a bottle of rum for that!"));
*pVal = m_ElementList[ElementID].m_LightParam[6];
return S_OK;
}
STDMETHODIMP CGraphCtl::put_ElementMaterialAmbient(short ElementID, short newVal)
{
if (m_ElementList.empty() || m_ElementList.size() - 1 < ElementID)
return Error(_T("Your mother never allows you that!"));
m_ElementList[ElementID].m_LightParam[7] = newVal;
SetDirty(TRUE);
FireViewChange();
return S_OK;
}
STDMETHODIMP CGraphCtl::get_ElementMaterialDiffuse(short ElementID, short *pVal)
{
if (m_ElementList.empty() || m_ElementList.size() - 1 < ElementID)
return Error(_T("Yo ho ho and a bottle of rum for that!"));
*pVal = m_ElementList[ElementID].m_LightParam[7];
return S_OK;
}
STDMETHODIMP CGraphCtl::put_ElementMaterialDiffuse(short ElementID, short newVal)
{
if (m_ElementList.empty() || m_ElementList.size() - 1 < ElementID)
return Error(_T("Your mother never allows you that!"));
m_ElementList[ElementID].m_LightParam[7] = newVal;
SetDirty(TRUE);
FireViewChange();
return S_OK;
}
STDMETHODIMP CGraphCtl::get_ElementMaterialSpecular(short ElementID, short *pVal)
{
if (m_ElementList.empty() || m_ElementList.size() - 1 < ElementID)
return Error(_T("Yo ho ho and a bottle of rum for that!"));
*pVal = m_ElementList[ElementID].m_LightParam[8];
return S_OK;
}
STDMETHODIMP CGraphCtl::put_ElementMaterialSpecular(short ElementID, short newVal)
{
if (m_ElementList.empty() || m_ElementList.size() - 1 < ElementID)
return Error(_T("Your mother never allows you that!"));
m_ElementList[ElementID].m_LightParam[8] = newVal;
SetDirty(TRUE);
FireViewChange();
return S_OK;
}
STDMETHODIMP CGraphCtl::get_ElementMaterialShinines(short ElementID, short *pVal)
{
if (m_ElementList.empty() || m_ElementList.size() - 1 < ElementID)
return Error(_T("Yo ho ho and a bottle of rum for that!"));
*pVal = m_ElementList[ElementID].m_LightParam[9];
return S_OK;
}
STDMETHODIMP CGraphCtl::put_ElementMaterialShinines(short ElementID, short newVal)
{
if (m_ElementList.empty() || m_ElementList.size() - 1 < ElementID)
return Error(_T("Your mother never allows you that!"));
m_ElementList[ElementID].m_LightParam[9] = newVal;
SetDirty(TRUE);
FireViewChange();
return S_OK;
}
STDMETHODIMP CGraphCtl::get_ElementMaterialEmission(short ElementID, short *pVal)
{
if (m_ElementList.empty() || m_ElementList.size() - 1 < ElementID)
return Error(_T("Yo ho ho and a bottle of rum for that!"));
*pVal = m_ElementList[ElementID].m_LightParam[10];
return S_OK;
}
STDMETHODIMP CGraphCtl::put_ElementMaterialEmission(short ElementID, short newVal)
{
if (m_ElementList.empty() || m_ElementList.size() - 1 < ElementID)
return Error(_T("Your mother never allows you that!"));
m_ElementList[ElementID].m_LightParam[10] = newVal;
SetDirty(TRUE);
FireViewChange();
return S_OK;
}
STDMETHODIMP CGraphCtl::SetLightCoordinates(short ElementID, float x, float y, float z)
{
if (m_ElementList.empty() || m_ElementList.size() - 1 < ElementID)
return Error(_T("Your mother never allows you that!"));
m_ElementList[ElementID].m_LightParam[0] = x;
m_ElementList[ElementID].m_LightParam[1] = y;
m_ElementList[ElementID].m_LightParam[2] = z;
SetDirty(TRUE);
FireViewChange();
return S_OK;
}
STDMETHODIMP CGraphCtl::get_Lighting(short ElementID, BOOL *pVal)
{
if (m_ElementList.empty() || m_ElementList.size() - 1 < ElementID)
return Error(_T("Yo ho ho and a bottle of rum for that!"));
*pVal = m_ElementList[ElementID].m_bLights;
return S_OK;
}
STDMETHODIMP CGraphCtl::put_Lighting(short ElementID, BOOL newVal)
{
if (m_ElementList.empty() || m_ElementList.size() - 1 < ElementID)
return Error(_T("Your mother never allows you that!"));
m_ElementList[ElementID].m_bLights = newVal;
SetDirty(TRUE);
FireViewChange();
return S_OK;
}