📄 cvinstnc.cpp
字号:
/*----------------------------------------------------------------------------
_ _ _
/\ | | | (_)
/ \ _ __ __| |_ __ ___ _ __ ___ ___ __| |_ __ _
/ /\ \ | '_ \ / _` | '__/ _ \| '_ ` _ \ / _ \/ _` | |/ _` |
/ ____ \| | | | (_| | | | (_) | | | | | | __/ (_| | | (_| |
/_/ \_\_| |_|\__,_|_| \___/|_| |_| |_|\___|\__,_|_|\__,_|
The contents of this file are subject to the Andromedia Public
License Version 1.0 (the "License"); you may not use this file
except in compliance with the License. You may obtain a copy of
the License at http://www.andromedia.com/APL/
Software distributed under the License is distributed on an
"AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
implied. See the License for the specific language governing
rights and limitations under the License.
The Original Code is Pueblo client code, released November 4, 1998.
The Initial Developer of the Original Code is Andromedia Incorporated.
Portions created by Andromedia are Copyright (C) 1998 Andromedia
Incorporated. All Rights Reserved.
Andromedia Incorporated 415.365.6700
818 Mission Street - 2nd Floor 415.365.6701 fax
San Francisco, CA 94103
Contributor(s):
--------------------------------------------------------------------------
Chaco team: Dan Greening, Glenn Crocker, Jim Doubek,
Coyote Lussier, Pritham Shetty.
Wrote and designed original codebase.
------------------------------------------------------------------------------
Implementation for the ChQvInstance class for Intel 3DR.
----------------------------------------------------------------------------*/
// $Header: /home/cvs/chaco/modules/client/msw/ChGraphx/CvInstnc.cpp,v 2.35 1996/06/30 19:44:15 jimd Exp $
#include "grheader.h"
#include "CvInstnc.h"
#include <QvInfo.h>
#include <QvState.h>
#include "ChMaze.h"
#include "ChRenderData.h"
#include "ChScriptData.h"
#include "ChMazDep.h"
#include "CvTrnsfm.h"
#include "CvNormal.h"
#include "CvBound.h"
#include "CvConvrt.h"
#include "CvHitTst.h"
#include "imode.h"
//#define VERIFY_NO_THREAD_CONFLICT 1
#if defined(VERIFY_NO_THREAD_CONFLICT)
static HANDLE ghCurrentAddThread = 0;
#define CheckAddThread() \
{if(0 == ghCurrentAddThread) ghCurrentAddThread = GetCurrentThread();\
ASSERT(ghCurrentAddThread == GetCurrentThread());}
#else
#define CheckAddThread()
#endif
#if (defined(CH_USE_RLAB) || defined(CH_USE_D3D))
class ChCanCollapseIterator : public ChQvInstanceIterator
{
public:
ChCanCollapseIterator(ChRenderContext * pContext) :
ChQvInstanceIterator(pContext), m_boolCanCollapse(true)
{};
virtual ~ChCanCollapseIterator() {};
virtual int DoNode(ChQvInstance& inst)
{
if(!inst.CanCollapse())
{
m_boolCanCollapse = true;
return false;
}
return true;
};
bool CanCollapse() {return m_boolCanCollapse;};
protected:
bool m_boolCanCollapse;
private:
/* Disable copy constructor and
assignment operator */
inline ChCanCollapseIterator( const ChDrawIterator& ) : ChQvInstanceIterator(0) {}
inline ChCanCollapseIterator& operator=( const ChDrawIterator& )
{
return *this;
}
};
#endif
//#define COUNT_INSTANCES 1
#if defined(COUNT_INSTANCES)
static int iInstCount = 0;
#endif
/////////////////////////////////////////////////////////////////////////////////////////////
ChQvInstance::ChQvInstance() :
m_pNode(0),
m_pParent(0),
m_pRenderData(0),
m_pBounds(0),
m_pTransform(0),
#if (defined(CH_USE_RLAB) || defined(CH_USE_D3D))
m_frame(0),
m_boolConstructed(0),
#endif
m_pContext(0),
m_boolBoundsDirty(true),
m_boolRenderDirty(true),
m_boolDeleteMe(false),
m_iUsage(1)
{
#if defined(COUNT_INSTANCES)
iInstCount ++;
TRACE1("Instance count = %d\n", iInstCount);
#endif
}
ChQvInstance::~ChQvInstance()
{
#if defined(COUNT_INSTANCES)
iInstCount --;
#endif
if(m_pRenderData)
{ // TODO more graceful destruction
if(m_pRenderData) m_pRenderData->Remove(this);
m_pRenderData = 0;
}
if(m_pParent)
{
m_pParent->Remove(this);
m_pParent = 0;
}
m_pNode=0;
delete m_pBounds;
m_pBounds = 0;
if(m_pTransform)
{
m_pTransform->RemoveDependent(this);
}
}
#if 1
void ChQvInstance::Use(bool boolChildren /*= true */ , chuint32 uBump /*= 1*/)
{
m_iUsage += uBump;
//TRACE2("Use %lx -> %d\n", UINT(this), m_iUsage);
}
void ChQvInstance::Release(bool boolChildren /*= true*/ , chuint32 uBump /*= 1*/)
{
m_iUsage -= uBump;
//TRACE2("Release %lx -> %d\n", UINT(this), m_iUsage);
if(m_iUsage <= 0)
{
//TRACE1("Delete %lx\n", UINT(this));
delete this;
}
}
#endif
bool ChQvInstance::GetBounds(ChQvBounds& bounds)
{
if(m_boolBoundsDirty)
{
ComputeBounds();
}
if(m_pBounds)
{
m_pBounds->SetTransform(GetTransform()); // cached transform might be out of date?
bounds = *m_pBounds;
}
else
{
bounds.SetTransform(GetTransform()); // cached transform might be out of date?
}
return (m_pBounds != 0);
}
ChQvInstance* ChQvInstance::Attach(QvNode *pNode, ChQvBuildState *pState)
{
m_pNode = pNode;
ChQvRenderBaseData *pRenderData = (ChQvRenderBaseData *)(pNode->GetRenderData());
// Hook us together
m_pRenderData = pRenderData;
pRenderData->Add(this);
ChQvGroupInstance *pParent = pState->GetCurrentParent();
if(pParent) pParent->Add(this);
Init(pState);
#if (defined(CH_USE_RLAB) || defined(CH_USE_D3D))
Build(GetContext());
#endif
return this;
}
bool ChQvInstance::Iterate(ChQvInstanceIterator *pIterator)
{
ChQvInstanceIterator::whenVisiting visit = pIterator->GetVisitType();
pIterator->SetVisitType(ChQvInstanceIterator::isLeaf);
bool boolKeepGoing = pIterator->DoNode(*this);
pIterator->SetVisitType(visit);
return boolKeepGoing;
}
void ChQvInstance::Init(ChQvBuildState *pState)
{
ChRenderContext *pRC = pState->GetView()->GetRenderContext();
//SetTransform(pRC->GetModelTransform());
m_pContext = pRC;
ChQvElement *pElt = (ChQvElement *)(pState->getTopElement(QvState::TransformationIndex));
if(pElt)
{
ASSERT(pElt->GetInstance());
m_pTransform = (ChQvTransformationInstance*)(pElt->GetInstance());
m_pTransform->AddDependent(this);
}
else
{
m_pTransform = pRC->GetDefaultTransform();
m_pTransform->AddDependent(this);
}
}
GxVec3f ChQvInstance::Transform(const GxVec3f& v)
{
return GetTransform() * v;
};
GxVec3f ChQvInstance::TransformWorldToModel(const GxVec3f& v)
{
return GetTransform().Inverse() * v;
};
GxTransform3Wf& ChQvInstance::GetTransform()
{
return m_pTransform->GetTransform();
};
ChQvInstance* ChQvInstance::SetTransform(ChQvTransformationInstance *pTransform)
{
m_pTransform = pTransform;
return this;
}
ChQvInstance * ChQvInstance::GetPipeline(ChRenderContext *pRC, ChPipeline &pipeline)
{
GxTransform3Wf modelCamera = pRC->GetWorldToCameraTransform(); // world to camera
GxTransform3Wf cameraToClip = pRC->GetCameraToClipTransform();
GxTransform3Wf clipToScreen = pRC->GetClipToScreenTransform();
pipeline.Set(GetTransform(), modelCamera, cameraToClip, clipToScreen);
return this;
}
void ChQvInstance::Term()
{
// placeholder
}
bool ChQvInstance::ComputeBounds()
{
// Every class needs to do their own. Maybe this should be pure virtual
return false;
}
#if (defined(CH_USE_RLAB) || defined(CH_USE_D3D))
void ChQvInstance::CreateFrame()
{
if(GetParent())
{
m_frame = GetContext()->CreateFrame(GetParent()->GetFrame());
}
else
{
m_frame = GetContext()->CreateFrame(m_pContext->GetFrame());
}
ChNrFrameAddTransform(m_frame, CombineBefore, *(GetTransform().GetMatrix()));
ChNrObjectSetAppData(m_frame, (unsigned long)this);
D3DRelease(m_frame);
InstallScripts();
};
ChNrFrame ChQvInstance::GetParentFrame()
{
ChNrFrame frame = 0;
if(GetParent())
{
frame = GetParent()->GetFrame();
}
if(!frame)
{
frame = m_pContext->GetFrame();
}
return frame;
};
bool ChQvInstance::CanCollapse()
{
if(GetParent() == 0) return false; // never collapse the root
return true;
};
bool ChQvInstance::Collapse()
{
#if 0 // not needed for now
if(m_frame)
{
ChNrFrame *pFrames;
int count;
ChNrFrameGetChildren(m_frame, &count, &pFrames);
if(count)
{
ChNrMesh mesh;
mesh = ChNrFrameBuildMesh(m_frame);
for(int j=0; j < count; j++)
{
ChNrFrame child = pFrames[j];
ChNrFrameRemoveChild(m_frame, child);
}
ChNrFrameAddVisual(m_frame, mesh);
ChNrObjectSetAppData(mesh, (unsigned long)this);
}
RLFree(pFrames);
}
#endif
return true;
}
#endif
void ChQvInstance::InstallScripts()
{
ChQvRenderBaseData *pData = (ChQvRenderBaseData *)(GetNode()->GetRenderData());
if(pData)
{
MyInstallScriptIterator iterator(*pData, this);
iterator.IterateScripts();
}
}
bool ChQvInstance::SetTexture(ChQvTextureRenderData *pTextureData, ChNrMesh mesh)
{
return false; // false says nothing happened
}
void ChQvInstance::MarkForRemoval(bool boolDelete /*= true*/)
{
m_boolDeleteMe = boolDelete;
m_pNode = 0; // break the link with the Node, it's probably going away
}
string& ChQvInstance::GetRelativeURL()
{
if(GetParent()) return GetParent()->GetRelativeURL();
return (((ChMazeWnd *)(GetContext()->GetWnd()))->GetCurrentURL());
}
// Transformation Instance Classes
ChQvTransformationInstance::ChQvTransformationInstance() : ChQvInstance(), m_pPredecessor(0)
{}
ChQvTransformationInstance::~ChQvTransformationInstance()
{
while(!m_dependents.IsEmpty())
{
ChQvInstance *pDependent = m_dependents.RemoveHead();
if(pDependent) pDependent->SetTransform( 0 );
}
}
void ChQvTransformationInstance::Init(ChQvBuildState *pState)
{
// Don't do the usual stuff...
ChQvElement *pElt = (ChQvElement *)(pState->getTopElement(QvState::TransformationIndex));
// Top is us, we go one deeper for who we depend on
if(pElt->next)
{
// Make this a dependent of instance that -was- top
ChQvElement *pPrevTop = (ChQvElement *)(pElt->next);
m_pPredecessor = ((ChQvTransformationInstance*)(pPrevTop->GetInstance()));
m_pPredecessor->AddDependent(this);
}
m_pTransform = m_pPredecessor;
ChRenderContext *pRC = pState->GetView()->GetRenderContext();
m_pContext = pRC;
SetTransform(pRC->GetModelTransform());
}
ChQvInstance* ChQvTransformationInstance::Attach(QvNode *pNode, ChQvBuildState *pState)
{ // TODO zap this, unnecessary ????
//ChQvInstance::Attach(pNode, pState);
m_pNode = pNode;
ChQvRenderBaseData *pRenderData = (ChQvRenderBaseData *)(pNode->GetRenderData());
// Hook us together
m_pRenderData = pRenderData;
pRenderData->Add(this);
ChQvGroupInstance *pParent = pState->GetCurrentParent();
//if(pParent) pParent->Add(this);
Init(pState);
return this;
}
ChQvInstance* ChQvTransformationInstance::SetTransformDirty(bool boolDirty)
{
// recurse to force recompute of all dependents
if(boolDirty)
{
if(m_pPredecessor)
{
m_ModelTransform = m_pPredecessor->m_ModelTransform.Compose(m_SelfTransform); // ?????????
//m_ModelTransform = m_SelfTransform.Compose(m_pPredecessor->m_ModelTransform); // ?????????
//m_ModelTransform = m_pPredecessor->m_ModelTransform * m_SelfTransform; // ?????????
}
else
{
m_ModelTransform = m_SelfTransform;
}
}
if(!m_dependents.IsEmpty())
{
ChPosition pos = m_dependents.GetHeadPosition();
while(pos)
{
ChQvInstance *pInst = m_dependents.GetNext(pos);
pInst->SetTransformDirty(boolDirty);
}
}
return this;
}
ChQvTransformationInstance* ChQvTransformationInstance::SetTransform(const GxTransform3Wf& modelTransform)
{
m_ModelTransform = modelTransform;
return this;
}
ChQvTransformationInstance* ChQvTransformationInstance::SetSelfTransform(const GxTransform3Wf& transform)
{
m_SelfTransform = transform;
return this;
}
ChQvTransformationInstance* ChQvTransformationInstance::AddDependent(ChQvInstance *pDependent)
{
CheckAddThread();
m_dependents.AddTail(pDependent);
return this;
}
ChQvTransformationInstance* ChQvTransformationInstance::RemoveDependent(ChQvInstance *pDependent)
{
CheckAddThread();
if(!m_dependents.IsEmpty())
{
ChPosition pos = m_dependents.Find(pDependent);
if(pos){
m_dependents.Remove(pos);
}
pDependent->SetTransform( 0 );
}
return this;
}
// ChQvGroupInstance
ChQvGroupInstance::ChQvGroupInstance() : ChQvInstance(), m_boolChildPendingRemoval(false)
{
}
ChQvGroupInstance::~ChQvGroupInstance()
{
// Delete children
CheckAddThread();
while(!m_children.IsEmpty())
{
ChQvInstance* pChild = m_children.RemoveHead();
//delete pChild;
//pChild->SetParent(0);
//if(pChild) pChild->Release(); YIKES!!!!!!!!!! DOUBLE DELETE!!
if(pChild) pChild->m_pParent = 0;
}
ChQvInstanceHasProps::Term(this);
}
ChQvInstance* ChQvGroupInstance::Attach(QvNode *pNode, ChQvBuildState *pState)
{
ChQvInstance::Attach(pNode, pState);
// Add the group's transform instance onto the stack
ChQvElement *elt = new ChQvElement;
elt->data = pNode;
elt->type = QvElement::Transform;
pState->addElement(QvState::TransformationIndex, elt);
ChQvTransformationInstance *pTransformInstance = GetTransformInstance();
pTransformInstance->Attach(pNode, pState, this);
GxTransform3Wf mat;
pTransformInstance->SetSelfTransform(mat);
elt->SetInstance(pTransformInstance);
return this;
}
ChQvTransformationInstance* ChQvTransformationInstance::Attach(QvNode *pNode, ChQvBuildState *pState, ChQvGroupInstance *pOwner)
{
m_pNode = pNode;
ChQvRenderBaseData *pRenderData = (ChQvRenderBaseData *)(pNode->GetRenderData());
// Hook us together
//m_pRenderData = pRenderData;
m_pRenderData = 0;
// We don't add to renderdata or parent, because we are not an instance of Group
Init(pState);
#if (defined(CH_USE_RLAB) || defined(CH_USE_D3D))
Build(GetContext());
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -