Пример #1
0
double MultitouchNavigation::angleBetween3DVectors(osg::Vec3 v1, osg::Vec3 v2)
{
    // http://codered.sat.qc.ca/redmine/projects/spinframework/repository/revisions/b6245189c19a7c6ba4fdb126940321c41c44e228/raw/src/spin/osgUtil.cpp

    // normalize vectors (note: this must be done alone, not within any vector arithmetic. why?!)
    v1.normalize();
    v2.normalize();

    // Get the dot product of the vectors
    double dotProduct = v1 * v2;

    // for acos, the value has to be between -1.0 and 1.0, but due to numerical imprecisions it sometimes comes outside this range
    if (dotProduct > 1.0)
        dotProduct = 1.0;
    if (dotProduct < -1.0)
        dotProduct = -1.0;

    // Get the angle in radians between the 2 vectors (should this be -acos ? ie, negative?)
    double angle = acos(dotProduct);

    // Here we make sure that the angle is not a -1.#IND0000000 number, which means indefinite
    if (std::isnan(angle)) //__isnand(x)
        return 0;

    // Return the angle in radians
    return (angle);
}
Пример #2
0
bool
HeightFieldUtils::getNormalAtNormalizedLocation(const osg::HeightField* input,
                                                double nx, double ny,
                                                osg::Vec3& output,
                                                ElevationInterpolation interp)
{
    double xcells = (double)(input->getNumColumns()-1);
    double ycells = (double)(input->getNumRows()-1);

    double w = input->getXInterval() * xcells * 111000.0;
    double h = input->getYInterval() * ycells * 111000.0;

    double ndx = 1.0/xcells;
    double ndy = 1.0/ycells;

    double xmin = osg::clampAbove( nx-ndx, 0.0 );
    double xmax = osg::clampBelow( nx+ndx, 1.0 );
    double ymin = osg::clampAbove( ny-ndy, 0.0 );
    double ymax = osg::clampBelow( ny+ndy, 1.0 );

    osg::Vec3 west (xmin*w, ny*h, getHeightAtNormalizedLocation(input, xmin, ny, interp));
    osg::Vec3 east (xmax*w, ny*h, getHeightAtNormalizedLocation(input, xmax, ny, interp));
    osg::Vec3 south(nx*w, ymin*h, getHeightAtNormalizedLocation(input, nx, ymin, interp));
    osg::Vec3 north(nx*w, ymax*h, getHeightAtNormalizedLocation(input, nx, ymax, interp));

    output = (west-east) ^ (north-south);
    output.normalize();
    return true;
}
Пример #3
0
// -------------------------------------------------------------------------
void Hermite::getTangentOnSegment(osg::Vec3& tangent, double distance, unsigned int segment)
{
	float fH1 = ( 6.0f * distance - 6.0f) * distance;
	float fH2 = ( 3.0f * distance - 4.0f) * distance + 1.0f;
	float fH3 = ( 3.0f * distance - 2.0f) * distance;
	float fH4 = (-6.0f * distance + 6.0f) * distance;

	const ControlPoint& begin = (*_segments)[segment].getBegin();
	const ControlPoint& end   = (*_segments)[segment].getEnd();

	tangent = begin.position * fH1 + begin.tangent * fH2 + end.tangent * fH3 + end.position * fH4;
	tangent.normalize();
	
	/*
	tangent[0] = begin->position.x * fH1 +
		begin->tangent.x  * fH2 +
		end->tangent.x    * fH3 +
		end->position.x   * fH4;
	tangent[1] = begin->position.y * fH1 +
		begin->tangent.y  * fH2 +
		end->tangent.y    * fH3 +
		end->position.y   * fH4;
	tangent[2] = begin->position.z * fH1 +
		begin->tangent.z  * fH2 +
		end->tangent.z    * fH3 +
		end->position.z   * fH4;

	Math::normalize(tangent);
	*/
	
}
Пример #4
0
    void normal(osg::Vec3 v1, osg::Vec3 v2, osg::Vec3 v3)
    {
        osg::Vec3 u,v;

        // right hand system, CCW triangle
        u = v2 - v1;
        v = v3 - v1;
        triNormal = u^v;
        triNormal.normalize();
    }
Пример #5
0
/**
 * Retrieves the normal of the terrain at the specified location.
 *
 * @param x the x coordinate to check
 * @param y the y coordinate to check
 * @param normal the location at which to store the normal
 * instead of triangle mesh height
 */
void SurfaceObject::GetNormal(float x, float y, osg::Vec3& normal)
{
      float z = GetHeight(x, y);

      osg::Vec3 v1(0.1f, 0.0f, GetHeight(x + 0.1f, y) - z);
      osg::Vec3 v2(0.0f, 0.1f, GetHeight(x, y + 0.1f) - z );

      normal = v1 ^ v2;

      normal.normalize();

      /*   if (normal.x() != 0 ||  normal.y() != 0 || normal.z() != 1 )
   	std::cout<<"NORM "<<"("<<normal.x()<<",\t"<<normal.y()<<",\t"<<normal.z()<<")"<<std::endl;
*/
}
Пример #6
0
bool
TileModel::ElevationData::getNormal(const osg::Vec3d&      ndc,
                                    const GeoLocator*      ndcLocator,
                                    osg::Vec3&             output,
                                    ElevationInterpolation interp ) const
{
    if ( !_locator.valid() || !ndcLocator )
    {
        output.set(0,0,1);
        return false;
    }

    double xcells = (double)(_hf->getNumColumns()-1);
    double ycells = (double)(_hf->getNumRows()-1);
    double xres = 1.0/xcells;
    double yres = 1.0/ycells;

    osg::Vec3d hf_ndc;
    GeoLocator::convertLocalCoordBetween( *ndcLocator, ndc, *_locator.get(), hf_ndc );

    float centerHeight = HeightFieldUtils::getHeightAtNormalizedLocation(_hf.get(), hf_ndc.x(), hf_ndc.y(), interp);

    osg::Vec3d west ( hf_ndc.x()-xres, hf_ndc.y(), 0.0 );
    osg::Vec3d east ( hf_ndc.x()+xres, hf_ndc.y(), 0.0 );
    osg::Vec3d south( hf_ndc.x(), hf_ndc.y()-yres, 0.0 );
    osg::Vec3d north( hf_ndc.x(), hf_ndc.y()+yres, 0.0 );

    if (!HeightFieldUtils::getHeightAtNormalizedLocation(_neighbors, west.x(),  west.y(),  west.z(), interp))
        west.z() = centerHeight;
    if (!HeightFieldUtils::getHeightAtNormalizedLocation(_neighbors, east.x(),  east.y(),  east.z(), interp))
        east.z() = centerHeight;
    if (!HeightFieldUtils::getHeightAtNormalizedLocation(_neighbors, south.x(), south.y(), south.z(), interp))
        south.z() = centerHeight;
    if (!HeightFieldUtils::getHeightAtNormalizedLocation(_neighbors, north.x(), north.y(), north.z(), interp))
        north.z() = centerHeight;

    osg::Vec3d westWorld, eastWorld, southWorld, northWorld;
    _locator->unitToModel(west,  westWorld);
    _locator->unitToModel(east,  eastWorld);
    _locator->unitToModel(south, southWorld);
    _locator->unitToModel(north, northWorld);

    output = (eastWorld-westWorld) ^ (northWorld-southWorld);
    output.normalize();

    return true;
}
Пример #7
0
/*
 * Ok, simulate a track-ball.  Project the points onto the virtual
 * trackball, then figure out the axis of rotation, which is the cross
 * product of P1 P2 and O P1 (O is the center of the ball, 0,0,0)
 * Note:  This is a deformed trackball-- is a trackball in the center,
 * but is deformed into a hyperbolic sheet of rotation away from the
 * center.  This particular function was chosen after trying out
 * several variations.
 *
 * It is assumed that the arguments to this routine are in the range
 * (-1.0 ... 1.0)
 */
void Vwr::CameraManipulator::trackball(osg::Vec3& axis, float& angle,
		float p1x, float p1y, float p2x, float p2y) {
	/*
	 * First, figure out z-coordinates for projection of P1 and P2 to
	 * deformed sphere
	 */

	osg::Matrix rotation_matrix(_rotation);

	osg::Vec3 uv = osg::Vec3(0.0f, 1.0f, 0.0f) * rotation_matrix;
	osg::Vec3 sv = osg::Vec3(1.0f, 0.0f, 0.0f) * rotation_matrix;
	osg::Vec3 lv = osg::Vec3(0.0f, 0.0f, -1.0f) * rotation_matrix;

	osg::Vec3 p1 = sv * p1x + uv * p1y - lv * tb_project_to_sphere(
			_trackballSize, p1x, p1y);
	osg::Vec3 p2 = sv * p2x + uv * p2y - lv * tb_project_to_sphere(
			_trackballSize, p2x, p2y);

	/*
	 *  Now, we want the cross product of P1 and P2
	 */

	// Robert,
	//
	// This was the quick 'n' dirty  fix to get the trackball doing the right
	// thing after fixing the Quat rotations to be right-handed.  You may want
	// to do something more elegant.
	//   axis = p1^p2;
	axis = p2 ^ p1;
	axis.normalize();

	/*
	 *  Figure out how much to rotate around that axis.
	 */
	float t = (p2 - p1).length() / (2.0 * _trackballSize);

	/*
	 * Avoid problems with out-of-control values...
	 */
	if (t > 1.0)
		t = 1.0;
	if (t < -1.0)
		t = -1.0;
	angle = inRadians(asin(t));

}
Пример #8
0
void dtAnim::GetCelestialCoordinates(osg::Vec3 target,
                                     const osg::Vec3 &lookForward,                                    
                                     float &azimuth, 
                                     float &elevation)
{  
   target.normalize();

   // Derive the reference frame for the "look" pose
   osg::Vec3 frameRight = lookForward ^ osg::Z_AXIS;
   osg::Vec3 frameUp    = frameRight ^ lookForward;

   osg::Matrix frameMatrix(frameRight.x(),  frameRight.y(),  frameRight.z(),  0.0f,                            
                           lookForward.x(), lookForward.y(), lookForward.z(), 0.0f,
                           frameUp.x(),     frameUp.y(),     frameUp.z(),     0.0f,
                           0.0f,            0.0f,            0.0f,            1.0f);  

   // Transform the target into the proper coordinate frame
   target = frameMatrix * target;

   // Project our target vector onto the xy plane 
   // in order to calculate azimuth
   osg::Vec3f targetRight = target ^ osg::Z_AXIS;
   targetRight.normalize();

   osg::Vec3f targetForward = osg::Z_AXIS ^ targetRight;
   targetForward.normalize();    

   // Use the projected vector to calculate the azimuth
   // between the projection and the character forward
   float lookDotTargetForward   = targetForward * osg::Y_AXIS;
   float targetDotTargetForward = targetForward * target;

   // acos needs it's parameter between -1 and 1
   dtUtil::Clamp(lookDotTargetForward, -1.0f, 1.0f);
   dtUtil::Clamp(targetDotTargetForward, -1.0f, 1.0f);

   // We need to manually determine the sign
   float azimuthSign   = ((target * osg::X_AXIS) > 0.0f) ? -1.0f: 1.0f;    
   float elevationSign = ((target * osg::Z_AXIS) > 0.0f) ? 1.0f: -1.0f;

   // We can use the angle between the projection
   // and the original target to determine elevation
   elevation  = acos(targetDotTargetForward) * elevationSign;
   azimuth    = acos(lookDotTargetForward) * azimuthSign;
}
Пример #9
0
bool
HeightFieldUtils::getNormalAtNormalizedLocation(const osg::HeightField* input,
                                                double nx, double ny,
                                                osg::Vec3& output,
                                                ElevationInterpolation interp)
{
    double dx = 1.0/(double)(input->getNumColumns()-1);
    double dy = 1.0/(double)(input->getNumRows()-1);

    double xmin = osg::clampAbove( nx-dx, 0.0 );
    double xmax = osg::clampBelow( nx+dx, 1.0 );
    double ymin = osg::clampAbove( ny-dx, 0.0 );
    double ymax = osg::clampBelow( ny+dy, 1.0 );

    osg::Vec3 west (xmin, ny, getHeightAtNormalizedLocation(input, xmin, ny, interp));
    osg::Vec3 east (xmax, ny, getHeightAtNormalizedLocation(input, xmax, ny, interp));
    osg::Vec3 south(nx, ymin, getHeightAtNormalizedLocation(input, nx, ymin, interp));
    osg::Vec3 north(nx, ymax, getHeightAtNormalizedLocation(input, nx, ymax, interp));

    output = (west-east) ^ (north-south);
    output.normalize();
    return true;
}
Пример #10
0
void Wire::cutWire(osg::Vec3 normal, float dist)
{

    normal.normalize();

    DrawArrayLengths *newPrimitives = new DrawArrayLengths(PrimitiveSet::POLYGON);
    UShortArray *newIndices = new UShortArray();

    int startIndex = 0;

    int index = vert->getNumElements();
    for (unsigned int i = 0; i < primitives->getNumPrimitives(); i++)
    {
        float oldd = -1;
        int numInd = 0;
        for (int v = 0; v < (*primitives)[i]; v++)
        {
            osg::Vec3 p = (*vert)[indices->index(startIndex + v)];
            float d = (p - normal * dist) * normal;
            /* Grundidee:
			* wir laufen allen Punkte von jedem Polygon einmal
			* durch; liegt der Punkte im "Verbleib" Bereich, wird
			* wird er einfach kopiert, liegt er ausserhalb, dann
			* wird er weggelassen
			* !! Immer wenn ein Wechsel zwischen "verbleibt" und\
			* und "weglassen" erfolgt, dann muss mindestens ein
			* zusaetzlicher Punkt eingefuegt werden.
			*/
            if (v == 0 && d >= 0)
            {
                newIndices->push_back((*indices)[startIndex + v]);
                numInd++;
            }
            else
            {
                if (d < 0)
                {
                    if (oldd > 0)
                    {
                        osg::Vec3 b = (*vert)[(*indices)[startIndex + v - 1]];
                        osg::Vec3 r = p - b;
                        float t = (dist - normal * p) / (normal * r);
                        osg::Vec3 newP = p + r * t;
                        osg::Vec3 n1 = (*normals)[(*indices)[startIndex + v]];
                        osg::Vec3 n2 = (*normals)[(*indices)[startIndex + v - 1]];
                        osg::Vec3 newN = n1 + (n1 - n2) * t;
                        vert->push_back(newP);
                        normals->push_back(newN);
                        newIndices->push_back(index);
                        index++;
                        numInd++;
                    }
                    else
                    {
                    }
                }
                else
                {
                    if (oldd < 0)
                    {
                        osg::Vec3 b = (*vert)[(*indices)[startIndex + v - 1]];
                        osg::Vec3 r = p - b;
                        float t = (dist - normal * p) / (normal * r);
                        osg::Vec3 newP = p + r * t;
                        osg::Vec3 n1 = (*normals)[(*indices)[startIndex + v]];
                        osg::Vec3 n2 = (*normals)[(*indices)[startIndex + v - 1]];
                        osg::Vec3 newN = n1 + (n1 - n2) * t;
                        vert->push_back(newP);
                        normals->push_back(newN);
                        newIndices->push_back(index);
                        index++;
                        numInd++;
                    }

                    newIndices->push_back((*indices)[startIndex + v]);
                    numInd++;
                }
            }
            oldd = d;
        }

        osg::Vec3 p = (*vert)[indices->index(startIndex)];
        float d = (p - normal * dist) * normal;

        if (d < 0)
        {
            if (oldd > 0)
            {
                osg::Vec3 b = (*vert)[(*indices)[startIndex + (*primitives)[i] - 1]];
                osg::Vec3 r = p - b;
                float t = (dist - normal * p) / (normal * r);
                osg::Vec3 newP = p + r * t;
                osg::Vec3 n1 = (*normals)[(*indices)[startIndex]];
                osg::Vec3 n2 = (*normals)[(*indices)[startIndex + (*primitives)[i] - 1]];
                osg::Vec3 newN = n1 + (n1 - n2) * t;
                vert->push_back(newP);
                normals->push_back(newN);
                newIndices->push_back(index);
                index++;
                numInd++;
            }
        }
        else
        {
            if (oldd < 0)
            {
                osg::Vec3 b = (*vert)[(*indices)[startIndex + (*primitives)[i] - 1]];
                osg::Vec3 r = p - b;
                float t = (dist - normal * p) / (normal * r);
                osg::Vec3 newP = p + r * t;
                osg::Vec3 n1 = (*normals)[(*indices)[startIndex]];
                osg::Vec3 n2 = (*normals)[(*indices)[startIndex + (*primitives)[i] - 1]];
                osg::Vec3 newN = n1 + (n1 - n2) * t;
                vert->push_back(newP);
                normals->push_back(newN);
                newIndices->push_back(index);
                index++;
                numInd++;
            }
        }
        newPrimitives->push_back(numInd);
        startIndex += (*primitives)[i];
    }

    geom->setVertexIndices(newIndices);
    geom->setNormalIndices(newIndices);

    geom->removePrimitiveSet(0, geom->getNumPrimitiveSets());
    geom->addPrimitiveSet(newPrimitives);
    primitives = newPrimitives;
    indices = newIndices;

    // calcColors();
    geom->dirtyBound();
    geom->dirtyDisplayList();
}