예제 #1
0
////////////////////////////////////////////////////////////////////////
//
// Description:
//    Stretch the dragger according to the motion along the plane
//    projector
//
// Use: private
//
void
SoTranslate2Dragger::drag()
//
////////////////////////////////////////////////////////////////////////
{
    // Set up the projector space and view.
    // Working space is space at end of motion matrix.
	planeProj->setViewVolume( getViewVolume() );    
	planeProj->setWorkingSpace( getLocalToWorldMatrix() );

    // Get newHitPt and startHitPt in workspace.
	SbVec3f newHitPt = planeProj->project( getNormalizedLocaterPosition()); 
	SbVec3f startHitPt = getLocalStartingPoint();

    // Convert newHitPt to world space and save this as our new worldRestartPt
	getLocalToWorldMatrix().multVecMatrix( newHitPt, worldRestartPt );

    // Figure out the translation relative to start position.
        SbVec3f motion = newHitPt - startHitPt;

    // Maybe we need to constrain the motion...
    if ( !shftDown )
	translateDir = -1;
    else {
	// The shift key is pressed. This means 1-D translation.
	if ( translateDir == -1 ) {
	    // The 1-D direction is not defined. Calculate it based on which
	    // direction got the maximum locater motion.
            if ( isAdequateConstraintMotion() ) {
		if ( fabs( motion[0]) > fabs( motion[1]))
		    translateDir = 0;
		else 
		    translateDir = 1;

		// Set the axis feedback switch to the given direction.
		setSwitchValue( axisFeedbackSwitch.getValue(), translateDir );
	    }
	    else {
		// Not ready to pick a direction yet. Don't move.
		return;
	    }
	}
	// get the projection of 'motion' onto the preferred axis.
	SbVec3f constrainedMotion(0,0,0);
	constrainedMotion[translateDir] = motion[translateDir];
	motion = constrainedMotion;
    }

    // Append this to the startMotionMatrix, which we saved at the beginning
    // of the drag, to find the current motion matrix.
	setMotionMatrix( appendTranslation( getStartMotionMatrix(), motion ) );
}
예제 #2
0
////////////////////////////////////////////////////////////////////////
//
// Description:
//    Rotate the rotateDiscDragger based on mouse motion.
//
// Use: private
//
void
SoRotateDiscDragger::drag()
//
////////////////////////////////////////////////////////////////////////
{
    // Set up the projector space and view.
    // Working space is space at end of motion matrix.
	planeProj->setViewVolume( getViewVolume() );    
	planeProj->setWorkingSpace( getLocalToWorldMatrix() );

    // Get newHitPt and startHitPt in workspace.
	SbVec3f newHitPt 
	    = planeProj->project( getNormalizedLocaterPosition()); 
	SbVec3f startHitPt = getLocalStartingPoint();

    // Find the amount of rotation
    SbVec3f oldVec = startHitPt;
    SbVec3f newVec = newHitPt;
    // Remove the part of these vectors that is parallel to the normal
    oldVec -= SbVec3f( 0, 0, oldVec[2] );
    newVec -= SbVec3f( 0, 0, newVec[2] );

    // deltaRot is how much we rotated since the mouse button went down.
    SbRotation deltaRot = SbRotation( oldVec, newVec );
	
    // Append this to the startMotionMatrix, which we saved at the beginning
    // of the drag, to find the current motion matrix.
	setMotionMatrix( 
	    appendRotation( getStartMotionMatrix(), deltaRot, SbVec3f(0,0,0)));
}
예제 #3
0
파일: particle.cpp 프로젝트: iClunk/openmw
void Emitter::emitParticles(double dt)
{
    int n = mCounter->numParticlesToCreate(dt);
    if (n == 0)
        return;

    osg::Matrix worldToPs;

    // maybe this could be optimized by halting at the lowest common ancestor of the particle and emitter nodes
    osg::NodePathList partsysNodePaths = getParticleSystem()->getParentalNodePaths();
    if (!partsysNodePaths.empty())
    {
        osg::Matrix psToWorld = osg::computeLocalToWorld(partsysNodePaths[0]);
        worldToPs = osg::Matrix::inverse(psToWorld);
    }

    const osg::Matrix& ltw = getLocalToWorldMatrix();
    osg::Matrix emitterToPs = ltw * worldToPs;

    if (!mTargets.empty())
    {
        int randomRecIndex = mTargets[(std::rand() / (static_cast<double>(RAND_MAX)+1.0)) * mTargets.size()];

        // we could use a map here for faster lookup
        FindGroupByRecIndex visitor(randomRecIndex);
        getParent(0)->accept(visitor);

        if (!visitor.mFound)
        {
            std::cerr << "Emitter: Can't find emitter node" << randomRecIndex << std::endl;
            return;
        }

        osg::NodePath path = visitor.mFoundPath;
        path.erase(path.begin());
        emitterToPs = osg::computeLocalToWorld(path) * emitterToPs;
    }

    emitterToPs.orthoNormalize(emitterToPs);

    for (int i=0; i<n; ++i)
    {
        osgParticle::Particle* P = getParticleSystem()->createParticle(0);
        if (P)
        {
            mPlacer->place(P);

            mShooter->shoot(P);

            P->transformPositionVelocity(emitterToPs);
        }
    }
}
예제 #4
0
void osgParticleHPS::ModularEmitter::emit(double dt) 
{
    int n = counter_->numParticlesToCreate(dt);
    for (int i=0; i<n; ++i) {
        Particle *P = getParticleSystem()->createParticle();
        if (P) {
            placer_->place(P);
            shooter_->shoot(P);
            if (getReferenceFrame() == RELATIVE_TO_PARENTS) {
                P->transformPositionVelocity(getLocalToWorldMatrix());
            }
        }
    }
}
예제 #5
0
void TranslateRadialDragger::
drag()
{
  // Things can change between renderings. To be safe, update
  // the projector with the current values.
  lineProj->setViewVolume(getViewVolume());
  lineProj->setWorkingSpace(getLocalToWorldMatrix());

  // Find the new intersection on the projector.
  SbVec3f newHitPt
    = lineProj->project(getNormalizedLocaterPosition());

  // Get initial point expressed in our current local space.
  SbVec3f startHitPt = getLocalStartingPoint();

  // Motion in local space is difference between old and
  // new positions.
  SbVec3f motion = newHitPt - startHitPt;

  // Append this to the startMotionMatrix, which was saved
  // automatically at the beginning of the drag, to find
  // the current motion matrix.
  setMotionMatrix( appendTranslation(getStartMotionMatrix(), motion));
}
예제 #6
0
void
SoDragPointDragger::checkBoxLimits()
//
////////////////////////////////////////////////////////////////////////
{
    // The limit box is defined in a space aligned and scaled as LOCAL 
    // space, but with it's center remaining fixed in WORLD space.

    // We need to do this work in LOCAL space, so to begin with,
    // get the location of the center of this box in LOCAL space.
    SbMatrix worldToLocal = getWorldToLocalMatrix();
    SbVec3f limitBoxCenterInLocal = limitBox.getCenter();
    worldToLocal.multVecMatrix( limitBoxCenterInLocal, 
				     limitBoxCenterInLocal );

    // Now, if our current position is out of range, we need to move
    // the limit box center accordingly. We continue to do our work
    // in LOCAL space.

    SbBool changed = FALSE;
    SbVec3f boxSize = limitBox.getMax() - limitBox.getMin();

    for (int i = 0; i < 3; i++) {

	float length = boxSize[i];
	float halfLength = length * 0.5;

	// Check the location of startLocalHitPt against boundaries of the limit
	// box (keeping in mind the jump limit as a % of the total length).

	// Have we gone too far in the positive direction?
	float high = limitBoxCenterInLocal[i] + halfLength;
	while ( (high - startLocalHitPt[i]) / length < jumpLimit ) {
	    limitBoxCenterInLocal[i] += halfLength;
	    high += halfLength;
	    changed = TRUE;

	}

	// Have we gone too far in the negative direction?
	float low  = limitBoxCenterInLocal[i] - halfLength;
	while (( startLocalHitPt[i] - low ) / length < jumpLimit ) {
	    limitBoxCenterInLocal[i] -= halfLength;
	    low  -= halfLength;
	    changed = TRUE;
	}
    }

    if (changed == TRUE ) {
	// First, convert the changed limitBoxCenterInLocal
	// into WORLD space...
	SbMatrix localToWorld = getLocalToWorldMatrix();
	SbVec3f newCenter;
	localToWorld.multVecMatrix(limitBoxCenterInLocal,newCenter);

	// Next, set the bounds of the limit box to have the same size
	// as before, but centered about this new point.
	SbVec3f diag = limitBox.getMax() - 
		       limitBox.getCenter();

	limitBox.setBounds( newCenter - diag, newCenter + diag );
    }
}
예제 #7
0
////////////////////////////////////////////////////////////////////////
//
// Description:
//   This routine sets the limitBox. 
// The limit box is defined in a space aligned and scaled as 
// LOCAL space, but with it's center remaining fixed in WORLD 
// space.
//
// Use: static private
//
void
SoDragPointDragger::updateLimitBoxAndFeedback()
//
////////////////////////////////////////////////////////////////////////
{
    // This gets called in the constructor, while the ref count is still 0.
    // Since there will be some ref'ing and unref'ing done inside here,
    // add a temporary ref and undo it at the end.
    ref();

    if ( xFeedback.getValue() != oldXAxisNode ||
	 yFeedback.getValue() != oldYAxisNode ||
	 zFeedback.getValue() != oldZAxisNode ) {

	oldXAxisNode = SO_GET_ANY_PART(this,"xFeedback",SoSeparator);
	oldYAxisNode = SO_GET_ANY_PART(this,"yFeedback",SoSeparator);
	oldZAxisNode = SO_GET_ANY_PART(this,"zFeedback",SoSeparator);

	// Get the bounds of the axis parts. 
	static SoGetBoundingBoxAction *bba = NULL;
	if (bba == NULL)
	    bba = new SoGetBoundingBoxAction(getViewportRegion());
	else
	    bba->setViewportRegion(getViewportRegion());

	float   xMin, yMin, zMin, xMax, yMax, zMax;
	SbVec3f min, max;

	bba->apply(xFeedback.getValue());
	bba->getBoundingBox().getBounds( xMin, yMin, zMin, xMax, yMax, zMax );
	min[0] = xMin;
	max[0] = xMax;

	bba->apply(yFeedback.getValue());
	bba->getBoundingBox().getBounds( xMin, yMin, zMin, xMax, yMax, zMax );
	min[1] = yMin; 
	max[1] = yMax; 

	bba->apply(zFeedback.getValue());
	bba->getBoundingBox().getBounds( xMin, yMin, zMin, xMax, yMax, zMax );
	min[2] = zMin;
	max[2] = zMax;

	// The limit box is defined in a space aligned and scaled as 
	// LOCAL space, but with it's center remaining fixed in WORLD 
	// space.

	SbVec3f newDiag = (max - min) / 2.0;

	// Give a default size of 1, in case no axis parts exist.
	for (int i = 0; i < 3; i++) {
	    if (newDiag[i] <= getMinScale())
		newDiag[i] = 1.0;
	}

	SbVec3f oldDiag = limitBox.getMax() - 
			  limitBox.getCenter();

	// If the size of the boundingBox has changed...
	if ( newDiag != oldDiag ) {

	    // curEdit point needs to be the current origin expressed in world
	    // space (i.e., this bizarro space).
	    SbMatrix localToWorld = getLocalToWorldMatrix();

	    SbVec3f zeroPt(0,0,0);
	    localToWorld.multVecMatrix( zeroPt, zeroPt );

	    limitBox.setBounds(zeroPt - newDiag, zeroPt + newDiag );
	}
    }

    setFeedbackGeometry();

    // undo the temporary ref.
    unrefNoDelete();
}