mirror of
https://github.com/TTimo/doom3.gpl.git
synced 2026-03-20 08:59:42 +01:00
hello world
This commit is contained in:
424
neo/tools/comafx/VectorCtl.cpp
Normal file
424
neo/tools/comafx/VectorCtl.cpp
Normal file
@@ -0,0 +1,424 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 GPL Source Code
|
||||
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
|
||||
|
||||
Doom 3 Source Code is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Doom 3 Source Code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
#include "../../idlib/precompiled.h"
|
||||
#pragma hdrstop
|
||||
|
||||
|
||||
#include "VectorCtl.h"
|
||||
#include <math.h>
|
||||
|
||||
BEGIN_MESSAGE_MAP(CVectorCtl, CButton)
|
||||
//{{AFX_MSG_MAP(idGLWidget)
|
||||
ON_WM_LBUTTONDOWN()
|
||||
ON_WM_LBUTTONUP()
|
||||
ON_WM_MOUSEMOVE()
|
||||
//}}AFX_MSG_MAP
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
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_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;
|
||||
}
|
||||
|
||||
rotationQuat.Set( 0.0f, 0.0f, 0.0f, 1.0f );
|
||||
lastPress.Zero();
|
||||
radius = 0.6f;
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
} 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 ( rotationQuat );
|
||||
|
||||
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 ( rotationQuat ); // 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 (LPDRAWITEMSTRUCT lpDrawItemStruct, CDC *pDC)
|
||||
{
|
||||
m_iWidth = lpDrawItemStruct->rcItem.right - lpDrawItemStruct->rcItem.left;
|
||||
m_iHeight = lpDrawItemStruct->rcItem.bottom - lpDrawItemStruct->rcItem.top;
|
||||
m_bmpBuffer.CreateCompatibleBitmap (pDC, m_iWidth, m_iHeight);
|
||||
m_bBmpCreated = TRUE;
|
||||
m_dcMem.CreateCompatibleDC (pDC);
|
||||
m_pOldBitmap = m_dcMem.SelectObject (&m_bmpBuffer);
|
||||
SetRadius (max (min (m_iWidth, m_iHeight) - 2, 0) / 2);
|
||||
SetCenter (m_iWidth / 2, m_iHeight / 2);
|
||||
CreateBackground ();
|
||||
}
|
||||
|
||||
// Set new specular intensity
|
||||
BOOL CVectorCtl::SetSpecularExponent (double dExp)
|
||||
{
|
||||
if (dExp < 1.0 || dExp > 200.0)
|
||||
return FALSE;
|
||||
m_dSpecularExponent = dExp;
|
||||
Redraw ();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Rotate our vector around the X and Y axis
|
||||
void CVectorCtl::RotateByXandY (double XRot, double YRot)
|
||||
{ // Angles are in radians
|
||||
|
||||
if (XRot == 0.0 && YRot == 0.0) {
|
||||
return;
|
||||
}
|
||||
|
||||
double cx = cos(XRot),
|
||||
sx = sin(XRot),
|
||||
cy = cos(YRot),
|
||||
sy = sin(YRot),
|
||||
dx = m_dVec[0] * cy + m_dVec[1] * sx * sy + m_dVec[2] * cx * sy,
|
||||
dy = m_dVec[1] * cx - m_dVec[2] * sx,
|
||||
dz = -m_dVec[0] * sy + m_dVec[1] * sx * cy + m_dVec[2] * cx * cy;
|
||||
|
||||
if (!m_bFrontVector || dz >= 0.0) { // Vector is bounds free
|
||||
m_dVec[0] = dx;
|
||||
m_dVec[1] = dy;
|
||||
m_dVec[2] = dz;
|
||||
} else { // Otherwise, do not allow Z to be negative (light shines from behind)
|
||||
m_dVec[2] = 0.0;
|
||||
m_dVec[0] = dx;
|
||||
m_dVec[1] = dy;
|
||||
Normalize ();
|
||||
}
|
||||
Redraw ();
|
||||
}
|
||||
|
||||
|
||||
void CVectorCtl::UpdateAxisControls ()
|
||||
{
|
||||
CString cs;
|
||||
for (int i=0; i<3; i++)
|
||||
if (pCtl[i]) {
|
||||
cs.Format ("%+1.5f",m_dVec[i]);
|
||||
pCtl[i]->SetWindowText (cs);
|
||||
}
|
||||
}
|
||||
|
||||
void CVectorCtl::SetAxisControl (int nXCtl, int nYCtl, int nZCtl)
|
||||
{
|
||||
pCtl[0] = GetParent()->GetDlgItem(nXCtl);
|
||||
pCtl[1] = GetParent()->GetDlgItem(nYCtl);
|
||||
pCtl[2] = GetParent()->GetDlgItem(nZCtl);
|
||||
}
|
||||
|
||||
void CVectorCtl::SetRadius (UINT uRadius)
|
||||
{
|
||||
m_iRadius = uRadius;
|
||||
m_iSqrRadius = m_iRadius * m_iRadius;
|
||||
CreateBackground ();
|
||||
Redraw (TRUE);
|
||||
}
|
||||
|
||||
|
||||
void CVectorCtl::SetCenter (UINT uHorizPos, UINT uVertPos)
|
||||
{
|
||||
m_iXCenter = uHorizPos;
|
||||
m_iYCenter = uVertPos;
|
||||
CreateBackground ();
|
||||
Redraw (TRUE);
|
||||
}
|
||||
|
||||
|
||||
void CVectorCtl::SetAxis (double d, int nAxis)
|
||||
{
|
||||
if (fabs(d)>=1.0) {
|
||||
m_dVec[nAxis]=d > 1.0 ? 1.0 : -1.0;
|
||||
m_dVec[(nAxis+1) %3]=m_dVec[(nAxis+2) %3]=0.0;
|
||||
Redraw ();
|
||||
return;
|
||||
}
|
||||
m_dVec[nAxis] = d;
|
||||
Normalize ();
|
||||
Redraw ();
|
||||
}
|
||||
|
||||
void CVectorCtl::SetVector (double dx, double dy, double dz)
|
||||
{
|
||||
m_dVec[0] = dx;
|
||||
m_dVec[1] = dy;
|
||||
m_dVec[2] = dz;
|
||||
Normalize ();
|
||||
Redraw ();
|
||||
}
|
||||
|
||||
void CVectorCtl::SetBackgroundColor (COLORREF clrStart, COLORREF clrEnd)
|
||||
{
|
||||
ClearBackgroundBitmap ();
|
||||
m_clrBackgroundStart = clrStart;
|
||||
m_clrBackgroundEnd = clrEnd;
|
||||
CreateBackground ();
|
||||
}
|
||||
|
||||
|
||||
BOOL CVectorCtl::SetBackgroundImage (UINT uBackgroundBitmapID)
|
||||
{
|
||||
if (m_bBackgroundBitmapUsed) {
|
||||
ClearBackgroundBitmap ();
|
||||
CreateBackground ();
|
||||
}
|
||||
if (!m_bmpBack.LoadBitmap (uBackgroundBitmapID))
|
||||
return FALSE;
|
||||
m_bBackgroundBitmapUsed = TRUE;
|
||||
CreateBackground ();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void CVectorCtl::CreateBackground ()
|
||||
{
|
||||
if (!m_bBmpCreated)
|
||||
return; // No image yet
|
||||
if (!m_bBackgroundBitmapUsed) { // No background used - fill with gradient color
|
||||
double r = GetRValue (m_clrBackgroundStart),
|
||||
g = GetGValue (m_clrBackgroundStart),
|
||||
b = GetBValue (m_clrBackgroundStart),
|
||||
rd = double (GetRValue (m_clrBackgroundEnd) - r) / double (m_iHeight),
|
||||
gd = double (GetGValue (m_clrBackgroundEnd) - g) / double (m_iHeight),
|
||||
bd = double (GetBValue (m_clrBackgroundEnd) - b) / double (m_iHeight);
|
||||
for (int j=0; j<m_iHeight; j++) {
|
||||
for (int i=0; i<m_iWidth; i++)
|
||||
m_dcMem.SetPixelV (i,j, RGB (BYTE(r),BYTE(g),BYTE(b)));
|
||||
r+=rd; g+=gd; b+=bd;
|
||||
}
|
||||
Redraw (TRUE);
|
||||
return;
|
||||
}
|
||||
// Bitmap used : tile it in back
|
||||
CDC DCtmp;
|
||||
BITMAP tmpBitmap;
|
||||
|
||||
m_bmpBack.GetBitmap (&tmpBitmap);
|
||||
int iTmpWidth = tmpBitmap.bmWidth,
|
||||
iTmpHeight = tmpBitmap.bmHeight;
|
||||
|
||||
DCtmp.CreateCompatibleDC (&m_dcMem);
|
||||
m_pOldBitmap = DCtmp.SelectObject (&m_bmpBack);
|
||||
|
||||
for (int i=0; i<m_iWidth; i++)
|
||||
for (int j=0; j<m_iHeight; j++)
|
||||
m_dcMem.SetPixelV (i,j, DCtmp.GetPixel (i % iTmpWidth, j % iTmpHeight));
|
||||
DCtmp.SelectObject (m_pOldBitmap);
|
||||
Redraw (TRUE);
|
||||
}
|
||||
|
||||
|
||||
void CVectorCtl::ClearBackgroundBitmap ()
|
||||
{
|
||||
if (!m_bBackgroundBitmapUsed)
|
||||
return;
|
||||
m_bmpBack.DeleteObject ();
|
||||
m_bBackgroundBitmapUsed = FALSE;
|
||||
}
|
||||
|
||||
BOOL CVectorCtl::SetSensitivity (UINT uSens)
|
||||
{
|
||||
if (uSens == 0)
|
||||
return FALSE;
|
||||
m_dSensitivity = double(uSens);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void CVectorCtl::Redraw (BOOL bErase) {
|
||||
m_bImageChange = TRUE;
|
||||
UpdateAxisControls();
|
||||
Invalidate (bErase);
|
||||
}
|
||||
|
||||
void CVectorCtl::OnMouseMove(UINT nFlags, CPoint point) {
|
||||
|
||||
if ( CWnd::GetCapture() != this ) {
|
||||
return;
|
||||
}
|
||||
|
||||
float curX = ( float )( 2 * point.x - 64 ) / 64;
|
||||
float curY = ( float )( 2 * point.y - 64 ) / 64;
|
||||
|
||||
idVec3 to( -curX, -curY, 0.0f );
|
||||
to.ProjectSelfOntoSphere( radius );
|
||||
lastPress.ProjectSelfOntoSphere( radius );
|
||||
|
||||
idVec3 axis;
|
||||
axis.Cross( to, lastPress );
|
||||
float len = ( lastPress - to ).Length() / ( 2.0f * radius );
|
||||
len = idMath::ClampFloat( -1.0f, 1.0f, len );
|
||||
float phi = 2.0f * asin ( len ) ;
|
||||
|
||||
axis.Normalize();
|
||||
axis *= sin( phi / 2.0f );
|
||||
idQuat rot( axis.z, axis.y, axis.x, cos( phi / 2.0f ) );
|
||||
rot.Normalize();
|
||||
|
||||
rotationQuat *= rot;
|
||||
rotationQuat.Normalize();
|
||||
|
||||
lastPress = to;
|
||||
lastPress.z = 0.0f;
|
||||
|
||||
m_dVec = rotationQuat.ToMat3()[2];
|
||||
m_dVec.Normalize();
|
||||
Redraw();
|
||||
}
|
||||
|
||||
void CVectorCtl::OnLButtonDown(UINT nFlags, CPoint point) {
|
||||
float curX = ( float )( 2 * point.x - 64 ) / 64;
|
||||
float curY = ( float )( 2 * point.y - 64 ) / 64;
|
||||
lastPress.Set( -curX, -curY, 0.0f );
|
||||
SetCapture();
|
||||
}
|
||||
|
||||
void CVectorCtl::OnLButtonUp(UINT nFlags, CPoint point) {
|
||||
ReleaseCapture();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user