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 + -
显示快捷键?