Hi Robert

I see no loss in removing more parts from the basic viewer for this demo 
code; I was just doing the minimal changes to produce a decent demo. I will try 
to simplify the demo soon.

Moving implementation details also sounds wise, are you doing this? If not 
my attempt to move the implementation is attached.

Geoff

  ----- Original Message ----- 
  From: Max Bandazian 
  To: OpenSceneGraph Submissions 
  Sent: Saturday, August 01, 2009 6:42 PM
  Subject: Re: [osg-submissions] osg::Group::removeChildren performance


  The algorithm copies things from the end of the vector into the locations of 
the elements to be deleted, and then shortens the vector by that amount. So if 
your vector is a, b, c and you want to remove 'a', first c gets copied into a's 
spot (c, b, c), then the vector is resized (c, b). I guess that would break 
Switch nodes etc.


  Normally it would be fine with me if this doesn't make it into osg, but the 
use of friends in osg::Node means that it's impossible to correctly reimplement 
osg::Group::removeChildren without changing the Node header. Maybe it could be 
added as an osg::UnorderedGroup, or the current osg::Group could become 
osg::OrderedGroup, etc.


  - Max


  On Fri, Jul 31, 2009 at 5:02 PM, Thrall, Bryan 
<[email protected]> wrote:

    Max Bandazian wrote on Friday, July 31, 2009 12:54 PM:

    >            if (_children.size() == numChildrenToRemove)
    >             {
    >                _children.clear();
    >             }
    >             else
    >             {
    >                int numThingsToCopy = std::min(numChildrenToRemove,
    >                _children.size() - numChildrenToRemove);
    >                std::copy(_children.end() - numThingsToCopy,
    _children.end(),
    >             _children.begin() + pos);
    _children.resize(_children.size() -
    > numChildrenToRemove); }
    >
    > With this change, removing the 30,000 nodes takes less than 1 second.
    It does
    > change the semantics of removing children from a group, in that the
    children
    > will be in a different order rather than just having their index
    changed. In
    > my opinion it's worth it for the performance gain.


    That sounds pretty nice, but I must be missing something, because that
    code looks like it does not change the order of the children. What's the
    down side again?

    --
    Bryan Thrall
    FlightSafety International
    [email protected]

    _______________________________________________
    osg-submissions mailing list
    [email protected]
    
http://lists.openscenegraph.org/listinfo.cgi/osg-submissions-openscenegraph.org





------------------------------------------------------------------------------


  _______________________________________________
  osg-submissions mailing list
  [email protected]
  
http://lists.openscenegraph.org/listinfo.cgi/osg-submissions-openscenegraph.org

Attachment: InertiaVisitor
Description: Binary data

#include <osgUtil/InertiaVisitor>
// included as separate file to ensure that InertiaVisitor is compiled into
// libraries.

void InertiaVisitor::apply(osg::Geode& geode) {
        osg::NodePath nodePath = getNodePath();
        unsigned int i;
        osg::Matrix totalmat; // accumulated matrix above this point

        for(i=0; i<nodePath.size()-1; ++i)
        {
                osg::Transform* transform = nodePath[i]->asTransform();
                if (transform) { // concatenate to totalmat.
                        transform->computeLocalToWorldMatrix(totalmat, this);
                }
        }
        for (unsigned int i=0; i<geode.getNumDrawables(); i++) {
                osg::Geometry *dr=dynamic_cast<osg::Geometry 
*>(geode.getDrawable(i));
                if (dr) {
                        // 200409 use ComputeInertiaTriangleFunctor to 
calculate volume, MI etc
                        osg::TriangleFunctor<ComputeInertiaTriangleFunctor> 
inert;
                        inert.setMatrix(totalmat);
                        dr->accept(inert);
                        _m+=inert.getVolume();
                        _Cx+=inert.getCx();
                        _Cy+=inert.getCy();
                        _Cz+=inert.getCz();
                        _xx+=inert.getixx();
                        _yy+=inert.getiyy();
                        _zz+=inert.getizz();
                        _zx+=inert.getizx();
                        _yx+=inert.getiyx();
                        _zy+=inert.getizy();
                        Area+=inert.getArea();
                        ntris+=inert.getntris();
                        osg::Vec2 xr=inert.getXrange();
                        if (xr.x()<xmin) xmin=xr.x();
                        if (xr.y()>xmax) xmax=xr.y();
                        osg::Vec2 yr=inert.getYrange();
                        if (yr.x()<ymin) ymin=yr.x();
                        if (yr.y()>ymax) ymax=yr.y();
                        osg::Vec2 zr=inert.getZrange();
                        if (zr.x()<zmin) zmin=zr.x();
                        if (zr.y()>zmax) zmax=zr.y();
                }
        }
        finish(); // construct the actual Inertia from the partial sums.
}
/**********************************************************************
from Reference 1.
Add the contribution of a triangle to the mass properties.
Call this method for each one of the mesh's triangles.  
The order of vertices must be such that their determinant is positive
when the origin lies on the inner side of this facet's plane.
**********************************************************************/
void ComputeInertiaTriangleFunctor::AddTriangleContribution(const osg::Vec3 
v1,const osg::Vec3 v2,const osg::Vec3 v3)
{
        double x1=v1.x(), y1=v1.y(), z1=v1.z();    // Triangle's vertex 1
        double x2=v2.x(), y2=v2.y(), z2=v2.z();    // Triangle's vertex 2
        double x3=v3.x(), y3=v3.y(), z3=v3.z();    // Triangle's vertex 3
        // Signed volume of this tetrahedron.
        double v = x1*y2*z3 + y1*z2*x3 + x2*y3*z1 -
                          (x3*y2*z1 + x2*y1*z3 + y3*z2*x1);
        
        // Contribution to the mass
        _m += v;
        
        // contribution to area; half base*height
        area+=((v2-v1)^(v3-v2)).length()/2.0;

        // Contribution to the centroid
        double x4 = x1 + x2 + x3;           _Cx += (v * x4);
        double y4 = y1 + y2 + y3;           _Cy += (v * y4);
        double z4 = z1 + z2 + z3;           _Cz += (v * z4);

        // Contribution to moment of inertia monomials
        _xx += v * (x1*x1 + x2*x2 + x3*x3 + x4*x4);
        _yy += v * (y1*y1 + y2*y2 + y3*y3 + y4*y4);
        _zz += v * (z1*z1 + z2*z2 + z3*z3 + z4*z4);
        _yx += v * (y1*x1 + y2*x2 + y3*x3 + y4*x4);
        _zx += v * (z1*x1 + z2*x2 + z3*x3 + z4*x4);
        _zy += v * (z1*y1 + z2*y2 + z3*y3 + z4*y4);
   // NB x4*x4 = x1*x1+x1*x2+x1*x3 + x2*x1 + x2*x2 + x2*x3+x3*x1+x3*x2+x3*x3....

   ntris++;
   // get range of coordinates used in triangles
        if (x1<xmin) xmin=x1;
        if (x2<xmin) xmin=x2;
        if (x3<xmin) xmin=x3;
        if (x1>xmax) xmax=x1;
        if (x2>xmax) xmax=x2;
        if (x3>xmax) xmax=x3;
        // also Y coordinate
        if (y1<ymin) ymin=y1;
        if (y2<ymin) ymin=y2;
        if (y3<ymin) ymin=y3;
        if (y1>ymax) ymax=y1;
        if (y2>ymax) ymax=y2;
        if (y3>ymax) ymax=y3;
        // and Z coordinate
        if (z1<zmin) zmin=z1;
        if (z2<zmin) zmin=z2;
        if (z3<zmin) zmin=z3;
        if (z1>zmax) zmax=z1;
        if (z2>zmax) zmax=z2;
        if (z3>zmax) zmax=z3;
           
}
void ComputeInertiaTriangleFunctor::zeroProperties() { // zero inertia 
component sums.
        // automatically zeroed at creation time, call if reused.
        _m=0;                              // Mass (times 6 to save divisions)
        _Cx=0; _Cy=0; _Cz=0;                   // Centroid
        _xx=0; _yy=0; _zz=0; _yx=0; _zx=0; _zy=0;    // Moment of inertia tensor
        ntris = 0; // number of triangles modelling the drawable
        area=0;
        xmin=1.e32,xmax=-1.e32; // initialise range of coordiantes
        ymin=1.e32,ymax=-1.e32;
        zmin=1.e32,zmax=-1.e32;
}

/**********************************************************************
>From ref 1 with minor improvements to allow reuse.
This method is called to obtain the results.
code from http://jgt.akpeters.com/papers/Kallay06/Moment_of_Inertia.cpp
As published method GetResults modifies the internal data; calling it again 
would return 
incorrect results. Modified to prevent this by using a local variable.
After calling this routine the results are stored in _Ixx etc
**********************************************************************/
void InertiaVisitor::GetResults( // returns m, Cx etc
        double & m,                               // Total mass
        double & Cx,  double & Cy,  double & Cz,  // Centroid
        double & Ixx, double & Iyy, double & Izz, // Moment of inertia       
                                                                                
          // diagonal entries
        double & Iyx, double & Izx, double & Izy) // Moment of inertia 
                                                                                
          // mixed entries
const { // NB const ensures that the aprtial sums are not damaged.
        // Centroid.
        // can now be called multiple times as does not modify routine.
        if (_m!=0) { // The case _m = 0 means zero volume.
        double r = 1.0 / (4 * _m);
        Cx = _Cx * r;
        Cy = _Cy * r;
        Cz = _Cz * r;

        // Mass
        m = _m / 6;

        // Moment of inertia about the centroid.
        r = 1.0 / 120;
        Iyx = _yx * r - m * Cy*Cx;
        Izx = _zx * r - m * Cz*Cx;
        Izy = _zy * r - m * Cz*Cy;
// 110709 protect internal sums
        double _xxt = _xx * r - m * Cx*Cx;
        double _yyt = _yy * r - m * Cy*Cy;
        double _zzt = _zz * r - m * Cz*Cz;
        Ixx = _yyt + _zzt;
        Iyy = _zzt + _xxt;
        Izz = _xxt + _yyt;
        }
}

void InertiaVisitor::zeroInertiaTensor() { // zero inertia COMPONENTS at start 
of write
        // automatically zeroed at creation time, call if reused.
        _m=0;                              // Mass
        _Cx=0; _Cy=0; _Cz=0;                   // Centroid
        _xx=0; _yy=0; _zz=0; _yx=0; _zx=0; _zy=0;    // Moment of inertia tensor
        xmin=1.e32,xmax=-1.e32; // rezero range of coordiantes
        ymin=1.e32,ymax=-1.e32;
        zmin=1.e32,zmax=-1.e32;
        Area=0;
        ntris = 0; // number of triangles modelling the object
}
_______________________________________________
osg-submissions mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-submissions-openscenegraph.org

Reply via email to