ch3rendr.cpp

来自「Windows上的MUD客户端程序」· C++ 代码 · 共 2,446 行 · 第 1/5 页

CPP
2,446
字号
			boolContinue = DoCamera(pEntry->GetName(), pEntry->GetCamera());
		}
	}
	return boolContinue;
}

ChCameraIterator* ChCameraIterator::Attach(ChMazeWnd *pWnd)
{
	m_pRC = pWnd->GetRenderContext();
	return this;
};


//////// back to RC methods

bool ChRenderContext::GetCamera(int i, string &strName, QvNode **ppCamera)
{
	bool	boolFound = false;
	if(!m_cameras.IsEmpty())
	{
		ChPosition pos = m_cameras.FindIndex(i);
		if(pos)
		{
			ChCameraEntry *pEntry = m_cameras.Get(pos);
			strName = pEntry->GetName();
			if(ppCamera) *ppCamera = pEntry->GetCamera();
			boolFound = true;
		}
	}
	return boolFound;
}

ChRenderContext *ChRenderContext::NewDefaultCamera()
{
	bool boolCurrentIsDefault = (m_pDefaultCamera == m_pCamera);
	delete m_pDefaultCamera;
	m_pDefaultCamera = new QvPerspectiveCamera;
	// traverse the camera so we get a renderdata set up
	 ChQvBuildState bldIt(((ChMazeWnd*)GetWnd()));
	 m_pDefaultCamera->traverse(&bldIt);

	if(boolCurrentIsDefault) SetCurrentCamera();
	return this;
}

ChRenderContext *ChRenderContext::SetCurrentCamera(QvNode *pCamera)
{
	if(!pCamera) pCamera = m_pDefaultCamera;
	m_pCamera = pCamera;
	#if (defined(CH_USE_RLAB)) || defined(CH_USE_D3D)
	((ChQvPCameraRenderData*)(m_pCamera->GetRenderData()))->Select();
	#endif
	((ChMazeWnd*)GetWnd())->OnCameraChange(ChMazeWnd::cameraSelected);

	return this;
}

ChRenderContext *ChRenderContext::SelectCamera(int iCamIndex)
{
	string strName;
	QvNode *pCamera	= 0;

	if(!GetCamera(iCamIndex, strName, &pCamera))
	{
		pCamera = 0;	
	}
	SetCurrentCamera(pCamera);

	return this;
}

#if	0 && ((defined(CH_USE_RLAB)) || defined(CH_USE_D3D))
ChRenderContext *ChRenderContext::SetCameraLoc(GxVec3f &cameraLoc)
{
	m_cameraLoc = cameraLoc;
	return this;
};
#endif
#if	(defined(CH_USE_RLAB)) || defined(CH_USE_D3D)
GxVec3f ChRenderContext::GetCameraLoc()
{	
	GxVec3f	  cameraLoc;
	QvNode *pCamera = GetCurrentCamera();
	ChQvPCameraRenderData *pData;
	if(pCamera)
	{
		pData = (ChQvPCameraRenderData*)(pCamera->GetRenderData());
		cameraLoc = pData->GetLoc();	
	}

	return cameraLoc;
}
GxVec3f ChRenderContext::GetCameraUp()
{	
	GxVec3f	  cameraUp;
	QvNode *pCamera = GetCurrentCamera();
	ChQvPCameraRenderData *pData;
	if(pCamera)
	{
		pData = (ChQvPCameraRenderData*)(pCamera->GetRenderData());
		cameraUp = pData->GetUp();	
	}

	return cameraUp;
}
GxVec3f ChRenderContext::GetCameraDir()
{	
	GxVec3f	  cameraDir;
	QvNode *pCamera = GetCurrentCamera();
	ChQvPCameraRenderData *pData;
	if(pCamera)
	{
		pData = (ChQvPCameraRenderData*)(pCamera->GetRenderData());
		cameraDir = pData->GetDir();	
	}

	return cameraDir;
}
#endif

int ChRenderContext::GetCameraIndex()
{	
	// Get index of current camera in camera list; -1 if no list
	int 	  index = -1;
	QvNode *pCamera = GetCurrentCamera();
	if(pCamera && !m_cameras.IsEmpty())
	{
		ChPosition pos = m_cameras.GetHeadPosition();
		int i = 0;
		while(pos)
		{
			ChPosition thisPos = pos;
			ChCameraEntry *pEntry = m_cameras.GetNext(pos);
			if(pEntry && pCamera == pEntry->GetCamera())
			{
				index = i;
				break;
			}
			i++;
		}
	}

	return index;
}

GxTransform3Wf ChRenderContext::GetWorldToCameraTransform()
{
	ChQvPCameraRenderData *pData = (ChQvPCameraRenderData*)(GetCurrentCamera()->GetRenderData());
	return pData->GetTransform();	//   use camera matrix
}

GxTransform3Wf ChRenderContext::GetClipToScreenTransform()
{
	// Use the camera port settings - 
	GxTransform3Wf mat;
	float  left, right, top, bottom;
 	ChQvPCameraRenderData *pData = (ChQvPCameraRenderData*)(GetCurrentCamera()->GetRenderData());

	pData->GetPort(left, right, top, bottom);
	// translation
	(*(mat.GetMatrix()))[0][3] = (right - left)	/ 2.;
	//(*(mat.GetMatrix()))[1][3] = (top - bottom) / 2.;
	(*(mat.GetMatrix()))[1][3] = (top - bottom) / 2.;
	(*(mat.GetMatrix()))[2][3] = 0;

	// scaling
	(*(mat.GetMatrix()))[0][0] = (right - left)	/ 2.;		 
	//(*(mat.GetMatrix()))[1][1] = (top - bottom) / 2.;
	(*(mat.GetMatrix()))[1][1] = -(top - bottom) / 2.;
	(*(mat.GetMatrix()))[2][2] = 1.;
	(*(mat.GetMatrix()))[3][3] = 1;

	return (mat);
}

GxTransform3Wf ChRenderContext::GetCameraToClipTransform()
{

 	ChQvPCameraRenderData *pData = (ChQvPCameraRenderData*)(GetCurrentCamera()->GetRenderData());
	GxTransform3Wf camClipTransform = pData->GetClipTransform();
	return (camClipTransform);
}

#if defined(CH_USE_3DR)
ChRenderContext* ChRenderContext::Add(ChQvLightInstance *pLightInst)
{
	m_lights.AddTail(pLightInst);
	return this;
}

ChRenderContext* ChRenderContext::Remove(ChQvLightInstance *pLightInst)
{
	if(m_lights.IsEmpty()) return this;
	ChPosition pos = m_lights.Find(pLightInst);
	if(pos)
	{
		m_lights.Remove(pos);
	}
	delete pLightInst;
	return (this);
}

#else
// These functions aren't used for RealityLab
#endif

ChRenderContext* ChRenderContext::RemoveLights()
{
#if defined(CH_USE_3DR)
	if(m_lights.IsEmpty()) return this;
	ChQvLightInstance *pLightInst;
	while(!m_lights.IsEmpty())
	{
		pLightInst = m_lights.RemoveHead();
		delete pLightInst;
	}
#else
// This function is unnecessary for RealityLab
#endif

	return (this);
}

// 
float ChRenderContext::GetAdjustedLODRange(float range)
{
	#if !((defined(CH_USE_RLAB))  || defined(CH_USE_D3D))
	if(((ChMazeWnd*)m_pWnd)->IsMoving())
	{
		range *= 10;
	}
	#endif
	return range;
}

// Return the angle subtended by one pixel vertically at the center of the screen
float ChRenderContext::GetPixelAngle()
{
	ChQvPCameraRenderData * pCamData = (ChQvPCameraRenderData *)(m_pCamera->GetRenderData());
	float angle;
	if(pCamData->IsPerspective())
	{
		QvPerspectiveCamera * pCamera = (QvPerspectiveCamera *)m_pCamera;
		float left, right, top, bottom;
		pCamData->GetPort( left, right, top, bottom);
		float heightAngle = pCamera->heightAngle.value;

		// abs(bottom - top) == heightAngle
		angle = fabs(heightAngle / (top - bottom));	  // small angle approximation
	}
	else
	{
		angle = 1.;
	} 
	return angle;
}
#if (defined(CH_USE_RLAB)) || defined(CH_USE_D3D)
bool ChRenderContext::IsAnchor( int iX, int iY, pChQvAnchorSensor &pAnchor )
{
	bool boolIsAnchor = false;
	#if 1 || (defined(CH_USE_RLAB))
	pAnchor = 0;
	GxVec3f clickPoint;	   
	ChQvInstance *pAnchorInst = 0;
	bool boolIsRetained = false;

	if(m_viewport)
	{

		// Lock the scene and don't be nice
		LockScene();
		
		#if (defined(CH_USE_RLAB))

		ChNrFrame frame;

		ChNrFrame retainedFrame = 0;	 // closest retained hit, anchor or not
		GxVec3f	retainedPoint;
		ChNrFaceInfo *pFaceInfo;
		int count;
		if(ChNrViewportFindFaces( m_viewport, &count, &pFaceInfo, iX, iY) != RLNotFound && count > 0)
		{
			const float zEpsilon = .01;

			float zLimit = pFaceInfo[0].position.z * (1. + zEpsilon);
			// Hit -something-. Is it an anchor? First remember so we can compare to 
			// immed mode hit if any
			retainedPoint= *(GxVec3f*)&(pFaceInfo[0].position);
			retainedFrame =  pFaceInfo[0].frame;

			// Now check for anchorness
			for(int j = 0; j < count && pFaceInfo[0].position.z <= zLimit && !boolIsAnchor; j++)
			{
				frame = pFaceInfo[j].frame;
				ChQvInstance *pInst = (ChQvInstance *)RLObjectGetAppData(frame);
				while(pInst)
				{
					string strType;
					if(pInst->GetNode()->GetType(strType) == typeQvWWWAnchor)
					{
						boolIsAnchor = true;
						pAnchorInst = pInst;
						clickPoint = *(GxVec3f*)&(pFaceInfo[j].position);

						boolIsRetained = true;
						pInst = 0;
					}
					else
					{
						pInst = pInst->GetParent();
					}
				}
			}
		}
		// Check for immed mode
		{
			ChHittestIterator	iterator(this, iX, iY);
			iterator.Attach(GetRoot());
			iterator.Iterate();

			ChQvInstance *pInst;
			GxVec3f pt;

			if(iterator.GetHit(pInst, pt))
			{
				ChNrFrame	hitFrame = pInst->GetFrame();
				bool boolIsClosest = true;
				if(retainedFrame)
				{
					// Note this bit of code is only executed if 
					// we have both a retained mode object and an immediate
					// mode object under the cursor
					RLIMViewVertex ptInScreen;
		
					#if 0
					RLIMTransformVertices
				    (   GetViewport(), 
				    	retainedFrame,
				        (RLIMPositionVector*)&(retainedPoint),
				        &ptInScreen,
				        sizeof(RLIMPositionVector), 
				        sizeof(RLIMViewVertex),
				        1,
				        1
				    );
					#endif
					float retainedZ = retainedPoint.z();

					RLIMTransformVertices
				    (   GetViewport(), 
				    	hitFrame,
				        (RLIMPositionVector*)&(pt),
				        &ptInScreen,
				        sizeof(RLIMPositionVector), 
				        sizeof(RLIMViewVertex),
				        1,
				        1
				    );
					float immedZ = ptInScreen.sz;

					boolIsClosest = immedZ < retainedZ;
				}
				if(boolIsClosest)
				{

					while(pInst)
					{
						string strType;
						if(pInst->GetNode()->GetType(strType) == typeQvWWWAnchor)
						{
							boolIsAnchor = true;
							pAnchorInst = pInst;
							clickPoint = pt;
							frame = hitFrame;
							pInst = 0;
							boolIsRetained = false;
						}
						else
						{
							pInst = pInst->GetParent();
						}
					}
				}
			}

		}
		// Finish up
		if(pAnchorInst)
		{
			pAnchor = ((ChQvWWWAnchorInstance*)pAnchorInst)->GetSensor();
			
			if(((ChQvWWWAnchorInstance*)pAnchorInst)->IsPointMap())
			{
				if(boolIsRetained)
				{
					RLVector4d screenCoord;
					screenCoord.x = clickPoint.x();
					screenCoord.y = clickPoint.y();
					screenCoord.z = clickPoint.z();
					screenCoord.w = 1;
					RLVector tmp;
					ChNrViewportInverseTransform(m_viewport, &tmp, &screenCoord);
					ChNrFrameInverseTransform(frame, (RLVector*)&clickPoint, &tmp);
				}


				pAnchor->SetHitPoint(clickPoint);
			}
		}
		#else
		//#pragma message("D3D anchor testing not done")
		ChNrFrame frame;

		ChNrFrame retainedFrame = 0;	 // closest retained hit, anchor or not
		GxVec3f	retainedPoint;
		//ChNrFaceInfo *pFaceInfo;

	    LPDIRECT3DRMVISUAL visual;
	    LPDIRECT3DRMFRAME pickFrame;
	    LPDIRECT3DRMPICKEDARRAY picked = 0;
	    LPDIRECT3DRMFRAMEARRAY frames;
	    LPDIRECT3DRMMESHBUILDER mesh;
	    LPDIRECT3DRMTEXTURE decal;
		D3DRMPICKDESC 	pickInfo;

		HRESULT rval = m_viewport->Pick(iX, iY, &picked);
		int count = picked ? picked->GetSize() : 0;
		float z = 0;
		if(count > 0)
		{
            picked->GetPick(0, &visual, &frames, &pickInfo);
            frames->GetElement(frames->GetSize() - 1, &pickFrame);

            if (SUCCEEDED(visual->QueryInterface(IID_IDirect3DRMMeshBuilder, (void **) &mesh)))
            {   
                mesh->Release();
				z = pickInfo.vPosition.z;
            }
            else if (SUCCEEDED(visual->QueryInterface(IID_IDirect3DRMTexture, (void **) &decal)))
            {   
                decal->Release();
				z = pickInfo.vPosition.z;
            }

            pickFrame->Release();
            frames->Release();
            visual->Release();

			const float zEpsilon = .01;

			float zLimit = z * (1. + zEpsilon);
			// Hit -something-. Is it an anchor? First remember so we can compare to 
			// immed mode hit if any
			retainedPoint= *(GxVec3f*)&(pickInfo.vPosition);
			retainedFrame =  pickFrame;

			// Now check for anchorness
			
			for(int j = 0; j < count && !boolIsAnchor; j++)
			{
				bool boolCheckit = false;
			    picked->GetPick(j, &visual, &frames, &pickInfo);
	            frames->GetElement(frames->GetSize() - 1, &pickFrame);

	            if (SUCCEEDED(visual->QueryInterface(IID_IDirect3DRMMeshBuilder, (void **) &mesh)))
	            {   
	                mesh->Release();
					z = pickInfo.vPosition.z;
					boolCheckit = true;
	            }
	            else if (SUCCEEDED(visual->QueryInterface(IID_IDirect3DRMTexture, (void **) &decal)))
	            {   
	                decal->Release();
					z = pickInfo.vPosition.z;
					boolCheckit = true;
	            }

	            pickFrame->Release();
	            frames->Release();
	            visual->Release();

				if(z > zLimit) break;

				if(boolCheckit)
				{
	

⌨️ 快捷键说明

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