⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chmazcam.cpp

📁 Windows上的MUD客户端程序
💻 CPP
📖 第 1 页 / 共 2 页
字号:
}


void ChMazeCameraControl::MoveRight( float fUnits, bool boolDraw )
{
	QvPerspectiveCamera*	pNode;

	if (pNode = GetCameraNode())
	{
		float	fX = fUnits;
		float	fY = 0;
		float	fZ = 0;

		ComputeRelativeCameraShift( fX, fY, fZ );

		if(m_pMazeWnd->GetRenderContext()->GetViewerMode() == walk)
		{
			fY = 0;
		}
		else
		{
			// Because of 3dr bug, our axis is -never- exactly vertical
			// If it's -almost- vertical, then zero the y delta
			// Additionally, we have round-off error.
			if( (fY*fY) / (fX * fX + fZ * fZ) <= 1e-3)
			{
				fY = 0.;
			}
		}

		Shift(fX, fY, fZ, boolDraw);
	}
}



void ChMazeCameraControl::MoveUp( float fUnits, bool boolDraw )
{
	QvPerspectiveCamera*	pNode;
	// This is -relative-
	if (pNode = GetCameraNode())
	{
		float	fX = 0;
		float	fY = fUnits;
		float	fZ = 0;

		ComputeRelativeCameraShift( fX, fY, fZ );

		Shift(fX, fY, fZ, boolDraw);
	}
}


void ChMazeCameraControl::MoveDown( float fUnits, bool boolDraw )
{
	QvPerspectiveCamera*	pNode;

	// This is always relative
	if (pNode = GetCameraNode())
	{
		float	fX = 0;
		float	fY = -fUnits;
		float	fZ = 0;

		ComputeRelativeCameraShift( fX, fY, fZ );

		Shift(fX, fY, fZ, boolDraw);

	}
}


void ChMazeCameraControl::Yaw( float fDegrees, bool boolDraw )
{
											// Positive degrees is left
	QvPerspectiveCamera*	pNode;

	if (pNode = GetCameraNode())
	{
		float	fDeltaRadians;

		fDeltaRadians = (fDegrees / 180.0) * PI;

		ChQvPCameraRenderData *pRenderData = (ChQvPCameraRenderData *)(GetCameraNode()->GetRenderData());

		GxVec3f		dir  = pRenderData->GetDir();
		GxVec3f		up  = pRenderData->GetUp();
		GxVec3f	axis = up;
		GxTransform3Wf mat(axis, fDeltaRadians);

		dir = mat * dir;
		up = mat * up;

		pRenderData->SetDir(dir);
		pRenderData->SetUp(up);
		pRenderData->SynchCamera();

		if (boolDraw)
		{
			InvalidateCamera( pNode );
		}
	}
}

void ChMazeCameraControl::Turn( float fDegrees, bool boolDraw )
{
											// Positive degrees is left
	QvPerspectiveCamera*	pNode;

	if (pNode = GetCameraNode())
	{
		float	fDeltaRadians;

		fDeltaRadians = (fDegrees / 180.0) * PI;

		ChQvPCameraRenderData *pRenderData = (ChQvPCameraRenderData *)(GetCameraNode()->GetRenderData());

		GxVec3f		dir  = pRenderData->GetDir();
		GxVec3f		up  = pRenderData->GetUp();
		GxVec3f	axis(0., 1., 0);
		GxTransform3Wf mat(axis, fDeltaRadians);

		dir = mat * dir;
		up = mat * up;

		#if 0
		// Now straighten your head if walking
		if(m_pMazeWnd->GetRenderContext()->GetViewerMode() == walk)
		{
			HeadsUp(dir, up);
		}
		#endif

		pRenderData->SetDir(dir);
		pRenderData->SetUp(up);
		pRenderData->SynchCamera();

		if (boolDraw)
		{
			InvalidateCamera( pNode );
		}
	}
}


void ChMazeCameraControl::Pitch( float fDegrees, bool boolDraw )
{
											// Positive degrees is up
	QvPerspectiveCamera*	pNode;

	if (pNode = GetCameraNode())
	{
		float	fDeltaRadians;

		fDeltaRadians = (fDegrees / 180.0) * PI;

		ChQvPCameraRenderData *pRenderData = (ChQvPCameraRenderData *)(GetCameraNode()->GetRenderData());

		GxVec3f		dir  = pRenderData->GetDir();
		GxVec3f		up  = pRenderData->GetUp();
		GxVec3f		axis = dir.cross(up);

		GxTransform3Wf mat(axis, fDeltaRadians);

		dir = mat * dir;
		up = mat * up;


		pRenderData->SetDir(dir);
		pRenderData->SetUp(up);
		pRenderData->SynchCamera();

		if (boolDraw)
		{
			InvalidateCamera( pNode );
		}
	}
}


void ChMazeCameraControl::Roll( float fDegrees, bool boolDraw )
{
											/* Positive degrees is counter-
												clockwise */
	// Does nothing if walking
	if(m_pMazeWnd->GetRenderContext()->GetViewerMode() == walk)
	{
		return;
	}

	QvPerspectiveCamera*	pNode;

	if (pNode = GetCameraNode())
	{
		float	fDeltaRadians;

		fDeltaRadians = (fDegrees / 180.0) * PI;

		ChQvPCameraRenderData *pRenderData = (ChQvPCameraRenderData *)(GetCameraNode()->GetRenderData());

		GxVec3f		dir  = pRenderData->GetDir();
		GxVec3f		up  = pRenderData->GetUp();
		GxVec3f		axis = dir;

		GxTransform3Wf mat(axis, fDeltaRadians);

		dir = mat * dir;
		up = mat * up;


		pRenderData->SetDir(dir);
		pRenderData->SetUp(up);
		pRenderData->SynchCamera();

		if (boolDraw)
		{
			InvalidateCamera( pNode );
		}
	}
}

void ChMazeCameraControl::LookAt( GxVec3f &target, bool boolDraw )
{
	QvPerspectiveCamera*	pNode;

	if (pNode = GetCameraNode())
	{

		ChQvPCameraRenderData *pRenderData = (ChQvPCameraRenderData *)(GetCameraNode()->GetRenderData());

		GxVec3f	dir  = target;
		GxVec3f	loc  = pRenderData->GetLoc();

		dir -= loc;

		dir .normalize;

		pRenderData->SetDir(dir);
		pRenderData->SynchCamera();

		if (boolDraw)
		{
			InvalidateCamera( pNode );
		}
	}
}

void ChMazeCameraControl::SetLookDir( GxVec3f &lookDir, bool boolDraw )
{
	QvPerspectiveCamera*	pNode;

	if (pNode = GetCameraNode())
	{

		ChQvPCameraRenderData *pRenderData = (ChQvPCameraRenderData *)(GetCameraNode()->GetRenderData());

		GxVec3f	dir  = lookDir;

		dir .normalize;

		pRenderData->SetDir(dir);
		pRenderData->SynchCamera();

		if (boolDraw)
		{
			InvalidateCamera( pNode );
		}
	}
}

void ChMazeCameraControl::RotateBallHorz(float fDegrees, bool boolDraw /*= true */)
{  
	GxVec3f axis (0., 1., 0);

	RotateBall( axis, PI * fDegrees / 180., boolDraw);
}

void ChMazeCameraControl::RotateBallVert(float fDegrees, bool boolDraw /*= true */)
{  
	GxVec3f axis (1., 0., 0);

	RotateBall( axis, PI * fDegrees / 180., boolDraw);
}

void ChMazeCameraControl::RotateBall(const ChPoint &ptLastMouse, const ChPoint &ptMouse, int iDiameter, bool boolDraw)
{
	// Rotate the camera location as if on the surface of a trackball
	// the 'finger' on the ball has moved from ptLastMouse to ptMouse.
	// the 'diameter' of the ball determines how sensitive it is
	// for now, we'll just use the relative offset from one pt to the other
	if(ptMouse.x == ptLastMouse.x && ptMouse.y == ptLastMouse.y) return; // No move!
	
	GxVec3f	delta(ptMouse.x - ptLastMouse.x, ptMouse.y - ptLastMouse.y, 0.);
	delta.x() /= iDiameter; 
	delta.y() /= -iDiameter; 				// flip coords in y
	float angle = -PI * delta.magnitude();

	GxVec3f	axis, zaxis(0., 0., 1.);
	axis = zaxis.cross(delta);
	RotateBall(axis, angle, boolDraw);
}


/*----------------------------------------------------------------------------
	ChMazeCameraControl protected methods
----------------------------------------------------------------------------*/

void ChMazeCameraControl::RotateBall(GxVec3f axis, float fRadians, bool boolDraw /*= true */)
{
	QvPerspectiveCamera* pNode = GetCameraNode();
	if(!pNode) return;	// nothing to rotate!

	ComputeRelativeCameraShift(axis.x(), axis.y(), axis.z());
	axis.normalize();

	// Get the bounding cube center, and use this as the center of rotation
	GxVec3f				lower, upper;
	GetMazeWnd()->GetBounds()->GetWorldBounds(lower, upper);
	GxVec3f				center = upper;
	center += lower;   center *= .5;	 // avg

	ChQvPCameraRenderData *pRenderData = (ChQvPCameraRenderData *)(GetCameraNode()->GetRenderData());
	GxVec3f		dir  = pRenderData->GetDir();
	GxVec3f		up  = pRenderData->GetUp();
	GxVec3f	loc  = pRenderData->GetLoc();

	GxTransform3Wf mat;
	#if defined(CH_USE_3DR)
	mat.Translate(center);
 	GxTransform3Wf rotMat(axis, fRadians);

	mat = rotMat.Compose(mat);
	mat.Translate(GxVec3f(-center.x(), -center.y(), -center.z()));
	loc = mat * loc;
	#elif (defined(CH_USE_RLAB) || defined(CH_USE_D3D))
 	GxTransform3Wf rotMat(axis, fRadians);	 // ??????????????????
	
	loc -= center;
	loc = rotMat * loc;
	loc += center;

	#else
	#pragma message("camera motion not defined")
	#endif

	GxVec3f toMove = loc;
	toMove -= pRenderData->GetLoc();	// This is so we can use Shift,
										// which does collision testing for us


	dir = rotMat * dir;
	up = rotMat * up;

	//pRenderData->SetLoc(loc);
	if(Shift(toMove.x(), toMove.y(), toMove.z(), false, true, false))
	{
					// Don't do rotates if the shift collided 
		pRenderData->SetDir(dir);
		pRenderData->SetUp(up);
		pRenderData->SynchCamera();
	}

	if (boolDraw)
	{
		InvalidateCamera( GetCameraNode() );
	}

}

QvPerspectiveCamera* ChMazeCameraControl::GetCameraNode()
{
	return  (QvPerspectiveCamera*)(m_pMazeWnd->GetRenderContext()->GetCurrentCamera());
}


void ChMazeCameraControl::InvalidateCamera( QvPerspectiveCamera* pCameraNode )
{
	GetMazeWnd()->GetRenderContext()->SetDirty();
	pCameraNode->Invalidate( GetMazeWnd()->GetRenderContext() );
}


void ChMazeCameraControl::
ComputeRelativeCameraShift( float &fX, float &fY, float &fZ )
{
	/* This method transforms from camera to world-like space for use in
		camera motion relative to camera orientation.  No translations, just
		adjusts x,y,z from the camera node's orientation to world. */

	GxVec3f		tmp;
	#if 0 && OLD_NAVIGATION
	if(m_pMazeWnd->GetRenderContext()->GetViewerMode() == walk)
	{
		ChQvPCameraRenderData *pRenderData = (ChQvPCameraRenderData *)(GetCameraNode()->GetRenderData());
		GxVec3f		dir  = pRenderData->GetDir();
		GxVec3f		up  = pRenderData->GetUp();

		GxVec3f 	n = dir.cross(up);
		 
		tmp.x() = fZ * dir.x() + fX * n.x();
		tmp.y() = fY;
		tmp.z() = fZ * dir.z() + fX * n.z();
	}
	else
	#endif

	{
		ChQvPCameraRenderData *pRenderData = (ChQvPCameraRenderData *)(GetCameraNode()->GetRenderData());
		GxVec3f		dir  = pRenderData->GetDir();
		GxVec3f		up  = pRenderData->GetUp();

		GxVec3f 	n = dir.cross(up);
		 
		tmp.x() = fZ * dir.x() + fY * up.x() + fX * n.x();
		tmp.y() = fZ * dir.y() + fY * up.y() + fX * n.y();
		tmp.z() = fZ * dir.z() + fY * up.z() + fX * n.z();
	}

	fX = tmp.x();
	fY = tmp.y();
	fZ = tmp.z();
}

void ChMazeCameraControl::
ComputeRelativeCameraShift( GxVec3f &vec, const GxVec3f &dir, const GxVec3f &up )
{
	/* This method transforms from camera to world-like space for use in
		camera motion relative to camera orientation.  No translations, just
		adjusts x,y,z from the camera node's orientation to world. */

	GxVec3f		tmp;
	GxVec3f 	n = dir.cross(up);
	 
	tmp.x() = vec.z() * dir.x() + vec.y() * up.x() + vec.x() * n.x();
	tmp.y() = vec.z() * dir.y() + vec.y() * up.y() + vec.x() * n.y();
	tmp.z() = vec.z() * dir.z() + vec.y() * up.z() + vec.x() * n.z();

	vec = tmp;
}

const float EPS = 1.e-12;	// nigh unto zero

void ChMazeCameraControl::HeadsUp(GxVec3f &dir, GxVec3f &up, bool boolAllowInverted)
{
	GxVec3f yAxis(0., 1., 0.);
	float prod = up.dot(yAxis);

	if(fabs(prod) < EPS) return;	// horizontal, let it be

	GxVec3f n = yAxis.cross(dir);				// normal to plane defined by (dir, yaxis)

	if (n.dot(n) > EPS)
	{
		up = dir.cross(n);
	}
	else
	{
		// special case; looking straight up or down
		// we should have trapped this if dir and up were really perps, buy
		// maybe they weren't
		return;
	} 

	if (up.dot(up) < EPS)
	{
		up.set( 0, 1, 0);
	}
	up.normalize();
	if(boolAllowInverted && prod < 0)
	{
			  // use up-down sense of original
		up.x() = -up.x();
		up.y() = -up.y();
		up.z() = -up.z();
	}
}

void ChMazeCameraControl::HeadsUp(bool boolDraw)
{
	QvPerspectiveCamera*	pNode;

	if (pNode = GetCameraNode())
	{
		ChQvPCameraRenderData *pRenderData = (ChQvPCameraRenderData *)(GetCameraNode()->GetRenderData());

		GxVec3f		dir  = pRenderData->GetDir();
		GxVec3f		up  = pRenderData->GetUp();
		
		// Now straighten your head 
		HeadsUp(dir, up);

		pRenderData->SetDir(dir);
		pRenderData->SetUp(up);
		pRenderData->SynchCamera();

		if (boolDraw)
		{
			InvalidateCamera( pNode );
		}
	}
}

// end of file

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -