📄 cvinstnc.cpp
字号:
#endif
return this;
}
#if 1
void ChQvGroupInstance::Use(bool boolChildren /*= true */, chuint32 uBump /*= 1*/)
{
m_iUsage += uBump;
//TRACE2("Use %lx -> %d (grp)\n", UINT(this), m_iUsage);
if(boolChildren && !m_children.IsEmpty())
{
ChPosition pos = m_children.GetHeadPosition();
while(pos)
{
ChQvInstance *pChild = m_children.GetNext(pos);
pChild->Use(boolChildren);
}
}
}
void ChQvGroupInstance::Release(bool boolChildren /*= true*/, chuint32 uBump /*= 1*/)
{
m_iUsage -= uBump;
//TRACE2("Release %lx -> %d (grp)\n", UINT(this), m_iUsage);
if(boolChildren && !m_children.IsEmpty())
{
ChPosition pos = m_children.GetHeadPosition();
while(pos)
{
ChQvInstance *pChild = m_children.GetNext(pos);
pChild->Release(boolChildren, uBump);
}
}
if(m_iUsage <= 0)
{
delete this;
}
}
#endif
void ChQvGroupInstance::Init(ChQvBuildState *pState)
{
ChQvInstance::Init(pState);
ChQvInstanceHasProps::Init(pState, this);
}
void ChQvGroupInstance::RestoreProp(ChQvState &state, QvNode *pProp, QvState::StackIndex stackIndex)
{
QvElement *elt = new QvElement;
elt->data = pProp;
state.addElement(stackIndex, elt);
}
ChQvGroupInstance *ChQvGroupInstance::SetupTraversalState(ChQvState &state)
{
ChRenderContext *pRC = state.GetView()->GetRenderContext();
pRC->SetModelTransform(GetTransform());
/// set up stack to have proper transform instance at top to
// inherit into subtree
ChQvElement *elt = new ChQvElement;
elt->data = m_pTransform->GetNode();
elt->SetInstance(m_pTransform);
state.addElement(QvState::TransformationIndex, elt);
// Now all the other simpler props
RestoreProp(state, GetMaterial(), QvState::MaterialIndex );
RestoreProp(state, GetMaterialBinding(), QvState::MaterialBindingIndex );
RestoreProp(state, GetNormal(), QvState::NormalIndex );
RestoreProp(state, GetNormalBinding(), QvState::NormalBindingIndex );
RestoreProp(state, GetCoordinate3(), QvState::Coordinate3Index );
RestoreProp(state, GetTextureCoordinate2(), QvState::TextureCoordinate2Index );
RestoreProp(state, GetTexture2Transform(), QvState::Texture2TransformationIndex);
RestoreProp(state, GetShapeHints(), QvState::ShapeHintsIndex );
RestoreProp(state, GetInfo(), QvState::InfoIndex );
RestoreProp(state, GetFontStyle(), QvState::FontStyleIndex );
return this;
}
#if (defined(CH_USE_RLAB) || defined(CH_USE_D3D))
#if (defined(CH_USE_RLAB))
void GroupCallback(ChNrFrame frame, void * arg)
#else
void GroupCallback(ChNrFrame frame, void * arg, float delta)
#endif
{
#if defined(CH_VRML_EVENTS)
ChQvGroupInstance *pInst = (ChQvGroupInstance *)arg;
if(pInst->HasChildrenMarkedForRemoval())pInst->RemoveMarkedChildren();
#endif
}
void ChQvGroupInstance::CreateFrame()
{
if(GetParent())
{
m_frame = GetContext()->CreateFrame(GetParent()->GetFrame());
}
else
{
m_frame = GetContext()->CreateFrame(m_pContext->GetFrame());
}
// Difference is that we don't do this: ChNrFrameAddTransform(m_frame, CombineBefore, *(GetTransform().GetMatrix()));
ChNrObjectSetAppData(m_frame, (unsigned long)this);
// Now add the callback for removing unwanted children
ChNrFrameAddCallback(m_frame, GroupCallback, this);
D3DRelease(m_frame);
InstallScripts();
};
// Callback to collapse mesh while rendering
void CollapseFrameCallback(ChNrFrame frame, void * arg)
{
#if 0
ChQvLODInstance *pInst = (ChQvLODInstance *)arg;
pInst->Collapse();
ChNrFrameRemoveCallback(frame, CollapseFrameCallback, pInst);
#endif
}
bool ChQvGroupInstance::Draw(ChRenderContext *pRC, ChDrawIterator *pIterator)
{
ASSERT(m_frame);
return true;
}
bool ChQvGroupInstance::Construct(ChRenderContext *pRC, ChConstructionIterator *pIterator)
{
ASSERT(m_frame);
#if 0
// Collapsing causes crashes in RL wehn we add the new mesh - ???
if(CanCollapse())
{
pRC->LockScene();
ChCanCollapseIterator iterator(pRC);
iterator.Attach(this);
iterator.IterateAll();
if(iterator.CanCollapse())
{
ChNrFrameAddCallback(m_frame, CollapseFrameCallback, this);
}
pRC->UnlockScene();
}
#endif
return true;
}
void ChQvGroupInstance::Build(ChRenderContext *pRC)
{
ASSERT(m_frame == 0);
CreateFrame();
}
void ChQvShapeInstance::Build(ChRenderContext *pRC)
{
ASSERT(m_frame == 0);
CreateFrame();
}
#endif
ChQvGroupInstance * ChQvGroupInstance::Add(ChQvInstance *pChild)
{
CheckAddThread();
if(pChild->m_pParent)
{
m_pParent->Remove(pChild);
}
m_children.AddTail(pChild);
pChild->m_pParent = this;
// Adjust the child's usage count to match the parent
// This means any construction threads will decrement
// correctly.
int iUsage = GetUsage() - pChild->GetUsage();
if(iUsage > 0) pChild->Use(true, chuint32(iUsage));
return this;
}
bool ChQvGroupInstance::Remove(ChQvInstance *pChild)
{
CheckAddThread();
if(m_children.IsEmpty()) return false;
ChPosition pos = m_children.Find(pChild);
if(pos)
{
m_children.Remove(pos);
pChild->m_pParent = 0;
}
//ASSERT(! m_children.Find(pChild)); // Should only be one copy!
return (pos != 0);
}
ChQvInstance* ChQvGroupInstance::GetChild( int iChild)
{
// result is only valid if all children were instatniated,
// and none have been deleted yet
ChQvInstance *pChild = 0;
if(!m_children.IsEmpty())
{
ChPosition pos = m_children.FindIndex(iChild);
if(pos)
{
pChild = m_children.Get(pos);
}
}
return pChild;
}
bool ChQvGroupInstance::Iterate(ChQvInstanceIterator *pIterator)
{
// Visit self pre
pIterator->SetVisitType(ChQvInstanceIterator::beforeChildren);
pIterator->SetDoKids(true);
bool boolKeepGoing = pIterator->DoNode(*this);
// Visit kids if any
if(pIterator->ShouldDoKids() && !m_children.IsEmpty())
{
ChPosition pos = m_children.GetHeadPosition();
while(pos && boolKeepGoing)
{
pIterator->SetVisitType(ChQvInstanceIterator::isLeaf);
ChQvInstance *pChild = m_children.GetNext(pos);
boolKeepGoing = pChild->Iterate(pIterator);
}
}
// Visit self post
pIterator->SetDoKids(true);
if(boolKeepGoing)
{
pIterator->SetVisitType(ChQvInstanceIterator::afterChildren);
boolKeepGoing = pIterator->DoNode(*this);
}
return boolKeepGoing;
}
void ChQvGroupInstance::MarkChildForRemoval(QvNode *pNode)
{
m_boolChildPendingRemoval = true;
if(!m_children.IsEmpty())
{
ChPosition pos = m_children.GetHeadPosition();
while(pos)
{
ChQvInstance *pChild = m_children.GetNext(pos);
if( pChild->GetNode() == pNode ) pChild->MarkForRemoval();
}
}
}
void ChQvGroupInstance::RemoveMarkedChildren()
{
#if (defined(CH_USE_RLAB) || defined(CH_USE_D3D))
if(!m_children.IsEmpty())
{
// m_pContext->LockConstruction();
ChPosition pos = m_children.GetHeadPosition();
TRACE("Removing marked children\n");
while(pos)
{
ChQvInstance *pChild = m_children.GetNext(pos);
if( pChild->IsMarkedForRemoval() )
{
ChNrFrameRemoveChild(m_frame, pChild->GetFrame());
//delete pChild;
pChild->Release();
}
}
// m_pContext->UnlockConstruction();
}
#endif
m_boolChildPendingRemoval = false;
};
ChQvInstance * ChQvGroupInstance::InstantiateChild(QvNode *pNewChild)
{
#if (defined(CH_USE_RLAB) || defined(CH_USE_D3D))
ChQvBuildState bldIt((ChMazeWnd*)(GetContext()->GetWnd()));
// Alternative idea, setCurrentParent(0), then extract it from
// state and add to parent??
bldIt.SetCurrentParent(this);
SetupTraversalState(bldIt);
pNewChild->traverse(&bldIt);
// Now construct them for RLab
ChQvInstance *pChildInst = (m_children.IsEmpty() ? 0 : m_children.GetTail());
if(pChildInst)
{
GetContext()->StartConstruction(pChildInst);
}
return pChildInst;
#else
return 0;
#endif
}
//////////////////////////////////////////////////////////////////////
// Iterators
ChQvInstanceIterator::ChQvInstanceIterator(ChRenderContext * pContext) :
m_pRoot(0), m_pContext(pContext), m_boolDoKids(true)
{
}
ChQvInstanceIterator::ChQvInstanceIterator(ChRenderContext * pContext, ChQvInstance* pRoot ) :
m_pRoot(0), m_pContext(pContext), m_boolDoKids(true)
{
Attach(pRoot);
}
ChQvInstanceIterator::~ChQvInstanceIterator()
{
}
void ChQvInstanceIterator::Attach( ChQvInstance *pInst )
{
m_pRoot = pInst;
}
bool ChQvInstanceIterator::Iterate() // Just those in draw scope; respects lods,etc.
{
m_type = inDrawScope;
if(!m_pRoot) return false;
return m_pRoot->Iterate(this);
}
int ChQvInstanceIterator::IterateAll() // Exhaustive iteration
{
m_type = all;
if(!m_pRoot) return false;
return m_pRoot->Iterate(this);
}
int ChDrawIterator::DoNode(ChQvInstance& inst)
{
bool boolKeepGoing = true;
if(GetVisitType() == isLeaf || GetVisitType() == afterChildren)
{
boolKeepGoing = inst.Draw(m_pContext, this);
}
return boolKeepGoing;
}
#if (defined(CH_USE_RLAB) || defined(CH_USE_D3D))
bool ChDrawIterator::Iterate() // Just those in draw scope; respects lods,etc.
{
m_startTime = ::GetTickCount();
bool retVal = ChQvInstanceIterator::Iterate();
return retVal;
}
bool ChDrawIterator::IterateAll() // Exhaustive iteration
{
m_startTime = ::GetTickCount();
bool retVal = ChQvInstanceIterator::IterateAll();
return retVal;
}
#endif
int ChConstructionIterator::DoNode(ChQvInstance& inst)
{
bool boolKeepGoing = true;
if(GetVisitType() == isLeaf || GetVisitType() == afterChildren)
{
boolKeepGoing = inst.Construct(m_pContext, this);
}
if(!boolKeepGoing) m_boolWorkRemains = true; // halted with work to do
return boolKeepGoing;
}
#if (defined(CH_USE_RLAB) || defined(CH_USE_D3D))
bool ChConstructionIterator::IsOKToProceed(ChQvInstance *pInst)
{
if ( GetRenderContext()->ContinueConstruction() && (!pInst || (pInst->GetNode() && pInst->GetRenderData())))
{
// Must call UnlockScene if this succeeds!
if(GetRenderContext()->IsThreaded())
{
GetRenderContext()->LockScene();
//GetRenderContext()->LockQv(); // Lock tree so other threads don't kill our data
}
else
{
// Check work done and elapsed time, and return false if exceeded
//#pragma message("nonthreaded not done")
int iMaxMsgs = 0;
CWinThread* pThread = AfxGetThread();
while ( GetRenderContext()->ContinueConstruction() && iMaxMsgs < 100 )
{
MSG msg;
if (::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) )
{
if ( msg.message == WM_VRML_PARSE_DONE )
{ // if there is a new scene to load, we should abort
// construction for the current scene. The message WM_VRML_PARSE_DONE
// should be retrieved from the main message loop, this guarantees that
// there is no construction going on.
return false;
}
if (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
iMaxMsgs++; // Num messages processed
::DispatchMessage(&msg);
}
// allow user-interface updates
pThread->OnIdle(-1);
}
else
{
break;
}
}
if ( !GetRenderContext()->ContinueConstruction() )
{
return false;
}
}
return true;
}
else
{ // Construction has been canceled
return false;
}
}
void ChConstructionIterator::DidAShape()
{
m_workDone ++;
GetRenderContext()->IncrementShapeCount();
if(GetRenderContext()->IsThreaded())
{
if(::GetTickCount() - m_startTime > TimeToDirty || ::GetTickCount() < m_startTime)
{
GetRenderContext()->SetDirty();
m_startTime = ::GetTickCount();
SayProgress();
}
}
else
{
GetRenderContext()->SetDirty(); // Set dirty for every piece of work
}
}
void ChConstructionIterator::SayProgress(bool boolDone)
{
#if (defined(CH_USE_RLAB) || defined(CH_USE_D3D))
ChMazeWnd *pWnd = (ChMazeWnd *)(m_pContext->GetWnd());
if(boolDone)
{ // PRITHAM: Please figure out how to do this
pWnd->WriteStatus( PROGRESS_MSG_1 );
}
else
{
pWnd->WriteStatus( PROGRESS_MSG_2 );
}
#endif
}
bool ChConstructionIterator::Iterate() // Just those in draw scope; respects lods,etc.
{
m_startTime = ::GetTickCount();
m_workDone = 0;
SayProgress();
bool retVal = ChQvInstanceIterator::Iterate();
SayProgress(true);
return retVal;
}
bool ChConstructionIterator::IterateAll() // Exhaustive iteration
{
m_startTime = ::GetTickCount();
m_workDone = 0;
SayProgress();
bool retVal = ChQvInstanceIterator::IterateAll();
SayProgress(true);
return retVal;
}
#endif
// Pipeline
ChPipeline * ChPipeline::Set(GxTransform3Wf &model, GxTransform3Wf &world2Cam, GxTransform3Wf &cam2Clip, GxTransform3Wf &clip2Screen)
{
m_model = model;
m_world2Cam = world2Cam;
m_cam2Clip = cam2Clip;
m_clip2Screen = clip2Screen;
m_model2Clip = cam2Clip;
m_model2Clip *= world2Cam;
m_model2Clip *= model;
return this;
}
GxVec3f ChPipeline::TransformToScreen(GxVec3f& pt)
{
GxVec3f newPt;
float w;
newPt = m_model2Clip.TransformW(pt, w);
newPt *= 1. / w;
newPt = m_clip2Screen * newPt;
//newPt.y() = -newPt.y();
return newPt;
}
GxVec3f ChPipeline::TransformToPort(GxVec3f& pt, bool & boolClipped)
{
GxVec3f p;
float w;
p = m_model2Clip.TransformW(pt, w);
boolClipped = (p.x() <= -w || p.x() >= w || p.y() <= -w || p.y() >= w || p.z() <= 0. || p.z() >= w);
p *= 1. / w;
GxTransform3Wf clip2Port = m_clip2Screen;
(*(clip2Port.GetMatrix()))[1][1] = -(*(clip2Port.GetMatrix()))[1][1];
(*(clip2Port.GetMatrix()))[1][3] = -(*(clip2Port.GetMatrix()))[1][3];
p = clip2Port * p;
return p;
}
// end of file
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -