【VC开源代码栏目提醒】:网学会员--在 VC开源代码编辑为广大网友搜集整理了:VECTORCTL.CPP绩等信息,祝愿广大网友取得需要的信息,参考学习。
#include "stdafx.h"
#include "VectorCtl.h"
#include <math.h>
CVectorCtl::CVectorCtl () :
m_bBmpCreated (FALSE),
m_bImageChange (TRUE),
m_bBackgroundBitmapUsed (FALSE),
m_clrDiffuse (DEFAULT_DIFFUSE),
m_clrAmbient (DEFAULT_AMBIENT),
m_clrLight (DEFAULT_LIGHT),
m_clrBackgroundStart (DEFAULT_START_BACKGROUND_COLOR),
m_clrBackgroundEnd (DEFAULT_END_BACKGROUND_COLOR),
m_dSpecularExponent (DEFAULT_SPEC_EXP),
m_bHasFocus (FALSE),
m_bSelected (FALSE),
m_bFrontVector (FALSE),
m_iLastMouseY (VAL_NOT_IN_USE),
m_iLastMouseX (VAL_NOT_IN_USE),
m_dSensitivity (20.0),
m_procVectorChanging (NULL),
m_procVectorChanged (NULL)
{
double DefaultVec[3] = DEFAULT_VEC;
for (int i=0; i<3; i++) {
m_dVec[i] = DefaultVec[i];
pCtl[i] = NULL;
}
}
CVectorCtl::~CVectorCtl ()
{
if (m_bBmpCreated)
m_dcMem.SelectObject (m_pOldBitmap);
ClearBackgroundBitmap ();
}
// Owner-drawn control service function:
void CVectorCtl::DrawItem( LPDRAWITEMSTRUCT lpDrawItemStruct )
{
CDC *pDC = CDC::FromHandle (lpDrawItemStruct->hDC); // Get CDC to draw
if (!m_bSelected && lpDrawItemStruct->itemState & ODS_SELECTED) {
// Just got re-selected (user starts a new mouse dragging session)
m_iLastMouseX = VAL_NOT_IN_USE;
m_iLastMouseY = VAL_NOT_IN_USE;
} else if (m_bSelected && // Last state was selected
!(lpDrawItemStruct->itemState & ODS_SELECTED) && // New state is NOT selected
(lpDrawItemStruct->itemState & ODS_FOCUS) && // New state is still in focus
m_procVectorChanged) // User asked for a callback
// User has left the track-ball and asked for a callback.
m_procVectorChanged (m_dVec[0], m_dVec[1], m_dVec[2]); // Call it!
m_bHasFocus = lpDrawItemStruct->itemState & ODS_FOCUS; // Update focus status
m_bSelected = lpDrawItemStruct->itemState & ODS_SELECTED; // Update selection status
if (!m_bBmpCreated) // 1st time
InitBitmap (lpDrawItemStruct, pDC);
if (m_bImageChange) { // Image has changes - recalc it!
if (m_procVectorChanging) // User has specified a callback
m_procVectorChanging (m_dVec[0], m_dVec[1], m_dVec[2]); // Call it!
BuildImage (lpDrawItemStruct);
m_bImageChange = FALSE;
}
pDC->BitBlt (0,0,m_iWidth, m_iHeight, &m_dcMem, 0, 0, SRCCOPY); // Update screen
}
// Mouse was dragged
void CVectorCtl::OnMouseDrag (int ixMove, int iyMove)
{
RotateByXandY (double(-iyMove) / m_dSensitivity,
double(ixMove) / m_dSensitivity);
}
// Recalc ball image
void CVectorCtl::BuildImage (LPDRAWITEMSTRUCT lpDrawItemStruct)
{
int xf, yf;
for (int x=0; x<m_iWidth; x++) // Scan all columns
for (int y=0; y<m_iHeight; y++) { // Scan all rows
xf = x-m_iXCenter; // Find distance from center
yf = y-m_iYCenter;
if (xf*xf + yf*yf <= m_iSqrRadius) { // Point on ball surface
double vx = double(xf) / double(m_iRadius),
vy = double(yf) / double(m_iRadius),
vz = sqrt (1.0 - vx*vx - vy*vy); // Find ball's normal
m_dcMem.SetPixelV (x,y, CalcLight (vx,vy,vz));
}
}
}
// Normalize a vector to unit size
BOOL CVectorCtl::Normalize ()
{
double Norm = m_dVec[0] * m_dVec[0] + m_dVec[1] * m_dVec[1] + m_dVec[2] * m_dVec[2];
if (Norm > EPS) {
Norm = sqrt (Norm);
m_dVec[0] /= Norm;
m_dVec[1] /= Norm;
m_dVec[2] /= Norm;
return TRUE;
} else { // Reset to defualt vector
double DefaultVec[3] = DEFAULT_VEC;
for (int i=0; i<3; i++)
m_dVec[i] = DefaultVec[i];
return FALSE;
}
}
// Calculate lightning effect for specific pixel on ball's surface
COLORREF CVectorCtl::CalcLight (double dx, double dy, double dz)
{
double NL = dx * m_dVec[0] + dy * m_dVec[1] + dz * m_dVec[2],
RV = 2.0 * NL,
rx = m_dVec[0] - (dx * RV),
ry = m_dVec[1] - (dy * RV),
rz = m_dVec[2] - (dz * RV);
if (NL < 0.0) // Diffuse coefficient
NL = 0.0;
RV = max (0.0, -rz);
RV = double(pow (RV, m_dSpecularExponent));
int r = int ( double(GetRValue(m_clrDiffuse)) * NL + // Diffuse
double(GetRValue(m_clrLight)) * RV + // Specular
double(GetRValue(m_clrAmbient))), // Ambient
g = int ( double(GetGValue(m_clrDiffuse)) * NL + // Diffuse
double(GetGValue(m_clrLight)) * RV + // Specular
double(GetGValue(m_clrAmbient))), // Ambient
b = int ( double(GetBValue(m_clrDiffuse)) * NL + // Diffuse
double(GetBValue(m_clrLight)) * RV + // Specular
double(GetBValue(m_clrAmbient))); // Ambient
r = min (255, r); // Cutoff highlight
g = min (255, g);
b = min (255, b);
return RGB(BYTE(r),BYTE(g),BYTE(b));
}
// Start memory buffer bitmap and measure it
void CVectorCtl::InitBitmap (LPDRAWITEM