📄 ch3rendr.cpp
字号:
/*
* create an egg frame within the scene
*/
egg = CreateFrame(m_sceneFrame);
/*
* add the loaded mesh into the frame
*/
if(egg)
{
rval = egg->AddVisual(egg_mesh);
egg->Release();
}
egg_mesh->Release();
}
}
#endif
}
#endif
}
#endif
SetTexture(0);
m_ppDefaults = new QvNode* [QvState::NumStacks];
for(int j=0; j< QvState::NumStacks; j++) m_ppDefaults[j] = 0;
// We don't set defaults for cameras, and lights
m_ppDefaults[QvState::BaseColorIndex ] = new QvBaseColor;
m_ppDefaults[QvState::Coordinate3Index ] = new QvCoordinate3;
m_ppDefaults[QvState::FontStyleIndex ] = new QvFontStyle;
m_ppDefaults[QvState::InfoIndex ] = new QvInfo;
m_ppDefaults[QvState::MaterialBindingIndex ] = new QvMaterialBinding;
m_ppDefaults[QvState::MaterialIndex ] = new QvMaterial;
m_ppDefaults[QvState::NormalBindingIndex ] = new QvNormalBinding;
m_ppDefaults[QvState::NormalIndex ] = new QvNormal;
m_ppDefaults[QvState::ShapeHintsIndex ] = new QvShapeHints;
m_ppDefaults[QvState::Texture2Index ] = new QvTexture2;
m_ppDefaults[QvState::Texture2TransformationIndex ] = new QvTexture2Transform;
m_ppDefaults[QvState::TextureCoordinate2Index ] = new QvTextureCoordinate2;
// transforms are different, but we need one identity instance handy
m_ppDefaults[QvState::TransformationIndex ] = new QvScale;
ChQvBuildState state((ChMazeWnd*)GetWnd());
// traverse once to init; this guarantees renderdata is newed
m_ppDefaults[QvState::BaseColorIndex ]->traverse(&state);
m_ppDefaults[QvState::Coordinate3Index ]->traverse(&state);
m_ppDefaults[QvState::FontStyleIndex ]->traverse(&state);
m_ppDefaults[QvState::InfoIndex ]->traverse(&state);
m_ppDefaults[QvState::MaterialBindingIndex ]->traverse(&state);
m_ppDefaults[QvState::MaterialIndex ]->traverse(&state);
m_ppDefaults[QvState::NormalBindingIndex ]->traverse(&state);
m_ppDefaults[QvState::NormalIndex ]->traverse(&state);
m_ppDefaults[QvState::ShapeHintsIndex ]->traverse(&state);
m_ppDefaults[QvState::Texture2Index ]->traverse(&state);
m_ppDefaults[QvState::Texture2TransformationIndex ]->traverse(&state);
m_ppDefaults[QvState::TextureCoordinate2Index ]->traverse(&state);
m_ppDefaults[QvState::TransformationIndex ]->traverse(&state);
}
void ChRenderContext::AbortConstruction()
{
// Stop all construction threads currently
// running for this instance
#if (defined(CH_USE_RLAB)) || defined(CH_USE_D3D)
if ( IsThreaded() )
{
// cancel all threads, currently running
m_boolContinueConstruction = false;
// Tell the reconstruction thread to abort all requests and clean up the queue
// Abort all reconstruction requests
::ResetEvent( GetEndConstructEvent() );
::SetEvent( m_hReconstructEvents[abortReconstruct] );
DWORD dwStatus;
// Wait till reconstruction thread says we are OK to proceed
dwStatus = ::WaitForSingleObject( GetEndConstructEvent(), INFINITE );
ASSERT( dwStatus == WAIT_OBJECT_0 );
TRACE1( "AbortConstruction : Threads running before abort : %d\n", NumPendingConstructionThreads() );
while( NumPendingConstructionThreads() )
{ // There is a thread curently running, block on the end thread event
dwStatus = ::WaitForSingleObject( GetEndConstructEvent(), INFINITE );
ASSERT( dwStatus == WAIT_OBJECT_0 );
}
// We can start construction of scenes again
m_boolContinueConstruction = true;
TRACE1( "AbortConstruction : Threads running after abort : %d\n", NumPendingConstructionThreads() );
ASSERT( NumPendingConstructionThreads() == 0 );
}
#endif
}
void ChRenderContext::Term()
{
#if defined(CH_USE_3DR)
if(m_hGC) G3dDeleteGC(m_hGC);
if(m_hRC) R3dDeleteRC(m_hRC);
m_hGC = 0;
m_hRC = 0;
#else
// Terminate the reconstruction thread
if ( IsThreaded() )
{
// Abort all reconstruction requests
::SetEvent( m_hReconstructEvents[endThread] );
DWORD dwStatus;
// Wait till reconstruction thread says we are OK to proceed
dwStatus = ::WaitForSingleObject( GetEndConstructEvent(), INFINITE );
ASSERT( dwStatus == WAIT_OBJECT_0 );
}
delete m_pDefaultCamera;
ChNrObjectDestroy(m_hRC);
ChNrObjectDestroy(m_sceneFrame);
m_hRC = 0;
m_sceneFrame = 0;
m_cameraFrame = 0;
m_viewport = 0;
#endif
// Moved from destructor to Term by VSP : This was required to
// Plug leaks in QV.
if(m_ppDefaults)
{
for(int j=0; j< QvState::NumStacks; j++)
{
delete m_ppDefaults[j];
m_ppDefaults[j] = 0;
}
}
delete m_ppDefaults;
m_ppDefaults = 0;
if(m_pRootInstance) m_pRootInstance->Release();
//delete m_pRootInstance;
m_pRootInstance = 0;
for(int j=0; j<CH_MAX_SPHERE_LEVEL+1; j++)
{
delete m_pSpheres[j];
m_pSpheres[j] = 0;
}
#if defined(CH_USE_3DR)
#else
delete m_pStack;
m_pStack = 0;
#endif
}
#if (defined(CH_USE_RLAB) || defined(CH_USE_D3D))
void ChRenderContext::Resize( int width, int height, bool boolForceNew )
{
if(m_hRC)
{
LockScene();
if(width == 0 || width == 0)
{
RECT r;
GetWnd()->GetClientRect(&r);
if(!width) width = r.right;
if(!height) height = r.bottom;
}
int dev_width = ChNrDeviceGetWidth(m_hRC);
int dev_height = ChNrDeviceGetHeight(m_hRC);
ChNrValue front = ChNrViewportGetFront(m_viewport);
ChNrValue back = ChNrViewportGetBack(m_viewport);
ChNrValue field = ChNrViewportGetField(m_viewport);
ChNrObjectDestroy(m_viewport);
/*
* if requesting a device of zero dimensions, actually make the device
* slightly larger, as a device of width or height zero is no device at
* all, and it causes many problems
*/
if (!width) {
width = 10;
}
if (!height) {
height = 10;
}
if (boolForceNew || (width > dev_width || height > dev_height))
{
int old_dither = ChNrDeviceGetDither(m_hRC);
ChNrRenderQuality old_quality = ChNrDeviceGetQuality(m_hRC);
ChNrColorModel old_model = ChNrDeviceGetColorModel(m_hRC);
int old_shades = ChNrDeviceGetShades(m_hRC);
#if 0
// We don't use any right now
RLDestroyCallback* fns;
void** args;
int c, count;
RLObjectGetDestroyCallbacks(m_hRC, &count, &fns, &args);
for (c = 0; c < count; c++) {
RLObjectRemoveDestroyCallback(m_hRC, fns[c], args[c]);
}
#endif
ChNrObjectDestroy(m_hRC);
m_hRC = CreateDevice(width, height);
#if 0
for (c = 0; c < count; c++) {
ChNrObjectAddDestroyCallback(m_hRC, fns[c], args[c]);
}
RLFree(fns);
RLFree(args);
#endif
ChNrDeviceSetDither(m_hRC, old_dither);
ChNrDeviceSetQuality(m_hRC, old_quality);
#if (defined(CH_USE_RLAB))
// Just for RL, implicit in device in d3d
ChNrDeviceSetColorModel(m_hRC, old_model);
#endif
ChNrDeviceSetShades(m_hRC, old_shades);
}
m_viewport = CreateViewport(m_hRC, m_cameraFrame, 0, 0, width, height);
ChNrObjectAddDestroyCallback(m_viewport, ViewportDestroyCallback, this);
//TRACE("Viewport Created\n");
ChNrViewportSetBack(m_viewport, back);
ChNrViewportSetFront(m_viewport, front);
ChNrViewportSetField(m_viewport, field);
if(m_pBackGroundNode)
{
ChQvBackgroundInfoData *pData = (ChQvBackgroundInfoData *)(m_pBackGroundNode->GetRenderData());
pData->OnResize(this);
}
if(GetCurrentCamera())((ChQvPCameraRenderData*)(GetCurrentCamera()->GetRenderData()))->SynchCamera();
SetDirty();
UnlockScene();
}
}
#endif
void ChRenderContext::SetModulation(bool boolUseTexture /*= true*/, bool boolPureEmissive)
{
#if defined(CH_USE_3DR)
Fixed32_t On = 1;
Fixed32_t Off = 0;
if(boolUseTexture && boolPureEmissive)
{
// turn off texture modulation - it paints black
R3dSetState( m_hRC, R3D_STA_DISABLES, R3D_SE_MODULATION);
G3dSetState( m_hGC, G3DL_TEXTURE_MOD, &Off);
}
else if(boolUseTexture && (R3dGetState( m_hRC, R3D_STA_ENABLES) & R3D_SE_SHADING))
{
// Normal case for diffuse or specular faces - must be smooth shaded to work
// in 3dr.
R3dSetState( m_hRC, R3D_STA_ENABLES, R3D_SE_MODULATION);
G3dSetState( m_hGC, G3DL_TEXTURE_MOD, &On);
}
else if(boolUseTexture)
{
// turn off texture modulation - no smoothing
R3dSetState( m_hRC, R3D_STA_DISABLES, R3D_SE_MODULATION);
G3dSetState( m_hGC, G3DL_TEXTURE_MOD, &Off);
}
// else texturing is off, so don't care
#elif (defined(CH_USE_RLAB)) || defined(CH_USE_D3D)
// not needed
#else
#pragma message("ChRenderContext::SetModulation() Not done!")
#endif
}
// Set shading according to user preferences and traversal state
ChRenderContext* ChRenderContext::SetShading( ChQvShapeInstance *pInstance )
{
#if defined(CH_USE_3DR)
ChShadingLevel stateShading = defaultShading;
ChShadingLevel resultShading;
int permute[5];
permute[int(smoothShading)] = 0;
permute[int(flatShading)] = 1;
permute[int(noShading)] = 2;
permute[int(defaultShading)] = 3;
permute[int(wireFrame)] = 4;
// Indexing is [user][state]
static ChShadingLevel aShadingTbl[5][5] =
{
// user == smoothShading
{ smoothShading, flatShading, noShading, smoothShading, noShading },
// user == flatShading
{ flatShading, flatShading, noShading, flatShading, noShading },
// user == none
{ noShading, noShading, noShading, noShading, noShading },
// user == defaultShading
{ smoothShading, flatShading, noShading, defaultShading, noShading },
// user == wireframe
{ noShading, noShading, noShading, noShading, noShading }
};
// Get Stack top and get the shading value, if any
// Right now the node only pushes shading nodes, so we don't have to walk down
QvInfo *pInfoNode = 0;
if(pInstance) pInfoNode = pInstance->GetInfo();
if(pInfoNode && pInfoNode->GetRenderData())
{
stateShading = ((ChQvInfoRenderData *)(pInfoNode->GetRenderData()))->GetShading();
}
// Make sure values are in range - Help stamp out wild pointers
int i = int(m_userShading); if(i>sizeof(permute)/sizeof(permute[0]) || i<0) i = defaultShading;
int j = int(stateShading); if(j>sizeof(permute)/sizeof(permute[0]) || j<0) j = defaultShading;
// Lookup in table
resultShading = aShadingTbl[permute[i]][permute[j]];
// Set it into the renderer's context
Fixed32_t On = 1;
Fixed32_t Off = 0;
if (resultShading == flatShading)
{
R3dSetState( GetRC(), R3D_STA_DISABLES, R3D_SE_SHADING);
//G3dSetState( GetGC(), G3DL_FLAT_SHADING, &On);
}
else if (resultShading == noShading)
{
R3dSetState( GetRC(), R3D_STA_DISABLES, R3D_SE_SHADING);
//G3dSetState( GetGC(), G3DL_FLAT_SHADING, &On);
}
else if (resultShading == smoothShading)
{
R3dSetState( GetRC(), R3D_STA_ENABLES, R3D_SE_SHADING);
//G3dSetState( GetGC(), G3DL_FLAT_SHADING, &Off);
}
else // default to smoothShading
{
R3dSetState( GetRC(), R3D_STA_ENABLES, R3D_SE_SHADING );
//G3dSetState( GetGC(), G3DL_FLAT_SHADING, &Off);
}
#elif (defined(CH_USE_RLAB)) || defined(CH_USE_D3D)
// not needed
#else
#pragma message("ChRenderContext::SetShading() Not done!")
#endif
return this;
}
#if defined(CH_USE_3DR)
// Private helper function for RebuildTransformStack
int ChRenderContext::ApplyQvTail( QvElement *elt)
{
int tailDepth = 0;
TransformF_t eltMat;
G3dSetActiveStack(m_hGC, G3DT_MODEL);
if(elt->next)
{
tailDepth = ApplyQvTail( elt->next );
}
if( tailDepth < elt->depth || elt->type == QvElement::NoOpTransform)
{
G3dPushTransform(m_hGC);
}
if(GetTransform( elt, eltMat))
{
G3dPostMultTransform(m_hGC, eltMat);
}
return elt->depth;
}
void ChRenderContext::RebuildTransformStack(ChQvState *pState)
{
// recurse down the qv stack, applying each matrix, and pushing the geometry engine stack
// each time the element depth changes, or a nooptransform is encountered. (Noop transforms are
// used by TransformSeparator::traverse as markers)
QvElement * top = pState->getTopElement(QvState::TransformationIndex);
G3dSetActiveStack(GetGC(), G3DT_MODEL);
if(top) ApplyQvTail( top );
}
#else
// not used by other renderer's implementations
#endif
Ch3DViewerMode ChRenderContext::GetViewerMode()
{
Ch3DViewerMode mode = ((ChMazeWnd*)GetWnd())->GetSceneViewerMode();
Ch3DViewerMode prefMode = ((ChMazeWnd*)GetWnd())->GetSettings()->GetViewerMode();
#if 0
if(mode == none || ((ChMazeWnd*)GetWnd())->GetSettings()->GetOverrideSceneMode())
{
mode = prefMode;
}
#endif
return prefMode;
}
ChQvTransformationInstance *ChRenderContext::GetDefaultTransform()
{
ChQvRenderBaseData *pData = (ChQvRenderBaseData *)(m_ppDefaults[QvState::TransformationIndex]->GetRenderData());
return (ChQvTransformationInstance *)(pData->m_instances.GetHead());
}
ChRenderContext* ChRenderContext::AddCamera(QvNode *pCamera, string &strName)
{
if(!strName.IsEmpty())
{
ChCameraEntry *pEntry = new ChCameraEntry(strName, pCamera,
((ChMazeWnd*)GetWnd())-> GetCurrentPage());
m_cameras.AddTail(pEntry);
m_cameraCount++;
}
return this;
}
ChRenderContext* ChRenderContext::RemoveCamera(string &strName)
{
if(!strName.IsEmpty() && !m_cameras.IsEmpty())
{
ChPosition pos = m_cameras.GetHeadPosition();
while(pos)
{
ChPosition thisPos = pos;
ChCameraEntry *pEntry = m_cameras.GetNext(pos);
if(pEntry && strName == pEntry->GetName())
{
m_cameras.Remove(thisPos);
delete pEntry;
break;
}
}
//m_cameras.Delete(strName);
m_cameraCount--;
}
return this;
}
ChRenderContext* ChRenderContext::RemoveCameras()
{
while(!m_cameras.IsEmpty())
{
ChCameraEntry *pEntry = m_cameras.RemoveHead();
delete pEntry;
}
m_cameraCount = 0;
return this;
}
//////////////// ChCameraIterator - only non-trivial method ////////////
// We put it here because of similarity to RC camera stuff
bool ChCameraIterator::Iterate()
{
if(!m_pRC) return false;
bool boolContinue = true;
if(!m_pRC->m_cameras.IsEmpty())
{
ChPosition pos = m_pRC->m_cameras.GetHeadPosition();
while(pos && boolContinue)
{
ChCameraEntry *pEntry = m_pRC->m_cameras.GetNext(pos);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -