📄 chrenderdata.cpp
字号:
if(boolSuccess)
{
if((axis[0] != pRotation->axis[0]) ||
(axis[1] != pRotation->axis[1]) ||
(axis[2] != pRotation->axis[2]) ||
(angle != pRotation->angle))
{
pRotation->axis[0] = axis[0];
pRotation->axis[1] = axis[1];
pRotation->axis[2] = axis[2];
pRotation->angle = angle;
//SetDirty();
MyTransformDirtyIterator iterator(*this);
iterator.Iterate();
}
}
#endif
return boolSuccess;
}
bool ChQvTransformationRenderData::OnSetScaleFactor(ChRenderContext *pRC, ChApplet * pApplet, ChIVrmlEvent *pEventList)
{
bool boolSuccess = false;
#if defined(CH_VRML_EVENTS)
// Apply based on transform type - eventually this gets merged into
// the containing separator in 2.0 - if we were going to keep this node,
// we'd split out the classes, but for now just hack it
string strType;
float scale[3];
ChVec3fEvent *pEvent = (ChVec3fEvent *)pEventList;
pEvent->GetValue(scale);
QvSFVec3f *pScale = 0;
if(m_pNode->GetType(strType) == typeQvScale)
{
QvScale *pNode = (QvScale *)m_pNode;
pScale = &(pNode->scaleFactor);
boolSuccess = true;
}
else if(m_pNode->GetType(strType) == typeQvTransform)
{
QvTransform *pNode = (QvTransform *)m_pNode;
pScale = &(pNode->scaleFactor);
boolSuccess = true;
}
if(boolSuccess)
{
if((scale[0] != pScale->value[0]) ||
(scale[1] != pScale->value[1]) ||
(scale[2] != pScale->value[2]))
{
pScale->value[0] = scale[0];
pScale->value[1] = scale[1];
pScale->value[2] = scale[2];
MyTransformDirtyIterator iterator(*this);
iterator.Iterate();
}
}
#endif
return boolSuccess;
}
bool ChQvTransformationRenderData::OnSetTranslation(ChRenderContext *pRC, ChApplet * pApplet, ChIVrmlEvent *pEventList)
{
bool boolSuccess = false;
#if defined(CH_VRML_EVENTS)
// Apply based on transform type - eventually this gets merged into
// the containing separator in 2.0 - if we were going to keep this node,
// we'd split out the classes, but for now just hack it
string strType;
float translation[3];
ChVec3fEvent *pEvent = (ChVec3fEvent *)pEventList;
pEvent->GetValue(translation);
QvSFVec3f *pTranslation = 0;
if(m_pNode->GetType(strType) == typeQvTranslation)
{
QvTranslation *pNode = (QvTranslation *)m_pNode;
pTranslation = &(pNode->translation);
boolSuccess = true;
}
else if(m_pNode->GetType(strType) == typeQvTransform)
{
QvTransform *pNode = (QvTransform *)m_pNode;
pTranslation = &(pNode->translation);
boolSuccess = true;
}
if(boolSuccess)
{
if((translation[0] != pTranslation->value[0]) ||
(translation[1] != pTranslation->value[1]) ||
(translation[2] != pTranslation->value[2]))
{
pTranslation->value[0] = translation[0];
pTranslation->value[1] = translation[1];
pTranslation->value[2] = translation[2];
MyTransformDirtyIterator iterator(*this);
iterator.Iterate();
}
}
#endif
return boolSuccess;
}
bool ChQvTransformationRenderData::OnSetScaleOrientation(ChRenderContext *pRC, ChApplet * pApplet, ChIVrmlEvent *pEventList)
{
bool boolSuccess = false;
#if defined(CH_VRML_EVENTS)
// Apply based on transform type - eventually this gets merged into
// the containing separator in 2.0 - if we were going to keep this node,
// we'd split out the classes, but for now just hack it
string strType;
float axis[3];
float angle;
ChRotationEvent *pEvent = (ChRotationEvent *)pEventList;
pEvent->GetValue(axis, angle);
QvSFRotation *pRotation = 0;
if(m_pNode->GetType(strType) == typeQvTransform)
{
QvTransform *pNode = (QvTransform *)m_pNode;
pRotation = &(pNode->scaleOrientation);
boolSuccess = true;
}
if(boolSuccess)
{
if((axis[0] != pRotation->axis[0]) ||
(axis[1] != pRotation->axis[1]) ||
(axis[2] != pRotation->axis[2]) ||
(angle != pRotation->angle))
{
pRotation->axis[0] = axis[0];
pRotation->axis[1] = axis[1];
pRotation->axis[2] = axis[2];
pRotation->angle = angle;
//SetDirty();
MyTransformDirtyIterator iterator(*this);
iterator.Iterate();
}
}
#endif
return boolSuccess;
}
bool ChQvTransformationRenderData::OnSetCenter(ChRenderContext *pRC, ChApplet * pApplet, ChIVrmlEvent *pEventList)
{
bool boolSuccess = false;
#if defined(CH_VRML_EVENTS)
// Apply based on transform type - eventually this gets merged into
// the containing separator in 2.0 - if we were going to keep this node,
// we'd split out the classes, but for now just hack it
string strType;
float center[3];
ChVec3fEvent *pEvent = (ChVec3fEvent *)pEventList;
pEvent->GetValue(center);
QvSFVec3f *pCenter = 0;
if(m_pNode->GetType(strType) == typeQvTransform)
{
QvTransform *pNode = (QvTransform *)m_pNode;
pCenter = &(pNode->scaleFactor);
boolSuccess = true;
}
if(boolSuccess)
{
if((center[0] != pCenter->value[0]) ||
(center[1] != pCenter->value[1]) ||
(center[2] != pCenter->value[2]))
{
pCenter->value[0] = center[0];
pCenter->value[1] = center[1];
pCenter->value[2] = center[2];
MyTransformDirtyIterator iterator(*this);
iterator.Iterate();
}
}
#endif
return boolSuccess;
}
/////////////////////////////////////////////////////////////////////////////////
ChQvGroupRenderData::ChQvGroupRenderData(QvNode* pNode) :
ChQvRenderBaseData(pNode)
{
#if defined(CH_VRML_EVENTS)
if(!m_pDispatcher)
{
m_pDispatcher = new ChVrmlDispatcher;
Init();
}
#endif
};
void ChQvGroupRenderData::Init()
{
ChQvRenderBaseData::Init();
#if defined(CH_VRML_EVENTS)
AddVrmlDispatcher("add_children", SFNode, OnAddChildren);
AddVrmlDispatcher("add_children", MFNode, OnAddChildren);
AddVrmlDispatcher("remove_children", SFNode, OnRemoveChildren);
#endif
};
ChQvGroupRenderData::~ChQvGroupRenderData()
{
}
void ChQvGroupRenderData::Term()
{
#if defined(CH_VRML_EVENTS)
delete m_pDispatcher;
m_pDispatcher = 0;
#endif
}
bool ChQvGroupRenderData::IsNodeRemovable(QvNode *pChild)
{
return IsNodeAddable( pChild);
}
bool ChQvGroupRenderData::IsNodeAddable(QvNode *pChild)
{
bool boolAddable = true;
string strType;
int theType = pChild->GetType(strType);
switch(theType)
{
case typeQvBackground:
case typeQvBaseColor:
case typeQvEnvironment:
case typeQvGroup:
case typeQvCoordinate3:
case typeQvInfo:
case typeQvFontStyle:
case typeQvMaterial:
case typeQvMaterialBinding:
case typeQvMatrixTransform:
case typeQvNormal:
case typeQvNormalBinding:
case typeQvRotation:
case typeQvScale:
case typeQvShapeHints:
case typeQvTexture2:
case typeQvTexture2Transform:
case typeQvTextureCoordinate2:
case typeQvTransform:
case typeQvTranslation:
case typeQvUnknownNode:
boolAddable = false;
break;
case typeQvCone:
case typeQvCube:
case typeQvCylinder:
case typeQvIndexedFaceSet:
case typeQvIndexedLineSet:
case typeQvLOD:
case typeQvSeparator:
case typeQvTransformSeparator:
case typeQvSwitch:
case typeQvAsciiText:
case typeQvDirectionalLight:
case typeQvOrthographicCamera:
case typeQvPerspectiveCamera:
case typeQvPointLight:
case typeQvPointSet:
case typeQvSphere:
case typeQvSpin:
case typeQvSpinGroup:
case typeQvSpotLight:
case typeQvWWWAnchor:
case typeQvWWWInline:
break;
}
return boolAddable;
}
// VRML 2.0 Event Handlers
bool ChQvGroupRenderData::OnAddChildren(ChRenderContext *pRC, ChApplet * pApplet, ChIVrmlEvent *pEventList)
{
bool boolSuccess = false;
#if defined(CH_VRML_EVENTS)
// Append a child to the group node.
ChNode* pChild = 0;
ChNodeEvent *pEvent = (ChNodeEvent *)pEventList;
pEvent->GetValue(pChild);
QvGroup *pNode = (QvGroup *)m_pNode;
if(pChild)
{
if(IsNodeAddable((QvNode*)pChild))
{
boolSuccess = true;
}
else
{
// Not allowable - allow it to be thrown it away by not using it
string strType;
((QvNode*)pChild)->GetType(strType);
TRACE1("Attempt to add_children node of type %s rejected.\n", LPCTSTR(strType) );
// Now tell the user
string strMsg;
strMsg.Format("VRML: Event add_children for child node of type %s is not permitted.\n", LPCTSTR(strType) );
((ChMazeWnd*)pRC->GetWnd())->OnError( CH_MAZE_ROUTE_ERROR_INVALID_ADD, strMsg, ChMazeWnd::traceError);
}
}
if(boolSuccess)
{
((QvNode*)pChild)->Use();
pNode->getChildren()->append((QvNode*)pChild);
// Now launch a constructtion thread, just like this was
// an inline
Instantiate( (ChMazeWnd *)(pRC->GetWnd()), (QvNode*)pChild);
// Spawn for new requests
ChQvSpawnState state((ChMazeWnd *)(pRC->GetWnd()), ((ChMazeWnd *)(pRC->GetWnd()))->GetCurrentURL());
((QvNode*)pChild)->traverse(&state);
// Set it dirty, for redraw, etc.
pRC->SetDirty();
}
#endif
return boolSuccess;
}
class MyChildRemovalIterator: public ChQvRenderBaseDataIterator
{
public:
MyChildRemovalIterator( const ChQvGroupRenderData& rbd, QvNode *pNode) :
ChQvRenderBaseDataIterator(rbd),
m_pNode(pNode)
{};
virtual int DoInstance(ChQvInstance& inst)
{
ChQvGroupInstance*pInst = (ChQvGroupInstance*)&inst;
pInst->MarkChildForRemoval(m_pNode);
return true;
};
protected:
QvNode *m_pNode;
};
bool ChQvGroupRenderData::OnRemoveChildren(ChRenderContext *pRC, ChApplet * pApplet, ChIVrmlEvent *pEventList)
{
bool boolSuccess = false;
#if defined(CH_VRML_EVENTS)
// Delete a child or children from the group node.
ChNode* pChild = 0;
ChNodeEvent *pEvent = (ChNodeEvent *)pEventList;
QvGroup *pNode = (QvGroup *)m_pNode;
int iNumToRemove = pEvent->GetCount();
//pRC->LockScene(); // Lock scene so we don't conflict with construction
for(int j = 0; j < iNumToRemove; j++)
{
pEvent->GetValue(j, pChild);
if(pChild)
{
if(IsNodeRemovable((QvNode*)pChild))
{
boolSuccess = true;
bool boolRemoved = false;
for ( int i = pNode->getNumChildren() - 1; i >= 0; i--)
{
if( pNode->getChild(i) == (QvNode*)pChild)
{
pRC->LockQv(); // Lock tree so parse and stream threads don't barf
MyChildRemovalIterator iterator(*this, (QvNode*)pChild);
iterator.Iterate();
pNode->getChildren()->remove(i);
((QvNode*)pChild)->Release(); // This is where the subtree is deleted
pRC->UnlockQv();
boolRemoved = true;
}
}
if(!boolRemoved)
{
string strMsg;
string strParent(pNode->getName().getString());
string strChild(((QvNode*)pChild)->getName().getString());
if(strParent.IsEmpty()) strParent = "<Unnamed>";
if(strChild.IsEmpty()) strChild = "<Unnamed>";
strMsg.Format("VRML: Event remove_children - node %s not a child of %s.\n",
LPCTSTR(strChild), LPCTSTR(strParent));
((ChMazeWnd*)pRC->GetWnd())->OnError( CH_MAZE_ROUTE_ERROR_NODE_NOTFOUND, strMsg, ChMazeWnd::traceError);
}
}
else
{
string strType;
((QvNode*)pChild)->GetType(strType);
TRACE1("Attempt to remove_children node of type %s rejected.\n", LPCTSTR(strType) );
// Now tell the user
string strMsg;
strMsg.Format("VRML: Event remove_children for child node of type %s is not permitted.\n", LPCTSTR(strType) );
((ChMazeWnd*)pRC->GetWnd())->OnError( CH_MAZE_ROUTE_ERROR_INVALID_REMOVE, strMsg, ChMazeWnd::traceError);
}
}
}
//pRC->UnlockScene();
#endif
return boolSuccess;
}
// End handlers
ChQvGroupRenderData* ChQvGroupRenderData::Instantiate(ChMazeWnd * pWnd, QvNode *pNewChild)
{
// Walk the list of the group's instances, instantiating the new subtree that came in
if (!m_instances.IsEmpty())
{
ChPosition pos = m_instances.GetHeadPosition();
while(pos)
{
ChQvGroupInstance *pInst = (ChQvGroupInstance *)(m_instances.GetNext(pos));
ChQvBuildState bldIt(pWnd);
bldIt.SetCurrentParent(pInst);
pInst->SetupTraversalState(bldIt);
pNewChild->traverse(&bldIt);
// Now construct them for RLab
#if (defined(CH_USE_RLAB) || defined(CH_USE_D3D))
pWnd->GetRenderContext()->StartConstruction(pInst);
#endif
}
}
return this;
}
// //////////////////////////////////////////
ChQvIFSRenderData::ChQvIFSRenderData(QvIndexedFaceSet* ifs, QvState* state)
: ChQvRenderBaseData(ifs), m_pNormals(0)
{
CheckValid(ifs, state);
if(m_boolValid) m_pNormals = new ChQvIndexedFaceSetNormals(ifs, state);
SetDirty(false);
}
ChQvIFSRenderData::~ChQvIFSRenderData()
{
delete m_pNormals;
}
void ChQvIFSRenderData::Init(QvIndexedFaceSet* ifs, QvState* state)
{
CheckValid(ifs, state);
delete m_pNormals;
m_pNormals = 0;
if(m_boolValid) m_pNormals = new ChQvIndexedFaceSetNormals(ifs, state);
SetDirty(false);
}
inline int VertCount(long *values, int num)
{
int i = 0;
while(values[i] != QV_END_FACE_INDEX) i++;
return i;
}
bool ChQvIFSRenderData::CheckValid(QvIndexedFaceSet* ifs, QvState* state)
{
/* Validate the coordinate indices of an ifs. Check for
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -