Exemple #1
0
    double Frustum::getAngleBetween(const osg::Vec3 &a, const osg::Vec3 &b) {

        float dot = a * b;
        float mag = a.length() * b.length();
        
        double angle = acos(dot/mag);
        
		if (osg::isNaN(angle)) 
            return 0;
        else
            return angle;
    }
Exemple #2
0
float ConeSector::operator() (const osg::Vec3& eyeLocal) const
{
    float dotproduct = eyeLocal*_axis;
    float length = eyeLocal.length();
    if (dotproduct>_cosAngle*length) return 1.0f; // fully in sector
    if (dotproduct<_cosAngleFade*length) return 0.0f; // out of sector
    return (dotproduct-_cosAngleFade*length)/((_cosAngle-_cosAngleFade)*length);
}
osg::Vec3 ShadowTechnique::computeOrthogonalVector(const osg::Vec3& direction) const
{
    float length = direction.length();
    osg::Vec3 orthogonalVector = direction ^ osg::Vec3(0.0f, 1.0f, 0.0f);
    if (orthogonalVector.normalize()<length*0.5f)
    {
        orthogonalVector = direction ^ osg::Vec3(0.0f, 0.0f, 1.0f);
        orthogonalVector.normalize();
    }
    return orthogonalVector;
}
        void set(const osg::Vec3d& start, osg::Vec3d& end, float ratio=FLT_MAX)
        {
            _hit=false;
            _index = 0;
            _ratio = ratio;

            _s = start;
            _d = end - start;
            _length = _d.length();
            _d /= _length;
        }
Exemple #5
0
void GliderManipulator::computePosition(const osg::Vec3& eye,const osg::Vec3& lv,const osg::Vec3& up)
{
    osg::Vec3 f(lv);
    f.normalize();
    osg::Vec3 s(f^up);
    s.normalize();
    osg::Vec3 u(s^f);
    u.normalize();
    
    osg::Matrixd rotation_matrix(s[0],     u[0],     -f[0],     0.0f,
                                s[1],     u[1],     -f[1],     0.0f,
                                s[2],     u[2],     -f[2],     0.0f,
                                0.0f,     0.0f,     0.0f,      1.0f);
                   
    _eye = eye;
    _distance = lv.length();
    _rotation = rotation_matrix.getRotate().inverse();
}
    osg::ref_ptr<osg::Geode> createRefGeometry( osg::Vec3 p, double len )
    {
        osg::ref_ptr<osg::Geode> geode = new osg::Geode;  

        if ( _drawingFlag==1 )
        {
            osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry;
            osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array;

            // Joint
            vertices->push_back( osg::Vec3(-len, 0.0, 0.0) );
            vertices->push_back( osg::Vec3( len, 0.0, 0.0) );
            vertices->push_back( osg::Vec3( 0.0,-len, 0.0) );
            vertices->push_back( osg::Vec3( 0.0, len, 0.0) );
            vertices->push_back( osg::Vec3( 0.0, 0.0,-len) );
            vertices->push_back( osg::Vec3( 0.0, 0.0, len) );

            // Bone
            vertices->push_back( osg::Vec3( 0.0, 0.0, 0.0) );
            vertices->push_back( p );

            geometry->addPrimitiveSet( new osg::DrawArrays(osg::PrimitiveSet::LINES, 0, 8) );
            geometry->setVertexArray( vertices.get() );

            geode->addDrawable( geometry.get() );
        }
        else if ( _drawingFlag==2 )
        {
            osg::Quat quat;
            osg::ref_ptr<osg::Box> box = new osg::Box( p*0.5, p.length(), len, len );
            quat.makeRotate( osg::Vec3(1.0,0.0,0.0), p );
            box->setRotation( quat );

            geode->addDrawable( new osg::ShapeDrawable(box.get()) );
        }
        
        return geode;
    }
void ConstraintsNode::applyConstrainedTranslation(osg::Vec3 v)
{
    osg::Vec3 localPos = this->getTranslation();
    osg::ref_ptr<ReferencedNode> hitNode;
    ReferencedNode *testNode;

    // with really big velocities (or small enclosures), and if the surface
    // doesn't damp the velocity, it's possible to get see an infinite recursion
    // occur. So, we keep a recursionCounter, and stop prevent this occurrence:
    if (++recursionCounter > 10) return;

    /*
    std::cout << std::endl << "checking for collisions" << std::endl;
    std::cout << "start =  " << localPos.x()<<","<<localPos.y()<<","<<localPos.z() << std::endl;
    std::cout << "v =      " << v.x()<<","<<v.y()<<","<<v.z() << std::endl;
    */

    osg::ref_ptr<ReferencedNode> targetNode = dynamic_cast<ReferencedNode*>(_target->s_thing);

    if (targetNode.valid())
    {
        // get current position (including offset from previous bounces)
        osg::Matrix thisMatrix = osg::computeLocalToWorld(this->currentNodePath);
        osg::Vec3 worldPos = thisMatrix.getTrans();

        // set up intersector:
        osg::ref_ptr<osgUtil::LineSegmentIntersector> intersector = new osgUtil::LineSegmentIntersector(worldPos, worldPos + v);
        osgUtil::IntersectionVisitor iv(intersector.get());

        // apply intersector:
        targetNode->accept(iv);

        if (intersector->containsIntersections())
        {
            osgUtil::LineSegmentIntersector::Intersections intersections;
            osgUtil::LineSegmentIntersector::Intersections::iterator itr;

            intersections = intersector->getIntersections();

            for (itr = intersections.begin(); itr != intersections.end(); ++itr)
            {
                //std::cout << "testing intersection with " << (*itr).nodePath[0]->getName() << std::endl;

                // first check if the hit is with our target (should be first in
                // the nodepath):

                testNode = dynamic_cast<ReferencedNode*>((*itr).nodePath[0]);
                if (testNode!=targetNode) continue;

                // The intersection has a nodepath that we have to walk down to
                // see which exact node has been hit. It's possible that there
                // are other SPIN nodes in the targetNode's subgraph that are
                // the real source of intersection:

                hitNode = 0;
                testNode = 0;
                for (unsigned int i=0; i<(*itr).nodePath.size(); i++)
                {
                    testNode = dynamic_cast<ReferencedNode*>((*itr).nodePath[i]);
                    if (testNode) hitNode = testNode;
                }

                if (hitNode.valid())
                {

                    //std::cout << id->s_name << " collision!!! with " << (*itr).drawable->getName() << "[" << (*itr).primitiveIndex << "] @ " << std::endl;
                    //std::cout << "localHitPoint:\t" << localHitPoint.x()<<","<<localHitPoint.y()<<","<<localHitPoint.z() << std::endl;
                    //std::cout << "localHitNormal:\t" << localHitNormal.x()<<","<<localHitNormal.y()<<","<<localHitNormal.z() << std::endl;


                    // For BOUNCE mode, we need to check if we've intersected
                    // with the same primitive again. This may occur since we
                    // do recursive translations after repositioning the node at
                    // the bounce point (and there may be numerical imprecision)
                    // If so, we skip this intersection:
                    if ((_mode==BOUNCE) &&
                            (lastDrawable.get()==(*itr).drawable.get()) &&
                            (lastPrimitiveIndex==(int)(*itr).primitiveIndex))
                    {
                        //std::cout << "... skipping" << std::endl;
                        continue;
                    }
                    else
                    {
                        lastDrawable=(*itr).drawable;
                        lastPrimitiveIndex=(*itr).primitiveIndex;
                    }


                    osg::Vec3 localHitPoint = (*itr).getWorldIntersectPoint();
                    osg::Vec3 localHitNormal = (*itr).getWorldIntersectNormal();
                    localHitNormal.normalize();


                    // current direction vector:
                    osg::Vec3 dirVec = v;
                    dirVec.normalize();

                    // Find the rotation between the direction vector and the
                    // surface normal at the hit point:
                    osg::Quat rot;
                    rot.makeRotate(dirVec, localHitNormal);
                    //std::cout << "rot =     " << rot.x()<<","<<rot.y()<<","<<rot.z()<<","<<rot.w() << " ... angle=" << acos(rot.w())*2 << ", indegrees=" << osg::RadiansToDegrees(acos(rot.w()))*2 << std::endl;

                    // the surface normal may be in the opposite direction
                    // from us. If so, we need to flip it:
                    if (acos(rot.w()) * 2 > osg::PI_2)
                    {
                        localHitNormal *= -1;
                        rot.makeRotate(dirVec, localHitNormal);
                        //std::cout << "flipped = " << rot.x()<<","<<rot.y()<<","<<rot.z()<<","<<rot.w() << " ... angle=" << acos(rot.w())*2 << ", indegrees=" << osg::RadiansToDegrees(acos(rot.w()))*2 << std::endl;
                    }


                    osg::Vec3 rotEulers = QuatToEuler(rot);
                    //std::cout << "newHitNormal:\t" << localHitNormal.x()<<","<<localHitNormal.y()<<","<<localHitNormal.z() << std::endl;


                    if ((_mode==COLLIDE)||(_mode==COLLIDE_THRU)||(_mode==STICK))
                    {
                        // Let the collisionPoint be just a bit before the real
                        // hitpoint (to avoid numerical imprecision placing the
                        // node behind the plane):
                        osg::Vec3 collisionPoint = localHitPoint - (localHitNormal * 0.01);

                        // place the node at the collision point
                        setTranslation(collisionPoint.x(), collisionPoint.y(), collisionPoint.z());

                        BROADCAST(this, "ssfff", "collide", hitNode->id->s_name, osg::RadiansToDegrees(rotEulers.x()), osg::RadiansToDegrees(rotEulers.y()), osg::RadiansToDegrees(rotEulers.z()));


                        if (_mode==COLLIDE)
                        {
                            // SLIDE along the hit plane with the left over energy:
                            // ie, project the remaining vector onto the surface we
                            // just intersected with.
                            //
                            // using:
                            //   cos(theta) = distToSurface / remainderVector length
                            //
                            double cosTheta = (dirVec * -localHitNormal) ; // dot product
                            osg::Vec3 remainderVector = (localPos + v) - localHitPoint;
                            double distToSurface = cosTheta * remainderVector.length();
                            osg::Vec3 slideVector = remainderVector + (localHitNormal * distToSurface);

                            // pseudo-recursively apply remainder of bounce:
                            applyConstrainedTranslation( slideVector );
                        }
                        else if (_mode==COLLIDE_THRU)
                        {
                            // allow the node to pass thru (ie, just apply the
                            // translation):
                            //setTranslation(v.x(), v.y(), v.z());
                            osg::Vec3 newPos = localPos + v;
                            setTranslation(newPos.x(), newPos.y(), newPos.z());
                        }

                        return;
                    }


                    else if (_mode==BOUNCE)
                    {
                        // bounce returns a translation mirrored about the hit
                        // normal to the surface



                        // the new direction vector is a rotated version
                        // of the original, about the localHitNormal:
                        //osg::Vec3 newDir = (rot * 2.0) * -dirVec;
                        osg::Vec3 newDir = (rot * (rot * -dirVec));
                        newDir.normalize();
                        //std::cout << "newDir = " << newDir.x()<<","<<newDir.y()<<","<<newDir.z() << std::endl;


                        // amount of distance still to travel after bounce:
                        double dist = v.length() - (localHitPoint-localPos).length();
                        //std::cout << "dist =   " << dist << std::endl;



                        // in node is translating (ie, changing position
                        // independently from it's orientatino), then we need to
                        // flip the velocity vector.
                        if (_velocityMode == GroupNode::TRANSLATE)
                        {
                            osg::Vec3 newVel = newDir * _velocity.length();
                            setVelocity(newVel.x(), newVel.y(), newVel.z());
                        }

                        // if the node is moving along it's orientation vector,
                        // we need to update the orientation of so that it
                        // points in 'bounced' direction
                        else if (_velocityMode == GroupNode::MOVE)
                        {
                            osg::Quat newQuat;
                            newQuat.makeRotate(osg::Vec3(0,1,0),  newDir);
                            osg::Vec3 newRot = Vec3inDegrees(QuatToEuler(newQuat));
                            //std::cout << "newrot = " << newRot.x()<<","<<newRot.y()<<","<<newRot.z() << std::endl;
                            setOrientation(newRot.x(), newRot.y(), newRot.z());

                        }

                        // the new position will be just a hair before hitpoint
                        // (because numerical imprecision may place the hitpoint
                        // slightly beyond the surface, and when we bounce the
                        // node, we don't want to  intersect with the same
                        // surface again)
                        double HAIR = 0.0000001;
                        setTranslation(localHitPoint.x()-dirVec.x()*HAIR, localHitPoint.y()-dirVec.y()*HAIR, localHitPoint.z()-dirVec.z()*HAIR);
                        //setTranslation(localHitPoint.x(), localHitPoint.y(), localHitPoint.z());

                        //std::cout << "rotEulers = " << osg::RadiansToDegrees(rotEulers.x())<<","<<osg::RadiansToDegrees(rotEulers.y())<<","<<osg::RadiansToDegrees(rotEulers.z()) << std::endl;
                        BROADCAST(this, "ssfff", "bounce", hitNode->id->s_name, osg::RadiansToDegrees(rotEulers.x()), osg::RadiansToDegrees(rotEulers.y()), osg::RadiansToDegrees(rotEulers.z()));

                        // pseudo-recursively apply remainder of bounce:
                        applyConstrainedTranslation(newDir*dist);

                        return;

                    }
                }
            }
        } //else std::cout << "no intersections" << std::endl;
    }


    // no intersections, so just do regular translation:
    osg::Vec3 newPos = localPos + v;
    setTranslation(newPos.x(), newPos.y(), newPos.z());
}
Exemple #8
0
float cvr::planePointDistanceRef(const osg::Vec3 & planePoint,
        const osg::Vec3 & planeNormal, const osg::Vec3 & point)
{
    return ((point - planePoint) * planeNormal) / planeNormal.length();
}
Exemple #9
0
double CVehicle::calculateAngle(osg::Vec3 vecA,osg::Vec3 vecB)
{
	double angle,angleA,angleB;

	angle = acos(vecA * vecB / (vecA.length() * vecB.length()));
	if( angle < 0.0001)
	{
		angle = 0.0;
		return angle;
	}

	//求得vecA vecB分别与x轴正向的夹角
	angleA =  acos( vecA.x() / vecA.length() );   
	if( vecA.y() >= 0 )
		angleA = angleA;
	if( vecA.y() < 0 )
		angleA = 2.0 * osg::PI - angleA;


	angleB =  acos( vecB.x() / vecB.length() );   
	if( vecB.y() >= 0 )
		angleB = angleB;
	if( vecB.y() < 0 )
		angleB = 2.0 * osg::PI - angleB;


	//得到两向量间的夹角,通过angleA angleB的关系来判断旋转的方向

	if( angleA > angleB && (angleA - angleB) <= osg::PI )
		angle = -1.0 * acos(vecA * vecB / (vecA.length() * vecB.length()));
	if( angleA > angleB && (angleA - angleB) > osg::PI)
		angle = acos(vecA * vecB / (vecA.length() * vecB.length())) ;


	if( angleA < angleB && (angleB - angleA) <= osg::PI )
		angle = acos(vecA * vecB / (vecA.length() * vecB.length()));
	if( angleA < angleB && (angleB - angleA) > osg::PI)
		angle = -1.0 *  acos(vecA * vecB / (vecA.length() * vecB.length()))  ;

	return angle;
}
Exemple #10
0
 void setAxis(const osg::Vec3 &a)
 {
     axis_ = a / a.length();
 }