void BulletNifLoader::handleNode(const std::string& fileName, const Nif::Node *node, int flags, bool isCollisionNode, bool isAnimated, bool autogenerated, bool avoid) { // Accumulate the flags from all the child nodes. This works for all // the flags we currently use, at least. flags |= node->flags; if (!node->controller.empty() && node->controller->recType == Nif::RC_NiKeyframeController && (node->controller->flags & Nif::NiNode::ControllerFlag_Active)) isAnimated = true; isCollisionNode = isCollisionNode || (node->recType == Nif::RC_RootCollisionNode); // Don't collide with AvoidNode shapes avoid = avoid || (node->recType == Nif::RC_AvoidNode); // We encountered a RootCollisionNode inside autogenerated mesh. It is not right. if (node->recType == Nif::RC_RootCollisionNode && autogenerated) Log(Debug::Info) << "Found RootCollisionNode attached to non-root node in " << fileName << ". Treat it as a common NiTriShape."; // Check for extra data Nif::Extra const *e = node; while (!e->extra.empty()) { // Get the next extra data in the list e = e->extra.getPtr(); assert(e != nullptr); if (e->recType == Nif::RC_NiStringExtraData) { // String markers may contain important information // affecting the entire subtree of this node Nif::NiStringExtraData *sd = (Nif::NiStringExtraData*)e; if (Misc::StringUtils::ciCompareLen(sd->string, "NC", 2) == 0) { // No collision. Use an internal flag setting to mark this. flags |= 0x800; } else if (sd->string == "MRK" && autogenerated) { // Marker can still have collision if the model explicitely specifies it via a RootCollisionNode. return; } } } if (isCollisionNode) { // NOTE: a trishape with hasBounds=true, but no BBoxCollision flag should NOT go through handleNiTriShape! // It must be ignored completely. // (occurs in tr_ex_imp_wall_arch_04.nif) if(!node->hasBounds && node->recType == Nif::RC_NiTriShape) { handleNiTriShape(static_cast<const Nif::NiTriShape*>(node), flags, getWorldTransform(node), isAnimated, avoid); } } // For NiNodes, loop through children const Nif::NiNode *ninode = dynamic_cast<const Nif::NiNode*>(node); if(ninode) { const Nif::NodeList &list = ninode->children; for(size_t i = 0;i < list.length();i++) { if(!list[i].empty()) handleNode(fileName, list[i].getPtr(), flags, isCollisionNode, isAnimated, autogenerated, avoid); } } }
void ManualBulletShapeLoader::handleNode(const Nif::Node *node, int flags, bool hasCollisionNode, bool isCollisionNode, bool raycastingOnly) { // Accumulate the flags from all the child nodes. This works for all // the flags we currently use, at least. flags |= node->flags; isCollisionNode = isCollisionNode || (node->recType == Nif::RC_RootCollisionNode); // Marker objects: no collision /// \todo don't do this in the editor if (node->name.find("marker") != std::string::npos) { flags |= 0x800; cShape->mIgnore = true; } // Check for extra data Nif::Extra const *e = node; while (!e->extra.empty()) { // Get the next extra data in the list e = e->extra.getPtr(); assert(e != NULL); if (e->recType == Nif::RC_NiStringExtraData) { // String markers may contain important information // affecting the entire subtree of this node Nif::NiStringExtraData *sd = (Nif::NiStringExtraData*)e; // not sure what the difference between NCO and NCC is, or if there even is one if (sd->string == "NCO" || sd->string == "NCC") { // No collision. Use an internal flag setting to mark this. flags |= 0x800; } else if (sd->string == "MRK" && !raycastingOnly) // Marker objects. These are only visible in the // editor. Until and unless we add an editor component to // the engine, just skip this entire node. return; } } if(!hasCollisionNode || isCollisionNode) { if(node->hasBounds) { cShape->boxTranslation = node->boundPos; cShape->boxRotation = node->boundRot; mBoundingBox = new btBoxShape(getbtVector(node->boundXYZ)); } if(node->recType == Nif::RC_NiTriShape) { cShape->mCollide = !(flags&0x800); handleNiTriShape(static_cast<const Nif::NiTriShape*>(node), flags, node->getWorldTransform(), raycastingOnly); } } // For NiNodes, loop through children const Nif::NiNode *ninode = dynamic_cast<const Nif::NiNode*>(node); if(ninode) { const Nif::NodeList &list = ninode->children; for(size_t i = 0;i < list.length();i++) { if(!list[i].empty()) handleNode(list[i].getPtr(), flags, hasCollisionNode, isCollisionNode, raycastingOnly); } } }