zoukankan      html  css  js  c++  java
  • osg::Group源码

    osg::Group源码

    /* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
     *
     * This library is open source and may be redistributed and/or modified under
     * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
     * (at your option) any later version.  The full license is in LICENSE file
     * included with this distribution, and on the openscenegraph.org website.
     *
     * This library is distributed in the hope that it will be useful,
     * but WITHOUT ANY WARRANTY; without even the implied warranty of
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     * OpenSceneGraph Public License for more details.
    */
    
    #include <osg/Group>
    #include <osg/BoundingBox>
    #include <osg/Transform>
    #include <osg/OccluderNode>
    #include <osg/Geometry>
    #include <osg/Notify>
    
    #include <stdio.h>
    #include <math.h>
    
    #include <algorithm>
    
    using namespace osg;
    
    Group::Group()
    {
    }
    
    Group::Group(const Group& group,const CopyOp& copyop):
        Node(group,copyop)
    {
        for(NodeList::const_iterator itr=group._children.begin();
            itr!=group._children.end();
            ++itr)
        {
            Node* child = copyop(itr->get());
            if (child) addChild(child);
        }
    }
    
    Group::~Group()
    {
        // remove reference to this from children's parent lists.
        for(NodeList::iterator itr=_children.begin();
            itr!=_children.end();
            ++itr)
        {
            (*itr)->removeParent(this);
        }
    
    }
    
    
    void Group::traverse(NodeVisitor& nv)
    {
        for(NodeList::iterator itr=_children.begin();
            itr!=_children.end();
            ++itr)
        {
            (*itr)->accept(nv);
        }
    }
    
    
    bool Group::addChild( Node *child )
    {
        return Group::insertChild( _children.size(), child );
    }
    
    bool Group::insertChild( unsigned int index, Node *child )
    {
        if (!child) return false;
    
    #if ENSURE_CHILD_IS_UNIQUE
        if (containsNode(child))
        {
            OSG_WARN<<"Adding non unique child to osg::Group, ignoring call"<<std::endl;
            return false;
        }
    #endif
    
        // handle deprecated geometry configurations by calling fixDeprecatedData().
        osg::Geometry* geometry = child->asGeometry();
        if (geometry && geometry->containsDeprecatedData()) geometry->fixDeprecatedData();
    
    
        // note ref_ptr<> automatically handles incrementing child's reference count.
        if (index >= _children.size())
        {
            index = _children.size();      // set correct index value to be passed to the "childInserted" method
            _children.push_back(child);
        }
        else
        {
            _children.insert(_children.begin()+index, child);
        }
    
        // register as parent of child.
        child->addParent(this);
    
        // tell any subclasses that a child has been inserted so that they can update themselves.
        childInserted(index);
    
        dirtyBound();
    
        // could now require app traversal thanks to the new subgraph,
        // so need to check and update if required.
        if (child->getNumChildrenRequiringUpdateTraversal()>0 ||
            child->getUpdateCallback())
        {
            setNumChildrenRequiringUpdateTraversal(
                getNumChildrenRequiringUpdateTraversal()+1
                );
        }
    
        // could now require app traversal thanks to the new subgraph,
        // so need to check and update if required.
        if (child->getNumChildrenRequiringEventTraversal()>0 ||
            child->getEventCallback())
        {
            setNumChildrenRequiringEventTraversal(
                getNumChildrenRequiringEventTraversal()+1
                );
        }
    
        // could now require disabling of culling thanks to the new subgraph,
        // so need to check and update if required.
        if (child->getNumChildrenWithCullingDisabled()>0 ||
            !child->getCullingActive())
        {
            setNumChildrenWithCullingDisabled(
                getNumChildrenWithCullingDisabled()+1
                );
        }
    
        if (child->getNumChildrenWithOccluderNodes()>0 ||
            dynamic_cast<osg::OccluderNode*>(child))
        {
            setNumChildrenWithOccluderNodes(
                getNumChildrenWithOccluderNodes()+1
                );
        }
    
        return true;
    }
    
    unsigned int Group::getNumChildren() const
    {
        return static_cast<unsigned int>(_children.size());
    }
    
    
    bool Group::removeChild( Node *child )
    {
        unsigned int pos = getChildIndex(child);
        if (pos<_children.size()) return removeChildren(pos,1);
        else return false;
    }
    
    
    bool Group::removeChildren(unsigned int pos,unsigned int numChildrenToRemove)
    {
        if (pos<_children.size() && numChildrenToRemove>0)
        {
            unsigned int endOfRemoveRange = pos+numChildrenToRemove;
            if (endOfRemoveRange>_children.size())
            {
                OSG_DEBUG<<"Warning: Group::removeChild(i,numChildrenToRemove) has been passed an excessive number"<<std::endl;
                OSG_DEBUG<<"         of chilren to remove, trimming just to end of child list."<<std::endl;
                endOfRemoveRange=_children.size();
            }
    
            unsigned int updateCallbackRemoved = 0;
            unsigned int eventCallbackRemoved = 0;
            unsigned int numChildrenWithCullingDisabledRemoved = 0;
            unsigned int numChildrenWithOccludersRemoved = 0;
    
            for(unsigned i=pos;i<endOfRemoveRange;++i)
            {
                osg::Node* child = _children[i].get();
                // remove this Geode from the child parent list.
                child->removeParent(this);
    
                if (child->getNumChildrenRequiringUpdateTraversal()>0 || child->getUpdateCallback()) ++updateCallbackRemoved;
    
                if (child->getNumChildrenRequiringEventTraversal()>0 || child->getEventCallback()) ++eventCallbackRemoved;
    
                if (child->getNumChildrenWithCullingDisabled()>0 || !child->getCullingActive()) ++numChildrenWithCullingDisabledRemoved;
    
                if (child->getNumChildrenWithOccluderNodes()>0 || dynamic_cast<osg::OccluderNode*>(child)) ++numChildrenWithOccludersRemoved;
    
            }
    
            childRemoved(pos,endOfRemoveRange-pos);
    
            _children.erase(_children.begin()+pos,_children.begin()+endOfRemoveRange);
    
            if (updateCallbackRemoved)
            {
                setNumChildrenRequiringUpdateTraversal(getNumChildrenRequiringUpdateTraversal()-updateCallbackRemoved);
            }
    
            if (eventCallbackRemoved)
            {
                setNumChildrenRequiringEventTraversal(getNumChildrenRequiringEventTraversal()-eventCallbackRemoved);
            }
    
            if (numChildrenWithCullingDisabledRemoved)
            {
                setNumChildrenWithCullingDisabled(getNumChildrenWithCullingDisabled()-numChildrenWithCullingDisabledRemoved);
            }
    
            if (numChildrenWithOccludersRemoved)
            {
                setNumChildrenWithOccluderNodes(getNumChildrenWithOccluderNodes()-numChildrenWithOccludersRemoved);
            }
    
            dirtyBound();
    
            return true;
        }
        else return false;
    }
    
    
    bool Group::replaceChild( Node *origNode, Node *newNode )
    {
        if (newNode==NULL || origNode==newNode) return false;
    
        unsigned int pos = getChildIndex(origNode);
        if (pos<_children.size())
        {
            return setChild(pos,newNode);
        }
        return false;
    }
    
    
    bool Group::setChild( unsigned  int i, Node* newNode )
    {
        if (i<_children.size() && newNode)
        {
    
            ref_ptr<Node> origNode = _children[i];
    
            // first remove for origNode's parent list.
            origNode->removeParent(this);
    
            // note ref_ptr<> automatically handles decrementing origNode's reference count,
            // and inccrementing newNode's reference count.
            _children[i] = newNode;
    
            // register as parent of child.
            newNode->addParent(this);
    
            dirtyBound();
    
    
            // could now require update traversal thanks to the new subgraph,
            // so need to check and update if required.
            int delta_numChildrenRequiringUpdateTraversal = 0;
            if (origNode->getNumChildrenRequiringUpdateTraversal()>0 ||
                origNode->getUpdateCallback())
            {
                --delta_numChildrenRequiringUpdateTraversal;
            }
            if (newNode->getNumChildrenRequiringUpdateTraversal()>0 ||
                newNode->getUpdateCallback())
            {
                ++delta_numChildrenRequiringUpdateTraversal;
            }
    
            if (delta_numChildrenRequiringUpdateTraversal!=0)
            {
                setNumChildrenRequiringUpdateTraversal(
                    getNumChildrenRequiringUpdateTraversal()+delta_numChildrenRequiringUpdateTraversal
                    );
            }
    
            // could now require event traversal thanks to the new subgraph,
            // so need to check and Event if required.
            int delta_numChildrenRequiringEventTraversal = 0;
            if (origNode->getNumChildrenRequiringEventTraversal()>0 ||
                origNode->getEventCallback())
            {
                --delta_numChildrenRequiringEventTraversal;
            }
            if (newNode->getNumChildrenRequiringEventTraversal()>0 ||
                newNode->getEventCallback())
            {
                ++delta_numChildrenRequiringEventTraversal;
            }
    
            if (delta_numChildrenRequiringEventTraversal!=0)
            {
                setNumChildrenRequiringEventTraversal(
                    getNumChildrenRequiringEventTraversal()+delta_numChildrenRequiringEventTraversal
                    );
            }
    
            // could now require disabling of culling thanks to the new subgraph,
            // so need to check and update if required.
            int delta_numChildrenWithCullingDisabled = 0;
            if (origNode->getNumChildrenWithCullingDisabled()>0 ||
                !origNode->getCullingActive())
            {
                --delta_numChildrenWithCullingDisabled;
            }
            if (newNode->getNumChildrenWithCullingDisabled()>0 ||
                !newNode->getCullingActive())
            {
                ++delta_numChildrenWithCullingDisabled;
            }
    
            if (delta_numChildrenWithCullingDisabled!=0)
            {
                setNumChildrenWithCullingDisabled(
                    getNumChildrenWithCullingDisabled()+delta_numChildrenWithCullingDisabled
                    );
            }
    
            // could now require disabling of culling thanks to the new subgraph,
            // so need to check and update if required.
            int delta_numChildrenWithOccluderNodes = 0;
            if (origNode->getNumChildrenWithOccluderNodes()>0 ||
                dynamic_cast<osg::OccluderNode*>(origNode.get()))
            {
                --delta_numChildrenWithOccluderNodes;
            }
            if (newNode->getNumChildrenWithOccluderNodes()>0 ||
                dynamic_cast<osg::OccluderNode*>(newNode))
            {
                ++delta_numChildrenWithOccluderNodes;
            }
    
            if (delta_numChildrenWithOccluderNodes!=0)
            {
                setNumChildrenWithOccluderNodes(
                    getNumChildrenWithOccluderNodes()+delta_numChildrenWithOccluderNodes
                    );
            }
    
            return true;
        }
        else return false;
    
    }
    
    BoundingSphere Group::computeBound() const
    {
        BoundingSphere bsphere;
        if (_children.empty())
        {
            return bsphere;
        }
    
        // note, special handling of the case when a child is an Transform,
        // such that only Transforms which are relative to their parents coordinates frame (i.e this group)
        // are handled, Transform relative to and absolute reference frame are ignored.
    
        BoundingBox bb;
        bb.init();
        NodeList::const_iterator itr;
        for(itr=_children.begin();
            itr!=_children.end();
            ++itr)
        {
            osg::Node* child = itr->get();
            const osg::Transform* transform = child->asTransform();
            if (!transform || transform->getReferenceFrame()==osg::Transform::RELATIVE_RF)
            {
                osg::Drawable* drawable = child->asDrawable();
                if (drawable)
                {
                    bb.expandBy(drawable->getBoundingBox());
                }
                else
                {
                    const osg::BoundingSphere& bs = child->getBound();
                    bb.expandBy(bs);
                }
            }
        }
    
        if (!bb.valid())
        {
            return bsphere;
        }
    
        bsphere._center = bb.center();
        bsphere._radius = 0.0f;
        for(itr=_children.begin();
            itr!=_children.end();
            ++itr)
        {
            osg::Node* child = itr->get();
            const osg::Transform* transform = child->asTransform();
            if (!transform || transform->getReferenceFrame()==osg::Transform::RELATIVE_RF)
            {
                const BoundingSphere& bs = child->getBound();
                bsphere.expandRadiusBy(bs);
            }
        }
    
        return bsphere;
    }
    
    void Group::setThreadSafeRefUnref(bool threadSafe)
    {
        Node::setThreadSafeRefUnref(threadSafe);
    
        for(NodeList::const_iterator itr=_children.begin();
            itr!=_children.end();
            ++itr)
        {
            (*itr)->setThreadSafeRefUnref(threadSafe);
        }
    }
    
    void Group::resizeGLObjectBuffers(unsigned int maxSize)
    {
        Node::resizeGLObjectBuffers(maxSize);
    
        for(NodeList::const_iterator itr=_children.begin();
            itr!=_children.end();
            ++itr)
        {
            (*itr)->resizeGLObjectBuffers(maxSize);
        }
    }
    
    void Group::releaseGLObjects(osg::State* state) const
    {
        Node::releaseGLObjects(state);
    
        for(NodeList::const_iterator itr=_children.begin();
            itr!=_children.end();
            ++itr)
        {
            (*itr)->releaseGLObjects(state);
        }
    }
  • 相关阅读:
    iOS9 UITableViewCell separatorInset设置为0分割线还是没有顶到头的问题
    facebook登录(集成FBSDKLoginKit) result的isCancelled总是YES token为nil
    Mac OS X 在Finder新建文本文件
    Xcode8 Could not build Objective-C module 'FBSDKCoreKit'
    Multiple methods named 'status' found with mismatched result, parameter type or attributes
    iOS 10 UserNotifications 框架解析
    WKWebView无法(通过URL schemes)跳转到其他App
    WKWebView不显示提示框(Swift)
    Redis 3.2.1集群搭建
    高吞吐量的分布式发布订阅消息系统Kafka-- 管理工具 Kafka Manager
  • 原文地址:https://www.cnblogs.com/herd/p/11927767.html
Copyright © 2011-2022 走看看