bool BodyLoaderImpl::extractShapeNodeTraverse (VrmlNode* node, const Affine3& T, const function<bool(VrmlShape* shapeNode, const Affine3& T)>& callback) { bool doContinue = true; if(node->isCategoryOf(PROTO_INSTANCE_NODE)){ VrmlProtoInstance* protoInstance = static_cast<VrmlProtoInstance*>(node); if(protoInstance->actualNode){ doContinue = extractShapeNodeTraverse(protoInstance->actualNode.get(), T, callback); } } else if(node->isCategoryOf(GROUPING_NODE)) { VrmlGroup* groupNode = static_cast<VrmlGroup*>(node); Affine3 T2; VrmlTransform* transformNode = dynamic_cast<VrmlTransform*>(groupNode); if(transformNode){ T2 = T * transformNode->toAffine3d(); } VrmlSwitch* switchNode = dynamic_cast<VrmlSwitch*>(node); if(switchNode){ int whichChoice = switchNode->whichChoice; if(whichChoice >= 0 && whichChoice < switchNode->countChildren()){ extractShapeNodeTraverse(switchNode->getChild(whichChoice), (transformNode ? T2 : T), callback); } } else { for(int i=0; i < groupNode->countChildren(); ++i){ if(!extractShapeNodeTraverse(groupNode->getChild(i), (transformNode ? T2 : T), callback)){ doContinue = false; break; } } } } else if(node->isCategoryOf(SHAPE_NODE)) { doContinue = callback(static_cast<VrmlShape*>(node), T); } return doContinue; }
void ModelNodeSetImpl::extractChildNodes (JointNodeSetPtr jointNodeSet, MFNode& childNodes, const ProtoIdSet acceptableProtoIds, const Matrix44& T) { for(size_t i = 0; i < childNodes.size(); i++){ VrmlNode* childNode = childNodes[i].get(); const Matrix44* pT; if(childNode->isCategoryOf(GROUPING_NODE)){ VrmlGroup* groupNode = static_cast<VrmlGroup*>(childNode); VrmlTransform* transformNode = dynamic_cast<VrmlTransform*>(groupNode); Matrix44 T2; if( transformNode ){ Matrix44 Tlocal; calcTransformMatrix(transformNode, Tlocal); T2 = T * Tlocal; pT = &T2; } else { pT = &T; } extractChildNodes(jointNodeSet, groupNode->getChildren(), acceptableProtoIds, *pT); } else if(childNode->isCategoryOf(LIGHT_NODE)){ jointNodeSet->lightNodes.push_back(std::make_pair(T,childNode)); } else if(childNode->isCategoryOf(PROTO_INSTANCE_NODE)){ VrmlProtoInstance* protoInstance = static_cast<VrmlProtoInstance*>(childNode); int id = PROTO_UNDEFINED; bool doTraverseChildren = false; ProtoIdSet acceptableChildProtoIds(acceptableProtoIds); const string& protoName = protoInstance->proto->protoName; ProtoNameToInfoMap::iterator p = protoNameToInfoMap.find(protoName); if(p == protoNameToInfoMap.end()){ doTraverseChildren = true; } else { id = p->second.id; if(!acceptableProtoIds.test(id)){ throw ModelNodeSet::Exception(protoName + " node is not in a correct place."); } } messageIndent += 2; switch(id){ case PROTO_JOINT: if(T != Matrix44::Identity()) throw ModelNodeSet::Exception(protoName + " node is not in a correct place."); jointNodeSet->childJointNodeSets.push_back(addJointNodeSet(protoInstance)); break; case PROTO_SENSOR: if(T != Matrix44::Identity()) throw ModelNodeSet::Exception(protoName + " node is not in a correct place."); jointNodeSet->sensorNodes.push_back(protoInstance); putMessage(protoName + protoInstance->defName); break; case PROTO_HARDWARECOMPONENT: if(T != Matrix44::Identity()) throw ModelNodeSet::Exception(protoName + " node is not in a correct place."); jointNodeSet->hwcNodes.push_back(protoInstance); putMessage(protoName + protoInstance->defName); break; case PROTO_SEGMENT: { jointNodeSet->segmentNodes.push_back(protoInstance); jointNodeSet->transforms.push_back(T); putMessage(string("Segment node ") + protoInstance->defName); doTraverseChildren = true; acceptableChildProtoIds.reset(); acceptableChildProtoIds.set(PROTO_SENSOR); } break; default: break; } if(doTraverseChildren){ if (protoInstance->fields.count("children")){ MFNode& childNodes = protoInstance->fields["children"].mfNode(); extractChildNodes(jointNodeSet, childNodes, acceptableChildProtoIds, T); } } messageIndent -= 2; } } }
/*! @if jp Shape ノード探索のための再帰関数 node以下のシーングラフをたどり、ShapeInfoを生成していく。 生成したShapeInfoはshapes_に追加する。 shapes_に追加した位置(index)を io_shapeIndicesに追加する。 io_shapeIndices は、BodyInfo構築時は LinkInfoのshapeIndices になり、 SceneInfo 構築時は SceneInfo のshapeIndicesになる。 @endif */ void ShapeSetInfo_impl::traverseShapeNodes (VrmlNode* node, const Matrix44& T, TransformedShapeIndexSequence& io_shapeIndices, DblArray12Sequence& inlinedShapeM, const SFString* url) { static int inline_count=0; SFString url_ = *url; if(node->isCategoryOf(PROTO_INSTANCE_NODE)){ VrmlProtoInstance* protoInstance = static_cast<VrmlProtoInstance*>(node); if(protoInstance->actualNode){ traverseShapeNodes(protoInstance->actualNode.get(), T, io_shapeIndices, inlinedShapeM, url); } } else if(node->isCategoryOf(GROUPING_NODE)) { VrmlGroup* groupNode = static_cast<VrmlGroup*>(node); VrmlTransform* transformNode = dynamic_cast<VrmlTransform*>(groupNode); VrmlInline* inlineNode = NULL; inlineNode = dynamic_cast<VrmlInline*>(groupNode); const Matrix44* pT; if(inlineNode){ if(!inline_count){ int inlinedShapeMIndex = inlinedShapeM.length(); inlinedShapeM.length(inlinedShapeMIndex+1); int p = 0; for(int row=0; row < 3; ++row){ for(int col=0; col < 4; ++col){ inlinedShapeM[inlinedShapeMIndex][p++] = T(row, col); } } url_ = inlineNode->urls[0]; } inline_count++; for( MFString::iterator ite = inlineNode->urls.begin(); ite != inlineNode->urls.end(); ++ite ){ string filename(deleteURLScheme(*ite)); struct stat statbuff; time_t mtime = 0; if( stat( filename.c_str(), &statbuff ) == 0 ){ mtime = statbuff.st_mtime; } fileTimeMap.insert(make_pair(filename, mtime)); } } Matrix44 T2; if( transformNode ){ Matrix44 Tlocal; calcTransformMatrix(transformNode, Tlocal); T2 = T * Tlocal; pT = &T2; } else { pT = &T; } VrmlSwitch* switchNode = dynamic_cast<VrmlSwitch*>(node); if(switchNode){ int whichChoice = switchNode->whichChoice; if( whichChoice >= 0 && whichChoice < switchNode->countChildren() ) traverseShapeNodes(switchNode->getChild(whichChoice), *pT, io_shapeIndices, inlinedShapeM, &url_); }else{ for(int i=0; i < groupNode->countChildren(); ++i){ traverseShapeNodes(groupNode->getChild(i), *pT, io_shapeIndices, inlinedShapeM, &url_); } } if(inlineNode) inline_count--; } else if(node->isCategoryOf(SHAPE_NODE)) { VrmlShape* shapeNode = static_cast<VrmlShape*>(node); short shapeInfoIndex; ShapeNodeToShapeInfoIndexMap::iterator p = shapeInfoIndexMap.find(shapeNode); if(p != shapeInfoIndexMap.end()){ shapeInfoIndex = p->second; } else { shapeInfoIndex = createShapeInfo(shapeNode, url); } if(shapeInfoIndex >= 0){ long length = io_shapeIndices.length(); io_shapeIndices.length(length + 1); TransformedShapeIndex& tsi = io_shapeIndices[length]; tsi.shapeIndex = shapeInfoIndex; int p = 0; for(int row=0; row < 3; ++row){ for(int col=0; col < 4; ++col){ tsi.transformMatrix[p++] = T(row, col); } } if(inline_count) tsi.inlinedShapeTransformMatrixIndex=inlinedShapeM.length()-1; else tsi.inlinedShapeTransformMatrixIndex=-1; } } }