Example #1
0
void DrawForce(NxActor* actor, NxVec3& forceVec, const NxVec3& color)
{
	// Draw only if the force is large enough
	NxReal force = forceVec.magnitude();
	if (force < 0.1)  return;

	forceVec = 3*forceVec/force;

	NxVec3 pos = actor->getCMassGlobalPosition();
	DrawArrow(pos, pos + forceVec, color);
}
Example #2
0
// ----------------------------------------------------------------------
void ObjMesh::updateNormals()
{
	mNormals.resize(mVertices.size());
	int i;
	for (i = 0; i < (int)mNormals.size(); i++) 
		mNormals[i].zero();
	NxVec3 n;
	for (i = 0; i < (int)mTriangles.size(); i++) {
		ObjMeshTriangle &mt = mTriangles[i];
		mt.normalNr[0] = mt.vertexNr[0];
		mt.normalNr[1] = mt.vertexNr[1];
		mt.normalNr[2] = mt.vertexNr[2];
		n.cross(mVertices[mt.vertexNr[1]] - mVertices[mt.vertexNr[0]], 
			mVertices[mt.vertexNr[2]] - mVertices[mt.vertexNr[0]]);
		mNormals[mt.normalNr[0]] += n;
		mNormals[mt.normalNr[1]] += n;
		mNormals[mt.normalNr[2]] += n;
	}
	for (i = 0; i < (int)mNormals.size(); i++) 
		mNormals[i].normalize();
}
Example #3
0
void SetupGLMatrix(const NxVec3& pos, const NxMat33& orient)
{
	float glmat[16];	//4x4 column major matrix for OpenGL.
	orient.getColumnMajorStride4(&(glmat[0]));
	pos.get(&(glmat[12]));

	//clear the elements we don't need:
	glmat[3] = glmat[7] = glmat[11] = 0.0f;
	glmat[15] = 1.0f;

	glMultMatrixf(&(glmat[0]));
}
Example #4
0
    void DynamicImage::update()
    {
        


        if (!sleep)
        {
            NxVec3 towardsVector = tarPos - curPos;

            switch (mode)
            {
            case 0:     //Linear
                if (towardsVector.magnitude() < LINEAR_VELOCITY)
                {
                    curPos = tarPos;
                    sleep = true;
                }
                else
                {
                    towardsVector.normalize();
                    curPos = curPos + (towardsVector * LINEAR_VELOCITY);
                }
                break;


            case 1:     //Halfling
                if (towardsVector.magnitude() < THRESHOLD)
                {
                    curPos = tarPos;
                    sleep = true;
                }
                else
                {
                    curPos = curPos + (towardsVector * 0.033f);
                }
                break;

            }
        }
    }
void Jumper::CanopyOpening::updatePhysics(void)
{
    // velocity of base jumper's body
    NxVec3 velocity = _phActor->getLinearVelocity();

    // local coordinate system of base jumper
    NxMat34 pose = _phActor->getGlobalPose();
    NxVec3 x = pose.M.getColumn(0);
    NxVec3 y = pose.M.getColumn(1);
    NxVec3 z = pose.M.getColumn(2);

    // air resistance force
    float AR = _jumper->getVirtues()->getTrackingAirResistance();

    // terminal velocity
    float Vt = sqrt( 9.8f * _phActor->getMass() / AR );
    float It = velocity.magnitude() / Vt;

    // air resistance force
    NxVec3 Far = NxVec3(0,1,0) * getAirResistancePower( velocity.magnitude() / Vt ) * _phActor->getMass() * 9.8f;

    // finalize motion equation    
    _phActor->addForce( Far );

    // linear damping is function of jumper velocity    
    // this is prevents calculation errors due to high speed rates
    float minVel     = 50.0f;
    float minDamping = _initialLD;
    float maxVel     = 70.0f;
    float maxDamping = 2.5f;
    float factor = ( velocity.magnitude() - minVel ) / ( maxVel - minVel );
    factor = factor < 0 ? 0 : ( factor > 1 ? 1 : factor );
    float damping = minDamping * ( factor - 1 ) + maxDamping * ( factor );
    _phActor->setLinearDamping( damping );

    // shallow brake setting
    _canopy->setLeftDeep( 0.0f );
    _canopy->setRightDeep( 0.0f );

}
void Jumper::RunningJump::update(float dt)
{
    updateAnimation( dt );
    _clump->getFrame()->getLTM();

    if( _actionTime < _blendTime ) 
    {
        Vector3f dir = _clump->getFrame()->getAt();
        dir.normalize();
        _clump->getFrame()->setPos( _clump->getFrame()->getPos() + dir * dt * _vel );            
        return;
    }

    if( _phActor->isSleeping() )
    {
        // setup physics
        Matrix4f sampleLTM = Jumper::getCollisionFF( _clump )->getFrame()->getLTM();
        _phActor->setGlobalPose( wrap( sampleLTM ) );
        _phActor->wakeUp();
        NxVec3 velH = wrap( _clump->getFrame()->getAt() );
        velH.normalize();
        velH *= _vel * 0.01f;
        NxVec3 velV = wrap( _clump->getFrame()->getUp() );
        velV.normalize();
        velV *= 1.5f;
        _phActor->setLinearVelocity( velH + velV + wrap(_clump->getFrame()->getAt() * 600.0f * dt)) ;
        _jumper->initOverburdenCalculator( velH + velV );


    }
    else
    {
        _clump->getFrame()->setMatrix( _matrixConversion->convert( wrap( _phActor->getGlobalPose() ) ) );
    }

    if( _clump->getAnimationController()->isEndOfAnimation( 0 ) )
    {
        _endOfAction = true;
    }
}
Example #7
0
void PxSingleActor::applyCorrection( const MatrixF& mat, const NxVec3& linVel, const NxVec3& angVel )
{
   // Sometimes the actor hasn't been
   // created yet during the call from unpackUpdate.
   if ( !mActor || !mWorld )
      return;

   mWorld->releaseWriteLock();

   NxVec3 newPos = mat.getPosition();
   NxVec3 currPos = getPosition();

   NxVec3 offset = newPos - currPos;

   // If the difference isn't large enough,
   // just set the new transform, no correction.
   if ( offset.magnitude() > 0.3f )
   {
      // If we're going to set the linear or angular velocity,
      // we do it before we add a corrective force, since it would be overwritten otherwise.
      NxVec3 currLinVel, currAngVel;
      currLinVel = mActor->getLinearVelocity();
      currAngVel = mActor->getAngularVelocity();

      // Scale the corrective force by half,
      // otherwise it will over correct and oscillate.
      NxVec3 massCent = mActor->getCMassGlobalPosition();
      mActor->addForceAtPos( offset, massCent, NX_VELOCITY_CHANGE );

      // If the linear velocity is divergent enough, change to server linear velocity.
      if ( (linVel - currLinVel).magnitude() > 0.3f )
         mActor->setLinearVelocity( linVel );
      // Same for angular.
      if ( (angVel - currAngVel).magnitude() > 0.3f )
         mActor->setAngularVelocity( angVel );   
   }

   Parent::setTransform( mat );
}
// ray-sphere intersection test from Graphics Gems p.388
// **NOTE** There is a bug in this Graphics Gem.  If the origin
// of the ray is *inside* the sphere being tested, it reports the
// wrong intersection location.  This code has a fix for the bug.
bool  SBM_rayIntersectsSphere(const float *point,const float *direction,const float *_center,float radius,float &t)
{
  bool ret = false;

  NxVec3 rayOrigin(point);
  NxVec3 dir(direction);
  NxVec3 center(_center);

	// notation:
	// point E  = rayOrigin
	// point O  = sphere center

	NxVec3 EO = center - rayOrigin;
  NxVec3 V = dir;

  float dist2 = EO.x*EO.x + EO.y*EO.y + EO.z * EO.z;

  float r2 = radius*radius;

  // Bug Fix For Gem, if origin is *inside* the sphere, invert the
  // direction vector so that we get a valid intersection location.
  if ( dist2 < r2 )
    V*=-1;

	float v = EO.dot(V);

	float disc = r2 - (EO.magnitudeSquared() - v*v);

	if (disc > 0.0f)
	{
    t = sqrtf(disc);
		ret = true;
	}

	return ret;
}
Example #9
0
void DrawForceAtShape(NxActor* actor, NxShape* shape, NxVec3& forceVec, const NxVec3& color)
{
	// Draw only if the force is large enough
	NxReal force = forceVec.magnitude();
	if (force < 0.1f)  return;

	forceVec = 3*forceVec/force;

	NxVec3 pos;	
	if (bShapeSelectMode && bForceMode)
		pos = shape->getGlobalPosition();
	else
		pos = actor->getCMassGlobalPosition();
	DrawArrow(pos, pos + forceVec, color);
}
Example #10
0
void CreateExperiment()
{
	switch (gExperimentType)
	{
	case LANDER:
		  {
			  gScene->releaseActor(*groundPlane); groundPlane=NULL; // will be recreated with the container cell
			  CreateExperimentMaterials();
			  CreateContainerCell(gCellSize);
			  gPhysicsSDK->setParameter(NX_VISUALIZE_ACTOR_AXES,0);
			  gPhysicsSDK->setParameter(NX_VISUALIZE_COLLISION_FNORMALS,0);
			  gPhysicsSDK->setParameter(NX_VISUALIZE_COLLISION_SHAPES,1);
			  gPhysicsSDK->setParameter(NX_VISUALIZE_WORLD_AXES,0);
			  //gLander=CreateLander(NxVec3(0.0f,0.0f,0.0f));
			  gLander=CreateLander(NxVec3(0.0f,gCellSize/2.0f,0.0f));
			  IdentifyGravitators();
			  if (gLander) {
			  ReOrientActor(gLander);
			  SpinActor(gLander,gLandingRoughness*sqrt(gCellSize*gDefaultGravity.magnitude()/(gLander->getMassSpaceInertiaTensor().magnitude())));
			  LaunchActor(gLander,gLandingRoughness*sqrt(gCellSize*gDefaultGravity.magnitude()));
			  gSelectedActor=gLander;
			  gPhysicsSDK->setParameter(NX_VISUALIZE_ACTOR_AXES,gLanderSize.magnitude());
			  isRunning=true;
			  }
			  else {
				  printf("Error: Unable to create lander\a\n");
				  isRunning=false;
			  }
			  break;
		  }
	case LAY_SUBSTRATE:
		{
			gScene->releaseActor(*groundPlane); groundPlane=NULL; // will be recreated with the container cell
			CreateExperimentMaterials();
			CreateContainerCell(gCellSize);
			gPhysicsSDK->setParameter(NX_VISUALIZE_ACTOR_AXES,0);
			gPhysicsSDK->setParameter(NX_VISUALIZE_COLLISION_FNORMALS,0);
			gPhysicsSDK->setParameter(NX_VISUALIZE_COLLISION_SHAPES,1);
			gPhysicsSDK->setParameter(NX_VISUALIZE_WORLD_AXES,0);
			//ThrowStone();
			isRunning=true;
			break;
		}
	default:				
		{printf("Error: unimplemented experiment type\a\n"); isRunning=false; break;}
	}
}
Example #11
0
// -----------------------------------------------------------------------------------
bool ObjMesh::rayTriangleIntersection(const NxVec3 &orig, const NxVec3 &dir,
	 									 const ObjMeshTriangle &triangle,
	 									 NxReal &t, NxReal &u, NxReal &v) const
{
	const NxVec3 &a = mVertices[triangle.vertexNr[0]];
	const NxVec3 &b = mVertices[triangle.vertexNr[0]];
	const NxVec3 &c = mVertices[triangle.vertexNr[0]];

	NxVec3 edge1, edge2, tvec, pvec, qvec;
	NxReal det,inv_det;

	edge1 = b - a;
	edge2 = c - a;
	pvec.cross(dir, edge2);

	/* if determinant is near zero, ray lies in plane of triangle */
	det = edge1.dot(pvec);

	if (det == 0.0f)
		return false;
	inv_det = 1.0f / det;

	/* calculate distance from vert0 to ray origin */
	tvec = orig - a;

	/* calculate U parameter and test bounds */
	u = tvec.dot(pvec) * inv_det;
	if (u < 0.0f || u > 1.0f)
	return false;

	/* prepare to test V parameter */
	qvec.cross(tvec, edge1);

	/* calculate V parameter and test bounds */
	v = dir.dot(qvec) * inv_det;
	if (v < 0.0f || u + v > 1.0f)
	return false;

	/* calculate t, ray intersects triangle */
	t = edge2.dot(qvec) * inv_det;

	return true;
}
Example #12
0
void ViewUnProject(int xi, int yi, float depth, NxVec3 &v)
{
//We cannot do picking easily on the xbox/PS3 anyway
#if defined(_XBOX)||defined(__CELLOS_LV2__)
	v=NxVec3(0,0,0);
#else
	GLint viewPort[4];
	GLdouble modelMatrix[16];
	GLdouble projMatrix[16];
	glGetIntegerv(GL_VIEWPORT, viewPort);
	glGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix);
	glGetDoublev(GL_PROJECTION_MATRIX, projMatrix);
	yi = viewPort[3] - yi - 1;
	GLdouble wx, wy, wz;
	gluUnProject((GLdouble) xi, (GLdouble) yi, (GLdouble) depth,
	modelMatrix, projMatrix, viewPort, &wx, &wy, &wz);
	v.set((NxReal)wx, (NxReal)wy, (NxReal)wz);
#endif
}
Example #13
0
void WindPointer::onEvent(Actor* initiator, unsigned int eventId, void* eventData)
{
    if( eventId == EVENT_CAMERA_IS_ACTUAL )
    {
        // current wind
        NxVec3 wind = _scene->getWindAtPoint( NxVec3( 0,0,0 ) );

        // make signature worldspace position
        Matrix4f cameraPose = _scene->getCamera()->getPose();
        Vector3f cameraPos( cameraPose[3][0], cameraPose[3][1], cameraPose[3][2] );
        Vector3f pos( wind.x, wind.y, wind.z );
        pos.normalize();
        pos *= 10000.0f;
        pos += cameraPos;

        // update signature window
        Vector3f screenPos = Gameplay::iEngine->getDefaultCamera()->projectPosition( pos );
        if( screenPos[2] > 1 )
        {
            _signature->getPanel()->setVisible( false );
            return;
        }
        else
        {
            _signature->getPanel()->setVisible( true );
            gui::Rect oldRect = _signature->getPanel()->getRect();
            gui::Rect newRect(
                int( screenPos[0] ), int( screenPos[1] ),
                int( screenPos[0] ) + oldRect.getWidth(),
                int( screenPos[1] ) + oldRect.getHeight()
            );
            _signature->getPanel()->setRect( newRect );
            _windSpeed->getStaticText()->setText( wstrformat( Gameplay::iLanguage->getUnicodeString(295), wind.magnitude() ).c_str() );
        }        
    }
}
Example #14
0
void GetPos(NxVec3 &maxPos, NxVec3 &minPos, NxCloth *cloth)
{
	NxVec3 vetex[2000];
	ofstream outFile("vetex");
	NxReal maxX = -999.0f, minX = 999.0f;
	NxReal maxY = -999.0f, minY = 999.0f;
	NxReal maxZ = -999.0f, minZ = 999.0f;

	memset(vetex, 0, 2000 * sizeof(NxVec3));
	cloth->getPositions(vetex);
	for (int i = 0; i < 2000; i++)
	{
		if (vetex[i].x == 0 && vetex[i].y == 0 || vetex[i].z == 0)              
		{
			//printf("i = %d\n", i); 
			break;
		}
		else
		{
			if (vetex[i].x > maxX)	maxX = vetex[i].x;
			if (vetex[i].y > maxY)	maxY = vetex[i].y;
			if (vetex[i].z > maxZ)	maxZ = vetex[i].z;

			if (vetex[i].x < minX)	minX = vetex[i].x;
			if (vetex[i].y < minY)	minY = vetex[i].y;
			if (vetex[i].z < minZ)	minZ = vetex[i].z;
			//printf("vetex %f %f %f\n", vetex[i].x, vetex[i].y, vetex[i].z);
			//outFile << vetex[i].x << "\t" << vetex[i].y << "\t" << vetex[i].z << endl;
		}
	}
	minPos.setx(minX);
	minPos.sety(minY);
	minPos.setz(minZ);

	maxPos.setx(maxX);
	maxPos.sety(maxY);
	maxPos.setz(maxZ);

	outFile << maxX << endl;
	outFile.close();
}
Example #15
0
void PxSingleActor::sweepTest( MatrixF *mat )
{
   NxVec3 nxCurrPos = getPosition();

   // If the position is zero, 
   // the parent hasn't been updated yet
   // and we don't even need to do the sweep test.
   // This is a fix for a problem that was happening
   // where on the add of the PxSingleActor, it would
   // set the position to a very small value because it would be getting a hit
   // even though the current position was 0.
   if ( nxCurrPos.isZero() )
      return;
   
   // Set up the flags and the query structure.
   NxU32 flags = NX_SF_STATICS | NX_SF_DYNAMICS;

   NxSweepQueryHit sweepResult;
   dMemset( &sweepResult, 0, sizeof( sweepResult ) );

   NxVec3 nxNewPos = mat->getPosition();

   // Get the velocity which will be our sweep direction and distance.
   NxVec3 nxDir = nxNewPos - nxCurrPos;
   if ( nxDir.isZero() )
      return;

   // Get the scene and do the sweep.
   mActor->wakeUp();
   mActor->linearSweep( nxDir, flags, NULL, 1, &sweepResult, NULL );

   if ( sweepResult.hitShape && sweepResult.t < nxDir.magnitude() )
   {
      nxDir.normalize();
      nxDir *= sweepResult.t;
      nxCurrPos += nxDir;

      mat->setPosition( Point3F( nxCurrPos.x, nxCurrPos.y, nxCurrPos.z ) );
   }
}
Example #16
0
NxFluid* CreateFluid(const NxVec3& pos, NxU32 sideNum, NxReal distance, NxScene* scene)
{
	float rad = sideNum*distance*0.5;
	for (unsigned i=0; i<sideNum; i++)
		for (unsigned j=0; j<sideNum; j++)
			for (unsigned k=0; k<sideNum; k++)
			{
				NxVec3 p = NxVec3(i*distance,j*distance,k*distance);
				if (p.distance(NxVec3(rad,rad,rad)) < rad)
				{
					p += pos;
					if(gParticleBufferNum< MAX_PARTICLES)
						gParticleBuffer[gParticleBufferNum++] = p;
				}
			}

	NxParticleData particles;

	//particles.maxParticles			= gParticleBufferCap;
	particles.numParticlesPtr		= &gParticleBufferNum;
	particles.bufferPos				= &gParticleBuffer[0].x;
	particles.bufferPosByteStride	= sizeof(NxVec3);

	//Create a fluid descriptor
	NxFluidDesc fluidDesc;
	fluidDesc.maxParticles = MAX_PARTICLES;
	fluidDesc.flags |= NX_FF_COLLISION_TWOWAY;
	fluidDesc.simulationMethod	= NX_F_SPH;
	fluidDesc.restParticlesPerMeter			= 5.0f;
	fluidDesc.motionLimitMultiplier			= 10.0f;
	fluidDesc.restDensity					= 1000.0f;
	fluidDesc.kernelRadiusMultiplier		= 1.6f;
	fluidDesc.stiffness						= 10.0f;
	fluidDesc.viscosity						= 50.0f;
	fluidDesc.damping						= 0.5f;
	fluidDesc.packetSizeMultiplier			= 16;
	fluidDesc.name                          = "fluid";

	fluidDesc.kernelRadiusMultiplier		= KERNEL_RADIUS_MULTIPLIER;
	fluidDesc.restParticlesPerMeter			= REST_PARTICLES_PER_METER;
	fluidDesc.motionLimitMultiplier			= MOTION_LIMIT_MULTIPLIER;
	fluidDesc.packetSizeMultiplier			= PACKET_SIZE_MULTIPLIER;
	fluidDesc.stiffness						= 40;  // 50
	fluidDesc.viscosity						= 22;
	fluidDesc.restDensity					= 1000;
	fluidDesc.damping						= 0;
// There are some API changes since 280 version, Fluid collision coefficients have been renamed, 
// E.g. NxFluidDesc::dynamicCollisionAdhesion is named NxFluidDesc::dynamicFrictionForDynamicShapes. 
#if NX_SDK_VERSION_NUMBER < 280
	fluidDesc.staticCollisionRestitution = 0.162f;
	fluidDesc.staticCollisionAdhesion = 0.146f;
	fluidDesc.dynamicCollisionRestitution = 0.5f;
	fluidDesc.dynamicCollisionAdhesion = 0.5f;
#else 
	fluidDesc.restitutionForStaticShapes = 0.162f;
	fluidDesc.dynamicFrictionForStaticShapes  = 0.146f;
	fluidDesc.restitutionForDynamicShapes = 0.5f;
	fluidDesc.dynamicFrictionForDynamicShapes = 0.5f;
#endif
	fluidDesc.simulationMethod				= NX_F_SPH;  //NX_F_NO_PARTICLE_INTERACTION;

	fluidDesc.initialParticleData			= particles;
	fluidDesc.particlesWriteData			= particles;

	if(!bHardwareFluid)
		fluidDesc.flags &= ~NX_FF_HARDWARE;

    fluid = gScene->createFluid(fluidDesc);
	if(!fluid)
	{
		fluidDesc.flags &= ~NX_FF_HARDWARE;
		bHardwareFluid = false;
		fluid = gScene->createFluid(fluidDesc);
	}
	
	assert(fluid != NULL);
	return fluid;
}
Example #17
0
void NxVehicle::updateVehicle(NxReal lastTimeStepSize)
{
	//printf("updating %x\n", this);
	
	NxReal distanceSteeringAxisCarTurnAxis = _steeringSteerPoint.x  - _steeringTurnPoint.x;
	NX_ASSERT(_steeringSteerPoint.z == _steeringTurnPoint.z);
	NxReal distance2 = 0;
	if (NxMath::abs(_steeringWheelState) > 0.01f)
		distance2 = distanceSteeringAxisCarTurnAxis / NxMath::tan(_steeringWheelState * _steeringMaxAngleRad);

	//printf("d1 = %2.3f, d2 = %2.3f, a1 = %2.3f, a2 = %2.3f\n",
	//	distanceSteeringAxisCarTurnAxis, distance2,
	//	_steeringWheelState, _steeringWheelState * _steeringMaxAngleRad);


	_lastTrailTime += lastTimeStepSize;

	if(_lastTrailTime > TRAIL_FREQUENCY)
	{
		_lastTrailTime = 0.0f;
	}

	NxU32 nbTouching = 0;
	NxU32 nbNotTouching = 0;
	NxU32 nbHandBrake = 0;
	for(NxU32 i = 0; i < _wheels.size(); i++)
	{
		NxWheel* wheel = _wheels[i];

		if (_lastTrailTime  == 0.0f)
		{
			if(_wheels[i]->hasGroundContact())
			{
				if (++_nextTrailSlot >= NUM_TRAIL_POINTS)
					_nextTrailSlot = 0;
				_trailBuffer[_nextTrailSlot] = _bodyActor->getGlobalPose() * _wheels[i]->getGroundContactPos();
			}
		}

		if(wheel->getWheelFlag(NX_WF_STEERABLE_INPUT))
		{
			if(distance2 != 0)
			{
				NxReal xPos = wheel->getWheelPos().x;
				NxReal zPos = wheel->getWheelPos().z;
				NxReal dz = -zPos + distance2;
				NxReal dx = xPos - _steeringTurnPoint.x;
				wheel->setAngle(NxMath::atan(dx/dz));
			} else {
				wheel->setAngle(0.f);
			}
			//printf("%2.3f\n", wheel->getAngle());

		} else if(wheel->getWheelFlag(NX_WF_STEERABLE_AUTO))
			{
			NxVec3 localVelocity = _bodyActor->getLocalPointVelocity(wheel->getWheelPos());
			NxQuat local2Global = _bodyActor->getGlobalOrientationQuat();
			local2Global.inverseRotate(localVelocity);
//			printf("%2.3f %2.3f %2.3f\n", wheel->getWheelPos().x,wheel->getWheelPos().y,wheel->getWheelPos().z);
			localVelocity.y = 0;
			if(localVelocity.magnitudeSquared() < 0.01f)
			{
				wheel->setAngle(0.0f);
			} else {
				localVelocity.normalize();
//				printf("localVelocity: %2.3f %2.3f\n", localVelocity.x, localVelocity.z);
				if(localVelocity.x < 0)
					localVelocity = -localVelocity;
				NxReal angle = NxMath::clamp((NxReal)atan(localVelocity.z / localVelocity.x), 0.3f, -0.3f);
				wheel->setAngle(angle);
			}
		}

		// now the acceleration part
		if(!wheel->getWheelFlag(NX_WF_ACCELERATED))
			continue;

		if(_handBrake && wheel->getWheelFlag(NX_WF_AFFECTED_BY_HANDBRAKE))
		{
			nbHandBrake++;
		} else {
			if (!wheel->hasGroundContact())
			{
				nbNotTouching++;
			} else {
				nbTouching++;
			}
		}
	}
	
	NxReal motorTorque = 0.0f; 
	if(nbTouching && NxMath::abs(_accelerationPedal) > 0.01f) 
	{
		NxReal axisTorque = _computeAxisTorque();
		NxReal wheelTorque = axisTorque / (NxReal)(_wheels.size() - nbHandBrake);
		NxReal wheelTorqueNotTouching = nbNotTouching>0?wheelTorque*(NxMath::pow(0.5f, (NxReal)nbNotTouching)):0;
		NxReal wheelTorqueTouching = wheelTorque - wheelTorqueNotTouching;
		motorTorque = wheelTorqueTouching / (NxReal)nbTouching; 
	} else {
		_updateRpms();
	}
//printf("wt: %f %f\n", motorTorque, _brakePedal);
	for(NxU32 i = 0; i < _wheels.size(); i++) 
	{
		NxWheel* wheel = _wheels[i];
		wheel->tick(_handBrake, motorTorque, _brakePedal, lastTimeStepSize);
	}

	//printf("---\n");
}
void Cloth::generateRegularMeshDesc(NxClothMeshDesc &desc, NxReal w, NxReal h, NxReal d, bool 
									texCoords)
{
	int numX = (int)(w / d) + 1;
	int numY = (int)(h / d) + 1;

	desc.numVertices				= (numX+1) * (numY+1);
	desc.numTriangles				= numX*numY*2;
	desc.pointStrideBytes			= sizeof(NxVec3);
	desc.triangleStrideBytes		= 3*sizeof(NxU32);
	desc.vertexMassStrideBytes		= sizeof(NxReal);
	desc.vertexFlagStrideBytes		= sizeof(NxU32);
	desc.points						= (NxVec3*)malloc(sizeof(NxVec3)*desc.numVertices);
	desc.triangles					= (NxU32*)malloc(sizeof(NxU32)*desc.numTriangles*3);
	desc.vertexMasses				= 0;
	desc.vertexFlags				= 0;
	desc.flags						= 0;

	mMaxVertices = TEAR_MEMORY_FACTOR * desc.numVertices;
	mMaxIndices  = 3 * desc.numTriangles;


	_geo_cloth = new osg::Geode;
	int i,j;
	// create particles - POINTS
	{
		osg::Geometry* pointsGeom = new osg::Geometry();
		osg::Vec3Array* vertices = new osg::Vec3Array;		

		NxVec3 *p = (NxVec3*)desc.points;
		for (i = 0; i <= numY; i++) {
			for (j = 0; j <= numX; j++) {
				p->set(d*j, 0.0f, d*i); 
				vertices->push_back(osg::Vec3f(d*j, d*i, 0.0f));
				p++;
			}
		}

		pointsGeom->setVertexArray(vertices);

		osg::Vec4Array* colors = new osg::Vec4Array;
		colors->push_back(osg::Vec4(1.0f,1.0f,0.0f,0.8f));

		pointsGeom->setColorArray(colors);
		pointsGeom->setColorBinding(osg::Geometry::BIND_OVERALL);


		// set the normal in the same way color.
		osg::Vec3Array* normals = new osg::Vec3Array;
		normals->push_back(osg::Vec3(0.0f,-1.0f,0.0f));
		pointsGeom->setNormalArray(normals);
		pointsGeom->setNormalBinding(osg::Geometry::BIND_OVERALL);
		
		osg::StateSet* stateSet = new osg::StateSet();
        
		pointsGeom->setStateSet(stateSet);
		pointsGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POINTS,0,vertices->size()));
		

		osg::Point* point = new osg::Point;
        point->setDistanceAttenuation(osg::Vec3(0.0,0.0000,0.05f));
		point->setSize(20.0f);
        stateSet->setAttribute(point);

		osg::PointSprite *sprite = new osg::PointSprite();
        stateSet->setTextureAttributeAndModes(0, sprite, osg::StateAttribute::ON);

		

		// add the points geometry to the geode.
		_geo_cloth->addDrawable(pointsGeom);
	}

	
	if (texCoords) {
		mTempTexCoords = (float *)malloc(sizeof(float)*2*TEAR_MEMORY_FACTOR*desc.numVertices);
		float *f = mTempTexCoords;
		float dx = 1.0f; if (numX > 0) dx /= numX;
		float dy = 1.0f; if (numY > 0) dy /= numY;
		for (i = 0; i <= numY; i++) {
			for (j = 0; j <= numX; j++) {
				*f++ = j*dx;
				*f++ = i*dy;
			}
		}
		
	
		mNumTempTexCoords = desc.numVertices;
	}
	else
	{
		mNumTempTexCoords = 0;
		mTempTexCoords = NULL;
	}

	NxU32 *id = (NxU32*)desc.triangles;
	for (i = 0; i < numY; i++) {
		for (j = 0; j < numX; j++) {
			NxU32 i0 = i * (numX+1) + j;
			NxU32 i1 = i0 + 1;
			NxU32 i2 = i0 + (numX+1);
			NxU32 i3 = i2 + 1;
			if ((j+i)%2) {
				*id++ = i0; *id++ = i2; *id++ = i1;
				*id++ = i1; *id++ = i2; *id++ = i3;
			}
			else {
				*id++ = i0; *id++ = i2; *id++ = i3;
				*id++ = i0; *id++ = i3; *id++ = i1;
			}
		}
	}

}
void Jumper::Flight::updatePhysics(void)
{
    SpinalCord* spinalCord = _jumper->getSpinalCord();
    Virtues* virtues = _jumper->getVirtues();
	CanopySimulator* canopy = _jumper->getDominantCanopy();

    // velocity of base jumper's body
    NxVec3 velocity = _phActor->getLinearVelocity();
    
    // horizontal velocity (including wind)
    NxVec3 velocityH = velocity; 
    velocityH += _jumper->getScene()->getWindAtPoint( _phActor->getGlobalPosition() );    
    velocityH.y = 0;

    // shock penalty
    float penalty = _jumper->getVirtues()->getControlPenalty( _jumper->getShock() );
    penalty = ( 1 - penalty );

    // update canopy controls
	// modifier to 50% input
	if (spinalCord->modifier) {
		float dt = _jumper->getDeltaTime();
		if (spinalCord->left > 0.5f && Gameplay::iGameplay->getActionChannel(iaLeft)->getTrigger()) Gameplay::iGameplay->getActionChannel(iaLeft)->downAmplitude(dt, 0.5f);
		if (spinalCord->right > 0.5f && Gameplay::iGameplay->getActionChannel(iaRight)->getTrigger()) Gameplay::iGameplay->getActionChannel(iaRight)->downAmplitude(dt, 0.5f);
		if (spinalCord->leftWarp > 0.5f && Gameplay::iGameplay->getActionChannel(iaLeftWarp)->getTrigger()) Gameplay::iGameplay->getActionChannel(iaLeftWarp)->downAmplitude(dt, 0.5f);
		if (spinalCord->rightWarp > 0.5f && Gameplay::iGameplay->getActionChannel(iaRightWarp)->getTrigger()) Gameplay::iGameplay->getActionChannel(iaRightWarp)->downAmplitude(dt, 0.5f);
		if (spinalCord->leftRearRiser > 0.5f && Gameplay::iGameplay->getActionChannel(iaLeftRearRiser)->getTrigger()) Gameplay::iGameplay->getActionChannel(iaLeftRearRiser)->downAmplitude(dt, 0.5f);
		if (spinalCord->rightRearRiser > 0.5f && Gameplay::iGameplay->getActionChannel(iaRightRearRiser)->getTrigger()) Gameplay::iGameplay->getActionChannel(iaRightRearRiser)->downAmplitude(dt, 0.5f);

		if (spinalCord->leftReserve > 0.5f && Gameplay::iGameplay->getActionChannel(iaReserveLeft)->getTrigger()) Gameplay::iGameplay->getActionChannel(iaReserveLeft)->downAmplitude(dt, 0.5f);
		if (spinalCord->rightReserve > 0.5f && Gameplay::iGameplay->getActionChannel(iaReserveRight)->getTrigger()) Gameplay::iGameplay->getActionChannel(iaReserveRight)->downAmplitude(dt, 0.5f);
		if (spinalCord->leftReserveWarp > 0.5f && Gameplay::iGameplay->getActionChannel(iaReserveLeftWarp)->getTrigger()) Gameplay::iGameplay->getActionChannel(iaReserveLeftWarp)->downAmplitude(dt, 0.5f);
		if (spinalCord->rightReserveWarp > 0.5f && Gameplay::iGameplay->getActionChannel(iaReserveRightWarp)->getTrigger()) Gameplay::iGameplay->getActionChannel(iaReserveRightWarp)->downAmplitude(dt, 0.5f);
		if (spinalCord->leftReserveRearRiser > 0.5f && Gameplay::iGameplay->getActionChannel(iaReserveLeftRearRiser)->getTrigger()) Gameplay::iGameplay->getActionChannel(iaReserveLeftRearRiser)->downAmplitude(dt, 0.5f);
		if (spinalCord->rightReserveRearRiser > 0.5f && Gameplay::iGameplay->getActionChannel(iaReserveRightRearRiser)->getTrigger()) Gameplay::iGameplay->getActionChannel(iaReserveRightRearRiser)->downAmplitude(dt, 0.5f);
	}


	// set risers
    canopy->setLeftWarpDeep( spinalCord->leftWarp * penalty );
    canopy->setRightWarpDeep( spinalCord->rightWarp * penalty );
    canopy->setLeftRearRiser( spinalCord->leftRearRiser * penalty );
    canopy->setRightRearRiser( spinalCord->rightRearRiser * penalty );

	canopy->setWLOToggles( spinalCord->trigger_wlo );
    canopy->setHookKnife( spinalCord->trigger_hook );


    // update reserve canopy controls
	if (_jumper->isPlayer() &&
		_jumper->getCanopyReserveSimulator() &&
		_jumper->getDominantCanopy() != _jumper->getCanopyReserveSimulator() && 
		_jumper->getCanopyReserveSimulator()->isOpened()) {

		// set toggles
		CanopySimulator *reserve_canopy = _jumper->getCanopyReserveSimulator();
		reserve_canopy->setLeftDeep( spinalCord->leftReserve * penalty );
		reserve_canopy->setRightDeep( spinalCord->rightReserve * penalty );
		// set risers
		reserve_canopy->setLeftWarpDeep( spinalCord->leftReserveWarp * penalty );
		reserve_canopy->setRightWarpDeep( spinalCord->rightReserveWarp * penalty );
		reserve_canopy->setLeftRearRiser( spinalCord->leftReserveRearRiser * penalty );
		reserve_canopy->setRightRearRiser( spinalCord->rightReserveRearRiser * penalty );

		reserve_canopy->setWLOToggles( spinalCord->trigger_wlo );
		reserve_canopy->setHookKnife( spinalCord->trigger_hook );
	}
    // determine animation sequence to be played
    _targetSequence = &passiveFlightSequence;

	// get total left and right input
	float totalInputLeft = 0.0f;
	float totalInputRight = 0.0f;
	float toggleLeft = spinalCord->left;
	float toggleRight = spinalCord->right;
	if (canopy->getLeftForcedDeep() != -1.0f) toggleLeft = 0.0f;
	if (canopy->getRightForcedDeep() != -1.0f) toggleRight = 0.0f;

	// hard toggle input if unstowing
	if (canopy->getLeftStowed() && spinalCord->trigger_left) {
		toggleLeft = 0.75f;
	}
	if (canopy->getRightStowed() && spinalCord->trigger_right) {
		toggleRight = 0.75f;
	}

	// set toggles
	canopy->setLeftDeep( spinalCord->left * penalty );
	canopy->setRightDeep( spinalCord->right * penalty );

	if (toggleLeft > spinalCord->leftRearRiser && toggleLeft > spinalCord->leftWarp) {
		totalInputLeft = toggleLeft;
	} else if (spinalCord->leftRearRiser > toggleLeft && spinalCord->leftRearRiser > spinalCord->leftWarp) {
		totalInputLeft = spinalCord->leftRearRiser;
	} else {
		totalInputLeft = spinalCord->leftWarp;
	}
	if (toggleRight > spinalCord->rightRearRiser && toggleRight > spinalCord->rightWarp) {
		totalInputRight = toggleRight;
	} else if (spinalCord->rightRearRiser > toggleRight && spinalCord->rightRearRiser > spinalCord->rightWarp) {
		totalInputRight = spinalCord->rightRearRiser;
	} else {
		totalInputRight = spinalCord->rightWarp;
	}


	if( totalInputLeft != 0 && totalInputRight == 0 ) {
		if (canopy->getLeftStowed() && spinalCord->trigger_left) {
			_targetSequence = &unstowLeftSequence;
		} else if (spinalCord->modifier) {
			_targetSequence = &steerLeftSequenceHalf;
		} else {
			_targetSequence = &steerLeftSequence;
		}
	}
	if( totalInputRight != 0 && totalInputLeft == 0 ) {
		if (canopy->getRightStowed() && spinalCord->trigger_right) {
			_targetSequence = &unstowRightSequence;
		} else if (spinalCord->modifier) {
			_targetSequence = &steerRightSequenceHalf;
		} else {
			_targetSequence = &steerRightSequence;
		}
	}
	if( totalInputLeft != 0 && totalInputRight != 0 ) {
		if (canopy->getLeftStowed() || canopy->getRightStowed()) {
			_targetSequence = &groupingUnstowSequence;
		} else if (spinalCord->modifier) {
			_targetSequence = &groupingSequenceHalf;
		} else {
			_targetSequence = &groupingSequence;
		}
	}

	// unstow toggles
	if (spinalCord->left > 0.1f) {
		canopy->setLeftStowed(false);
	}
	if (spinalCord->right > 0.1f) {
		canopy->setRightStowed(false);
	}

    // local coordinate system of base jumper
    NxMat34 pose = _phActor->getGlobalPose();
    NxVec3 x = pose.M.getColumn(0);
    NxVec3 y = pose.M.getColumn(1);
    NxVec3 z = pose.M.getColumn(2);



	// altitude [m]
	//NxVec3 pos = _phActor->getGlobalPosition();
	//const float altitude = pos.y;
	//const float arch_pose_area = 1.9f;

	//// air density: converted to linear from barometric equation [0:10] km altitude
	//// http://www.denysschen.com/catalogue/density.aspx
	//const float AirDensityOld = altitude <= 10000.0f ? (1.196f - 0.0000826f * altitude) : (0.27f);

	//// add drag force
	//float Cd = 0.4f;	// altitude suit = 0.4f
	//const float mTracking = database::Suit::getRecord( _jumper->getVirtues()->equipment.suit.id )->mTracking;
	//Cd *= mTracking;
	//// Drag force vector
	//NxVec3 VecFd = -_phActor->getLinearVelocity();
	//VecFd.normalize();

	//float Fd = 0.5f * AirDensityOld * velocity.magnitudeSquared() * Cd * arch_pose_area * getCore()->getRandToolkit()->getUniform(0.94f, 1.06f);
	//_phActor->addForceAtLocalPos(Fd*VecFd, NxVec3(0, -3.0f, 0));

    // air resistance coefficient
    const float ARmult = 2.5f;
    float AR = ARmult * virtues->getTrackingAirResistance();
    if( database::Suit::getRecord( virtues->equipment.suit.id )->wingsuit )
    {
        AR = ARmult * virtues->getFrogAirResistance();
    }

    // terminal velocity
    const float Vt = sqrt( 9.8f * _phActor->getMass() / AR );
    const float It = velocity.magnitude() / Vt;

    NxVec3 dir = velocity * -1;
    dir.normalize();

    // air resistance force
    const NxVec3 Far = dir * getAirResistancePower( velocity.magnitude() / Vt ) * _phActor->getMass() * 9.8f;

    // finalize motion equation    
    _phActor->addForce( Far );
}
Example #20
0
// -----------------------------------------------------------------------
void MyCloth::generateRegularMeshDesc(NxClothMeshDesc &desc, NxReal w, NxReal h, NxReal d, bool texCoords)
{
	int numX = (int)(w / d) + 1;
	int numY = (int)(h / d) + 1;

	desc.numVertices				= (numX+1) * (numY+1);
	desc.numTriangles				= numX*numY*2;
	desc.pointStrideBytes			= sizeof(NxVec3);
	desc.triangleStrideBytes		= 3*sizeof(NxU32);
	desc.vertexMassStrideBytes		= sizeof(NxReal);
	desc.vertexFlagStrideBytes		= sizeof(NxU32);
	desc.points						= (NxVec3*)malloc(sizeof(NxVec3)*desc.numVertices);
	desc.triangles					= (NxU32*)malloc(sizeof(NxU32)*desc.numTriangles*3);
	desc.vertexMasses				= 0;
	desc.vertexFlags				= 0;
	desc.flags						= 0;

	mMaxVertices = desc.numVertices;
	mMaxIndices  = 3 * desc.numTriangles;

	int i,j;
	NxVec3 *p = (NxVec3*)desc.points;
	for (i = 0; i <= numY; i++) {
		for (j = 0; j <= numX; j++) {
			p->set(d*j, 0.0f, d*i); 
			p++;
		}
	}

	if (texCoords) {
		mTempTexCoords = (GLfloat *)malloc(sizeof(GLfloat)*2*desc.numVertices);
		GLfloat *f = mTempTexCoords;
		GLfloat dx = 1.0f; if (numX > 0) dx /= numX;
		GLfloat dy = 1.0f; if (numY > 0) dy /= numY;
		for (i = 0; i <= numY; i++) {
			for (j = 0; j <= numX; j++) {
				*f++ = j*dx;
				*f++ = i*dy;
			}
		}
		mNumTempTexCoords = desc.numVertices;
	}
	else
	{
		mNumTempTexCoords = 0;
		mTempTexCoords = NULL;
	}

	NxU32 *id = (NxU32*)desc.triangles;
	for (i = 0; i < numY; i++) {
		for (j = 0; j < numX; j++) {
			NxU32 i0 = i * (numX+1) + j;
			NxU32 i1 = i0 + 1;
			NxU32 i2 = i0 + (numX+1);
			NxU32 i3 = i2 + 1;
			if ((j+i)%2) {
				*id++ = i0; *id++ = i2; *id++ = i1;
				*id++ = i1; *id++ = i2; *id++ = i3;
			}
			else {
				*id++ = i0; *id++ = i2; *id++ = i3;
				*id++ = i0; *id++ = i3; *id++ = i1;
			}
		}
	}

}
void PxCloth::_initClothMesh()
{
   // Make sure we can change the world.
   mWorld->releaseWriteLock();

   _releaseMesh();

   // Must have at least 2 verts.
   mPatchVerts.x = getMax( 2, mPatchVerts.x );
   mPatchVerts.y = getMax( 2, mPatchVerts.y );

   // Generate a uniform cloth patch, 
   // w and h are the width and height, 
   // d is the distance between vertices.  
   mNumVertices = mPatchVerts.x * mPatchVerts.y;
   mNumIndices = (mPatchVerts.x-1) * (mPatchVerts.y-1) * 2;

   NxClothMeshDesc desc;
   desc.numVertices = mNumVertices;    
   desc.numTriangles = mNumIndices;   
   desc.pointStrideBytes = sizeof(NxVec3);    
   desc.triangleStrideBytes = 3*sizeof(NxU32);    
   desc.points = (NxVec3*)dMalloc(sizeof(NxVec3)*desc.numVertices);    
   desc.triangles = (NxU32*)dMalloc(sizeof(NxU32)*desc.numTriangles*3);    
   desc.flags = 0;    

   U32 i,j;    
   NxVec3 *p = (NxVec3*)desc.points;    
   
   F32 patchWidth = mPatchSize.x / (F32)( mPatchVerts.x - 1 );
   F32 patchHeight = mPatchSize.y / (F32)( mPatchVerts.y - 1 );

   for (i = 0; i < mPatchVerts.y; i++) 
   {        
      for (j = 0; j < mPatchVerts.x; j++) 
      {            
         p->set( patchWidth * j, 0.0f, patchHeight * i );     
         p++;
      }    
   }

   NxU32 *id = (NxU32*)desc.triangles;    
   
   for (i = 0; i < mPatchVerts.y-1; i++) 
   {        
      for (j = 0; j < mPatchVerts.x-1; j++) 
      {            
         NxU32 i0 = i * mPatchVerts.x + j;            
         NxU32 i1 = i0 + 1;            
         NxU32 i2 = i0 + mPatchVerts.x;            
         NxU32 i3 = i2 + 1;            
         if ( (j+i) % 2 ) 
         {                
            *id++ = i0; 
            *id++ = i2; 
            *id++ = i1;                
            *id++ = i1; 
            *id++ = i2; 
            *id++ = i3;            
         }            
         else 
         {                
            *id++ = i0; 
            *id++ = i2; 
            *id++ = i3;                
            *id++ = i0; 
            *id++ = i3; 
            *id++ = i1;            
         }        
      }    
   }   
   
   NxCookingInterface *cooker = PxWorld::getCooking();
   cooker->NxInitCooking();

   // Ok... cook the mesh!
   NxCookingParams params;
   params.targetPlatform = PLATFORM_PC;
   params.skinWidth = 0.01f;
   params.hintCollisionSpeed = false;

   cooker->NxSetCookingParams( params );
  
   PxMemStream cooked;	
  
   if ( cooker->NxCookClothMesh( desc, cooked ) )
   {
      cooked.resetPosition();
      mClothMesh = gPhysicsSDK->createClothMesh( cooked );
   }
   
   cooker->NxCloseCooking();
   
   NxVec3 *ppoints = (NxVec3*)desc.points;
   NxU32 *triangs = (NxU32*)desc.triangles;

   dFree( ppoints );
   dFree( triangs );

   if ( mClothMesh )
      _initReceiveBuffers();
}
Example #22
0
// Using swept code & direct position update (no physics engine)
// This function is the generic character controller logic, valid for all swept volumes
void SweepTest::MoveCharacter(
					void* user_data,
					void* user_data2,
					SweptVolume& volume,
					const NxVec3& direction,
					NxU32 nb_boxes, const NxExtendedBounds3* boxes, const void** box_user_data,
					NxU32 nb_capsules, const NxExtendedCapsule* capsules, const void** capsule_user_data,
					NxU32 groups, float min_dist,
					NxU32& collision_flags,
					const NxGroupsMask* groupsMask,
					bool constrainedClimbingMode
					 )
{
	mHitNonWalkable = false;
	NxU32 CollisionFlags = 0;
	const NxU32 MaxIter = mMaxIter;	// 1 for "collide and stop"
	const NxU32 MaxIterUp = MaxIter;
	const NxU32 MaxIterSides = MaxIter;
//	const NxU32 MaxIterDown = gWalkExperiment ? MaxIter : 1;
	const NxU32 MaxIterDown = 1;

	// ### this causes the artificial gap on top of chars
	float StepOffset = mStepOffset;	// Default step offset can be cancelled in some cases.

	// Save initial height
	Extended OriginalHeight = volume.mCenter[mUpDirection];
	Extended OriginalBottomPoint = OriginalHeight - volume.mHalfHeight;	// UBI

	// TEST! Disable auto-step when flying. Not sure this is really useful.
	if(direction[mUpDirection]>0.0f)
		StepOffset = 0.0f;

	// Decompose motion into 3 independent motions: up, side, down
	// - if the motion is purely down (gravity only), the up part is needed to fight accuracy issues. For example if the
	// character is already touching the geometry a bit, the down sweep test might have troubles. If we first move it above
	// the geometry, the problems disappear.
	// - if the motion is lateral (character moving forward under normal gravity) the decomposition provides the autostep feature
	// - if the motion is purely up, the down part can be skipped

	NxVec3 UpVector(0.0f, 0.0f, 0.0f);
	NxVec3 DownVector(0.0f, 0.0f, 0.0f);

	if(direction[mUpDirection]<0.0f)	DownVector[mUpDirection] = direction[mUpDirection];
	else								UpVector[mUpDirection] = direction[mUpDirection];

	NxVec3 SideVector = direction;
	SideVector[mUpDirection] = 0.0f;

	// If the side motion is zero, i.e. if the character is not really moving, disable auto-step.
	if(!SideVector.isZero())
		UpVector[mUpDirection] += StepOffset;

	// ==========[ Initial volume query ]===========================
	if(1)
	{
		NxVec3 MotionExtents = UpVector;
		MotionExtents.max(SideVector);
		MotionExtents.max(DownVector);

		NxExtendedBounds3 TemporalBox;
		volume.ComputeTemporalBox(*this, TemporalBox, volume.mCenter, MotionExtents);

		// Gather touched geoms
		UpdateTouchedGeoms(user_data, volume,
							nb_boxes, boxes, box_user_data,
							nb_capsules, capsules, capsule_user_data,
							groups, TemporalBox, groupsMask);
	}

	// ==========[ UP PASS ]===========================

	mCachedTriIndexIndex = 0;
	const bool PerformUpPass = true;
	NxU32 NbCollisions=0;

	if(PerformUpPass)
	{
		// Prevent user callback for up motion. This up displacement is artificial, and only needed for auto-stepping.
		// If we call the user for this, we might eventually apply upward forces to objects resting on top of us, even
		// if we visually don't move. This produces weird-looking motions.
		mValidateCallback = false;

		// In the walk-experiment we explicitely want to ban any up motions, to avoid characters climbing slopes they shouldn't climb.
		// So let's bypass the whole up pass.
		if(!mWalkExperiment)
		{
			// ### MaxIter here seems to "solve" the V bug
			if(DoSweepTest(user_data,
				user_data2,
				nb_boxes, boxes, box_user_data,
				nb_capsules, capsules, capsule_user_data,
				volume, UpVector, MaxIterUp, &NbCollisions, groups, min_dist, groupsMask))
			{
				if(NbCollisions)
				{
					CollisionFlags |= NXCC_COLLISION_UP;

					// Clamp step offset to make sure we don't undo more than what we did
					Extended Delta = volume.mCenter[mUpDirection] - OriginalHeight;
					if(Delta<StepOffset)
					{
						StepOffset=float(Delta);
					}
				}
			}
		}
	}

	// ==========[ SIDE PASS ]===========================

	mCachedTriIndexIndex = 1;
	mValidateCallback = true;
	const bool PerformSidePass = true;

	if(PerformSidePass)
	{
		NbCollisions=0;
		if(DoSweepTest(user_data,
			user_data2,
			nb_boxes, boxes, box_user_data,
			nb_capsules, capsules, capsule_user_data,
			volume, SideVector, MaxIterSides, &NbCollisions, groups, min_dist, groupsMask))
		{
			if(NbCollisions)	CollisionFlags |= NXCC_COLLISION_SIDES;
		}
	}

	// ==========[ DOWN PASS ]===========================

	mCachedTriIndexIndex = 2;
	const bool PerformDownPass = true;

	if(PerformDownPass)
	{
		NbCollisions=0;

		if(!SideVector.isZero())	// We disabled that before so we don't have to undo it in that case
			DownVector[mUpDirection] -= StepOffset;	// Undo our artificial up motion

		mValidTri = false;

		// min_dist actually makes a big difference :(
		// AAARRRGGH: if we get culled because of min_dist here, mValidTri never becomes valid!
		if(DoSweepTest(user_data,
			user_data2,
			nb_boxes, boxes, box_user_data,
			nb_capsules, capsules, capsule_user_data,
			volume, DownVector, MaxIterDown, &NbCollisions, groups, min_dist, groupsMask, true))
		{
			if(NbCollisions)
			{
				CollisionFlags |= NXCC_COLLISION_DOWN;
				if(mHandleSlope)	// PT: I think the following fix shouldn't be performed when mHandleSlope is false.
				{
					// PT: the following code is responsible for a weird capsule behaviour,
					// when colliding against a highly tesselated terrain:
					// - with a large direction vector, the capsule gets stuck against some part of the terrain
					// - with a slower direction vector (but in the same direction!) the capsule manages to move
					// I will keep that code nonetheless, since it seems to be useful for them.

					// constrainedClimbingMode
					if ( constrainedClimbingMode && mContactPointHeight > OriginalBottomPoint + StepOffset)
					{
						mHitNonWalkable = true;
						if(!mWalkExperiment)
							return;
					}
					//~constrainedClimbingMode
				}
			}
		}

		// TEST: do another down pass if we're on a non-walkable poly
		// ### kind of works but still not perfect
		// ### could it be because we zero the Y impulse later?
		// ### also check clamped response vectors
		if(mHandleSlope && mValidTri && direction[mUpDirection]<0.0f)
		{
			NxVec3 Normal;
		#ifdef USE_CONTACT_NORMAL_FOR_SLOPE_TEST
			Normal = mCN;
		#else
			mTouched.normal(Normal);
		#endif
		//	if(fabsf(Normal|NxVec3(0.0f, 1.0f, 0.0f))<cosf(45.0f*DEGTORAD))
			if(Normal[mUpDirection]>=0.0f && Normal[mUpDirection]<mSlopeLimit)
			{
				mHitNonWalkable = true;
				// Early exit if we're going to run this again anyway...
				if(!mWalkExperiment)	return;
		/*		CatchScene()->GetRenderer()->AddLine(mTouched.mVerts[0], mTouched.mVerts[1], ARGB_YELLOW);
				CatchScene()->GetRenderer()->AddLine(mTouched.mVerts[0], mTouched.mVerts[2], ARGB_YELLOW);
				CatchScene()->GetRenderer()->AddLine(mTouched.mVerts[1], mTouched.mVerts[2], ARGB_YELLOW);
		*/

				// ==========[ WALK EXPERIMENT ]===========================

				mNormalizeResponse=true;

				Extended Delta = volume.mCenter[mUpDirection] > OriginalHeight ? volume.mCenter[mUpDirection] - OriginalHeight : 0.0f;
				Delta += fabsf(direction[mUpDirection]);
				Extended Recover = Delta;

				NbCollisions=0;
				const Extended MD = Recover < min_dist ? Recover/float(MaxIter) : min_dist;

				NxVec3 RecoverPoint(0,0,0);
				RecoverPoint[mUpDirection]=-float(Recover);

				if(DoSweepTest(user_data,
					user_data2,
					nb_boxes, boxes, box_user_data,
					nb_capsules, capsules, capsule_user_data,
					volume, RecoverPoint, MaxIter, &NbCollisions, groups, float(MD), groupsMask))
				{
		//			if(NbCollisions)	CollisionFlags |= COLLISION_Y_DOWN;
					// PT: why did we do this ? Removed for now. It creates a bug (non registered event) when we land on a steep poly.
					// However this might have been needed when we were sliding on those polygons, and we didn't want the land anim to
					// start while we were sliding.
		//			if(NbCollisions)	CollisionFlags &= ~NXCC_COLLISION_DOWN;
				}
				mNormalizeResponse=false;
			}
		}
	}

	// Setup new collision flags
	collision_flags = CollisionFlags;
}
Example #23
0
// This is the generic sweep test for all swept volumes, but not character-controller specific
bool SweepTest::DoSweepTest(void* user_data,
							void* user_data2,
							NxU32 nb_boxes, const NxExtendedBounds3* boxes, const void** box_user_data,
							NxU32 nb_capsules, const NxExtendedCapsule* capsules, const void** capsule_user_data,
							SweptVolume& swept_volume,
							const NxVec3& direction, NxU32 max_iter, NxU32* nb_collisions,
							NxU32 group_flags, float min_dist, const NxGroupsMask* groupsMask, bool down_pass)
{
	// Early exit when motion is zero. Since the motion is decomposed into several vectors
	// and this function is called for each of them, it actually happens quite often.
	if(direction.isZero())
		return false;

	bool HasMoved = false;
	mValidTri = false;

	NxExtendedVec3 CurrentPosition = swept_volume.mCenter;
	NxExtendedVec3 TargetPosition = swept_volume.mCenter;
	TargetPosition += direction;

	NxU32 NbCollisions = 0;
	while(max_iter--)
	{
		gNbIters++;
		// Compute current direction
		NxVec3 CurrentDirection = TargetPosition - CurrentPosition;

		// Make sure the new TBV is still valid
		{
			// Compute temporal bounding box. We could use a capsule or an OBB instead:
			// - the volume would be smaller
			// - but the query would be slower
			// Overall it's unclear whether it's worth it or not.
			// TODO: optimize this part ?
			NxExtendedBounds3 TemporalBox;
			swept_volume.ComputeTemporalBox(*this, TemporalBox, CurrentPosition, CurrentDirection);

			// Gather touched geoms
			UpdateTouchedGeoms(user_data, swept_volume,
								nb_boxes, boxes, box_user_data,
								nb_capsules, capsules, capsule_user_data,
								group_flags, TemporalBox, groupsMask);
		}

		const float Length = CurrentDirection.magnitude();
		if(Length<min_dist)	break;

		CurrentDirection /= Length;

		// From Quake2: "if velocity is against the original velocity, stop dead to avoid tiny occilations in sloping corners"
		if((CurrentDirection|direction) <= 0.0f)	break;

		// From this point, we're going to update the position at least once
		HasMoved = true;

		// Find closest collision
		SweptContact C;
		C.mDistance = Length + mSkinWidth;

		if(!CollideGeoms(this, swept_volume, mGeomStream, CurrentPosition, CurrentDirection, C))
		{
			// no collision found => move to desired position
			CurrentPosition = TargetPosition;
			break;
		}

		ASSERT(C.mGeom);	// If we reach this point, we must have touched a geom

		if(C.mGeom->mType==TOUCHED_USER_BOX || C.mGeom->mType==TOUCHED_USER_CAPSULE)
		{
			// We touched a user object, typically another CCT
			if(mValidateCallback)	UserHitCallback(user_data2, C, CurrentDirection, Length);

			// Trying to solve the following problem:
			// - by default, the CCT "friction" is infinite, i.e. a CCT will not slide on a slope (this is by design)
			// - this produces bad results when a capsule CCT stands on top of another capsule CCT, without sliding. Visually it looks
			//   like the character is standing on the other character's head, it looks bad. So, here, we would like to let the CCT
			//   slide away, i.e. we don't want friction.
			// So here we simply increase the number of iterations (== let the CCT slide) when the first down collision is with another CCT.
			if(down_pass && !NbCollisions)
				max_iter += 9;
		}
		else
		{
			// We touched a normal object
#ifdef USE_CONTACT_NORMAL_FOR_SLOPE_TEST
			mValidTri = true;
			mCN = C.mWorldNormal;
#else
			if(C.mIndex!=INVALID_ID)
			{
				mValidTri = true;
				mTouched = mWorldTriangles[C.mIndex];
			}
#endif
			{
				if(mValidateCallback)	ShapeHitCallback(user_data2, C, CurrentDirection, Length);
			}
		}

		NbCollisions++;
		mContactPointHeight = (float)C.mWorldPos[mUpDirection];	// UBI

		const float DynSkin = mSkinWidth;

		if(C.mDistance>DynSkin/*+0.01f*/)
			CurrentPosition += CurrentDirection*(C.mDistance-DynSkin);

		NxVec3 WorldNormal = C.mWorldNormal;
		if(mWalkExperiment)
		{
			// Make sure the auto-step doesn't bypass this !
			WorldNormal[mUpDirection]=0.0f;
			WorldNormal.normalize();
		}

		const float Bump = 0.0f;	// ### doesn't work when !=0 because of Quake2 hack!
		const float Friction = 1.0f;
		CollisionResponse(TargetPosition, CurrentPosition, CurrentDirection, WorldNormal, Bump, Friction, mNormalizeResponse);
	}

	if(nb_collisions)	*nb_collisions = NbCollisions;

	// Final box position that should be reflected in the graphics engine
	swept_volume.mCenter = CurrentPosition;

	// If we didn't move, don't update the box position at all (keeping possible lazy-evaluated structures valid)
	return HasMoved;
}
hsVectorStream* plPhysXCooking::IMakePolytope(const plMaxMeshExtractor::NeutralMesh& inMesh)
{
    hsBool success=0;
    std::vector<hsPoint3> outCloud;
    hsPoint3 offset;
    int numPlanes=26;
    float planeMax[26];
    int indexMax[26];
    hsPoint3 AABBMin(FLT_MAX,FLT_MAX,FLT_MAX);
    hsPoint3 AABBMax(-FLT_MAX,-FLT_MAX,-FLT_MAX);
    //prep
    NxVec3* vectors = new NxVec3[26];
    
    int curvec=0;
    for(int xcomp= -1;xcomp<2;xcomp++)
    {
        for(int ycomp= -1;ycomp<2;ycomp++)
        {
            for(int zcomp= -1;zcomp<2;zcomp++)
            {
                if(!((xcomp==0)&&(ycomp==0)&&(zcomp==0)))
                {
                    vectors[curvec].set((float)(xcomp),(float)(ycomp),(float)(zcomp));
                    vectors[curvec].normalize();
                    planeMax[curvec]=(-FLT_MAX);
                    //indexMax[curvec]=0;
                    curvec++;
                }
            }
        }
    }
    /*
    for(int i=0;i<26;i++)
    {//make your max and mins
        planeMax[i]=(-FLT_MAX);
    }
    */
    hsPoint3 centroid(0.0f,0.0f,0.0f);
    for(int i=0;i<inMesh.fNumVerts;i++) centroid+=inMesh.fVerts[i];
    centroid=centroid/(float)inMesh.fNumVerts;
    //temp
    NxVec3* nxLocs=new NxVec3[inMesh.fNumVerts];
    NxVec3* nxLocs2=new NxVec3[inMesh.fNumVerts];
    for(int i=0;i<inMesh.fNumVerts;i++)
    {
        hsPoint3 temppt=inMesh.fVerts[i] - centroid;
        nxLocs[i]=plPXConvert::Point(temppt);
    }
    NxMat33 rot;
    NxVec3 eigen;
    PCA(nxLocs,inMesh.fNumVerts,rot);
    NxMat33 invrot;
    rot.getInverse(invrot);
    for(int i=0; i<inMesh.fNumVerts;i++)
    {
        nxLocs2[i]=invrot*nxLocs[i];
    }
    for(int i=0;i<inMesh.fNumVerts;i++)
    {
        for(int plane=0;plane<26;plane++)
        {
            float dist=nxLocs2[i].dot(vectors[plane]);
            if(dist>=planeMax[plane])
            {
                planeMax[plane]=dist;
                indexMax[plane]=i;
            }
        }
    }
    for(int i=0;i<inMesh.fNumVerts;i++)
    {
        AABBMin.fX = hsMinimum(nxLocs2[i].x, AABBMin.fX);
        AABBMin.fY = hsMinimum(nxLocs2[i].y, AABBMin.fY);
        AABBMin.fZ = hsMinimum(nxLocs2[i].z, AABBMin.fZ);
        AABBMax.fX = hsMaximum(nxLocs2[i].x, AABBMax.fX);
        AABBMax.fY = hsMaximum(nxLocs2[i].y, AABBMax.fY);
        AABBMax.fZ = hsMaximum(nxLocs2[i].z, AABBMax.fZ);
    }
    
    int resultingPoints=0;
    for(int i=0;i<26;i++)
    {
        for(int j=0;j<26;j++)
        {
            for(int k=0;k<26;k++)
            {   
                NxVec3 res;
                if(ThreePlaneIntersect(vectors[i],nxLocs2[indexMax[i]],vectors[j],nxLocs2[indexMax[j]], vectors[k],nxLocs2[indexMax[k]],res))
                {
                    //check it is within all slabs
                    bool within=true;
                    int curplane=0;
                    do
                    {
                        float intersecdist=res.dot(vectors[curplane]);
                        if((intersecdist-planeMax[curplane])>0.0001)

                        {
                            within=false;
                    
                        }
                        curplane++;
                    }
                    while((curplane<26)&&within);
                    if(within)
//                  if((res.x>=AABBMin.fX)&&(res.x<=AABBMax.fX)&&
//                      (res.y>=AABBMin.fY)&&(res.y<=AABBMax.fY)&&
//                      (res.z>=AABBMin.fZ)&&(res.z<=AABBMax.fZ))
                    {
                        NxVec3 reverted;
                        reverted=rot*res;
                        reverted.x=reverted.x +centroid.fX;
                        reverted.y=reverted.y +centroid.fY;
                        reverted.z=reverted.z +centroid.fZ;
                        hsPoint3 out;
                        out=plPXConvert::Point(reverted);
                        outCloud.push_back(out);
                    }
                }
            }
        }
    }
    
    //planes discovered
    //this is'nt  right
    //cleanup
    offset=centroid;

    delete[] vectors;
        hsPoint3* pointages=new hsPoint3[outCloud.size()];
    for(int x=0;x<outCloud.size();x++)pointages[x]=outCloud[x];
    hsVectorStream* vectorstrm;
    vectorstrm= CookHull(outCloud.size(),pointages,true);
    delete[] pointages; 
    delete[] nxLocs;
    delete[] nxLocs2;
    return vectorstrm;
}
Example #25
0
// ----------------------------------------------------------------------
bool ObjMesh::loadFromObjFile(char *filename)
{
	FILE *f = fopen(filename, "r");
	if (!f) return false;
	clear();
	ObjMeshString s, subs[maxVerticesPerFace];
	ObjMeshString mtllib, matName;

	mHasTextureCoords = false;
	mHasNormals = false;

	strcpy(mtllib, "");
	int materialNr = -1;
	int i,j;
	NxVec3 v;
	ObjMeshTriangle t;
	TexCoord tc;

	std::vector<NxVec3> centermVertices;
	std::vector<TexCoord> centermTexCoords;
	std::vector<NxVec3> centerNormals;

	extractPath(filename);

	while (!feof(f)) {
		if (fgets(s, OBJ_MESH_STRING_LEN, f) == NULL) break;

		if (strncmp(s, "mtllib", 6) == 0) {  // material library
			sscanf(&s[7], "%s", mtllib);
			importMtlFile(mtllib);
		}
		else if (strncmp(s, "usemtl", 6) == 0) {  // use material
			sscanf(&s[7], "%s", matName);
			materialNr = 0;
			int numMaterials = (int)mMaterials.size();
			while (materialNr < numMaterials &&
				   strcasecmp(mMaterials[materialNr].name, matName) != 0)
				materialNr++;
			if (materialNr >= numMaterials) 
				materialNr = -1;
		}
		else if (strncmp(s, "v ", 2) == 0) {	// vertex
			sscanf(s, "v %f %f %f", &v.x, &v.y, &v.z);
			mVertices.push_back(v);
		}
		else if (strncmp(s, "vn ", 3) == 0) {	// normal
			sscanf(s, "vn %f %f %f", &v.x, &v.y, &v.z);
			mNormals.push_back(v);
		}
		else if (strncmp(s, "vt ", 3) == 0) {	// texture coords
			sscanf(s, "vt %f %f", &tc.u, &tc.v);
			mTexCoords.push_back(tc);
		}
		else if (strncmp(s, "f ", 2) == 0) {	// face
			int nr;
			nr = sscanf(s, "f %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s",
			subs[0], subs[1], subs[2], subs[3], subs[4],
			subs[5], subs[6], subs[7], subs[8], subs[9],
			subs[10], subs[11], subs[12],subs[13], subs[14]);
			int vertNr[maxVerticesPerFace], texNr[maxVerticesPerFace];
			int normalNr[maxVerticesPerFace];
			for (i = 0; i < nr; i++) {
				int refs[3];
				parseRef(subs[i], refs);
				vertNr[i] = refs[0]-1;
				texNr[i] = refs[1]-1;
				normalNr[i] = refs[2]-1;
			}
			if (nr <= 4) {	// simple non-singular triangle or quad
				if (vertNr[0] != vertNr[1] && vertNr[1] != vertNr[2] && vertNr[2] != vertNr[0]) {
					t.init();
					t.vertexNr[0] = vertNr[0];
					t.vertexNr[1] = vertNr[1];
					t.vertexNr[2] = vertNr[2];
					t.normalNr[0] = normalNr[0];
					t.normalNr[1] = normalNr[1];
					t.normalNr[2] = normalNr[2];
					t.texCoordNr[0] = texNr[0];
					t.texCoordNr[1] = texNr[1];
					t.texCoordNr[2] = texNr[2];
					t.materialNr = materialNr;
					mTriangles.push_back(t);
				}
				if (nr == 4) {	// non-singular quad -> generate a second triangle
					if (vertNr[2] != vertNr[3] && vertNr[3] != vertNr[0] && vertNr[0] != vertNr[2]) {
						t.init();
						t.vertexNr[0] = vertNr[2];
						t.vertexNr[1] = vertNr[3];
						t.vertexNr[2] = vertNr[0];
						t.normalNr[0] = normalNr[2];
						t.normalNr[1] = normalNr[3];
						t.normalNr[2] = normalNr[0];
						t.texCoordNr[0] = texNr[0];
						t.texCoordNr[1] = texNr[1];
						t.texCoordNr[2] = texNr[2];
						t.materialNr = materialNr;
						mTriangles.push_back(t);
					}
				}
			}
			else {	// polygonal face

				// compute center properties
				NxVec3 centerPos(0.0f, 0.0f, 0.0f);
				TexCoord centerTex; centerTex.zero();
				for (i = 0; i < nr; i++) {
					centerPos += mVertices[vertNr[i]];
					if (texNr[i] >= 0) centerTex += mTexCoords[texNr[i]];
				}
				centerPos /= (float)nr;
				centerTex /= (float)nr;
				NxVec3 d1 = centerPos - mVertices[vertNr[0]];
				NxVec3 d2 = centerPos - mVertices[vertNr[1]];
				NxVec3 centerNormal = d1.cross(d2); centerNormal.normalize();

				// add center vertex
				centermVertices.push_back(centerPos);
				centermTexCoords.push_back(centerTex);
				centerNormals.push_back(centerNormal);

				// add surrounding elements
				for (i = 0; i < nr; i++) {
					j = i+1; if (j >= nr) j = 0;
					t.init();
					t.vertexNr[0] = mVertices.size() + centermVertices.size()-1;
					t.vertexNr[1] = vertNr[i];
					t.vertexNr[2] = vertNr[j];

					t.normalNr[0] = mNormals.size() + centerNormals.size()-1;
					t.normalNr[1] = normalNr[i];
					t.normalNr[2] = normalNr[j];

					t.texCoordNr[0] = mTexCoords.size() + centermTexCoords.size()-1;
					t.texCoordNr[1] = texNr[i];
					t.texCoordNr[2] = texNr[j];
					t.materialNr = materialNr;
					mTriangles.push_back(t);
				}
			}
		}
	}
	fclose(f);

	// new center mVertices are inserted here.
	// If they were inserted when generated, the vertex numbering would be corrupted
	for (i = 0; i < (int)centermVertices.size(); i++)
		mVertices.push_back(centermVertices[i]);
	for (i = 0; i < (int)centerNormals.size(); i++)
		mNormals.push_back(centerNormals[i]);
	for (i = 0; i < (int)centermTexCoords.size(); i++)
		mTexCoords.push_back(centermTexCoords[i]);

	if (mTexCoords.size() > 0) mHasTextureCoords = true;
	if (mNormals.size() > 0) 
		mHasNormals = true;
	else
		updateNormals();

	updateBounds();
	return true;
}
Jumper::CanopyOpening::CanopyOpening(Jumper* jumper, NxActor* phFreeFall, NxActor* phFlight, MatrixConversion* mcFlight, PilotchuteSimulator* pc, CanopySimulator* c, NxVec3 fla, NxVec3 fra, NxVec3 rla, NxVec3 rra) :
    JumperAction( jumper )
{
    // set action properties
    _actionTime = 0.0f;
    _blendTime = 0.2f;
    _endOfAction = false;
    _phActor = phFlight;
    _matrixConversion = mcFlight;
    _pilotchute = pc;
    _canopy = c;
    _frontLeftAnchor  = fla;
    _frontRightAnchor = fra;
    _rearLeftAnchor   = rla;
    _rearRightAnchor  = rra;
    _initialLD = phFlight->getLinearDamping();

    // activate jumper body simulator
    Matrix4f sampleLTM = Jumper::getCollisionFC( _clump )->getFrame()->getLTM();
    phFlight->setGlobalPose( wrap( sampleLTM ) );
    phFlight->wakeUp();
    phFlight->setLinearVelocity( phFreeFall->getLinearVelocity() );
    phFlight->setAngularVelocity( phFreeFall->getAngularVelocity() );    

    // connect & open canopy    
    _canopy->connect(
        _phActor, 
        _frontLeftAnchor,
        _frontRightAnchor,
        _rearLeftAnchor,
        _rearRightAnchor,
        Jumper::getFrontLeftRiser( _clump ),
        Jumper::getFrontRightRiser( _clump ),
        Jumper::getRearLeftRiser( _clump ),
        Jumper::getRearRightRiser( _clump )
    );

	// age
	if (_jumper->getCanopyReserveSimulator() && _jumper->getCanopyReserveSimulator() == _canopy) {
		++jumper->getVirtues()->equipment.reserve.age;
	} else {
		++jumper->getVirtues()->equipment.canopy.age;
	}

    // retrieve pilotchute velocity
    float pcVel = pc->getPhActor()->getLinearVelocity().magnitude();
	float anglVel = phFreeFall->getAngularVelocity().magnitude();

    // retrieve pilotchute reference velocity
	database::Canopy* canopyInfo = _canopy->getGearRecord();
	database::Pilotchute* pcInfo;
	if (_jumper->getCanopyReserveSimulator() == _canopy) {
		pcInfo = canopyInfo->pilots;
	} else {
		assert( canopyInfo->numPilots > _jumper->getVirtues()->equipment.pilotchute );
		pcInfo = canopyInfo->pilots + _jumper->getVirtues()->equipment.pilotchute;
	}

    // probability of lineover
    float lineoverProb  = _jumper->getVirtues()->getLineoverProbability( pcVel / pcInfo->Vrec );
	// no slider has not smaller probability
	if (_jumper->getVirtues()->equipment.sliderOption != soRemoved) {
		lineoverProb *= 0.3f;
	}
	// reserves have 70% less lineover probability
	if (_jumper->getCanopyReserveSimulator() == _canopy) {
		lineoverProb *= 0.3f;
	}
    bool  leftLineover  = ( getCore()->getRandToolkit()->getUniform( 0, 1 ) < lineoverProb );
    bool  rightLineover = !leftLineover && ( getCore()->getRandToolkit()->getUniform( 0, 1 ) < lineoverProb );
    float leftLOW  = leftLineover ? getCore()->getRandToolkit()->getUniform( 0.5, 1.0f ) : 0;
    float rightLOW = rightLineover ? getCore()->getRandToolkit()->getUniform( 0.5, 1.0f ) : 0;

    // probability of linetwists
	// add probability if spinning
	//if( _jumper->isPlayer() ) getCore()->logMessage( "angular velocity component on deployment: %2.10f", anglVel * 0.13f );
    float linetwistsProb = _jumper->getVirtues()->getLinetwistsProbability( pcVel ) + anglVel * 0.13f;
    float linetwistsDice = getCore()->getRandToolkit()->getUniform( 0.0f, 1.0f );
	
	// probability of linetwists because of incorrect body position
	NxVec3 motionDir = _jumper->getFreefallActor()->getLinearVelocity(); motionDir.normalize();
    NxVec3 canopyDown  = _jumper->getFreefallActor()->getGlobalPose().M.getColumn(2); canopyDown.normalize();
    float relativity = 1.0f + fabs(canopyDown.dot( motionDir ));
	linetwistsProb *= relativity;

	// reserves have 50% less linetwist probability
	if (_jumper->getCanopyReserveSimulator() == _canopy) {
		linetwistsProb *= 0.5f;
	}
	
	// base canopies gave 40% less linetwist probability
	else if (!canopyInfo->skydiving) {
		linetwistsProb *= 0.4f;
	}

    bool  linetwists = ( linetwistsDice <= linetwistsProb );
	//if( _jumper->isPlayer() ) {
		//getCore()->logMessage( "linetwists prob: %3.5f", linetwistsProb );
		//getCore()->logMessage( "linetwists dice: %3.5f", linetwistsDice );
	//} else {
		//getCore()->logMessage( "linetwists prob BOT: %3.5f", linetwistsProb );
		//getCore()->logMessage( "linetwists dice BOT: %3.5f", linetwistsDice );
	//}

    // generate linetwists (positive is righttwist, negative is lefttwist)
	// the smaller the canopy, the heavier the linetwist
	float sq = canopyInfo->square * 2.0f;
	// 300 canopy: 120; 840
	// 200 canopy: 320; 1040
	// 100 canopy: 520; 1240
    float linetwistsAngle = getCore()->getRandToolkit()->getUniform( 720 - sq, 1540 - sq );
	if (linetwistsAngle > 1080.0f) {
		linetwistsAngle = 1440.0f;
	} else if (linetwistsAngle < 320.0f) {
		linetwistsAngle = 180.0f;
	}

    float sign = getCore()->getRandToolkit()->getUniform( -1, 1 );
    sign = sign < 0.0f ? -1.0f : ( sign > 0.0f ? 1.0f : 0.0f );
    linetwistsAngle *= sign;

    if( !linetwists ) linetwistsAngle = 0.0f;

	// test, force linetwist
	//if (!_jumper->isPlayer() && _jumper->getCanopyReserveSimulator() != _canopy) {
	//	linetwists = true;
	//	linetwistsAngle = 1440.0f;
	//}

    // offheading : canopy turns by specified angle
    float minTurn = 30.0f; // rigging skill = 0.0 
    float maxTurn = 10.0f;  // rigging skill = 1.0 
    float rigging = _jumper->getVirtues()->getRiggingSkill(); assert( rigging >= 0 && rigging <= 1 );
    float turn    = minTurn * ( 1 - rigging ) + maxTurn * rigging;
    float angle = getCore()->getRandToolkit()->getUniform( -turn, turn );
    //if( _jumper->isPlayer() ) getCore()->logMessage( "additional turn (offheading): %2.1f", angle );
    //if( !_jumper->isPlayer() ) angle = 0;


    Vector3f sampleX( sampleLTM[0][0], sampleLTM[0][1], sampleLTM[0][2] );
    Vector3f sampleY( sampleLTM[1][0], sampleLTM[1][1], sampleLTM[1][2] );
    Vector3f sampleZ( sampleLTM[2][0], sampleLTM[2][1], sampleLTM[2][2] );
    Vector3f sampleP( sampleLTM[3][0], sampleLTM[3][1], sampleLTM[3][2] );
    // orient canopy towards jumper velocity
    sampleZ = wrap( phFlight->getLinearVelocity() );
    sampleZ *= -1;
    sampleZ.normalize();
    sampleY = _jumper->getClump()->getFrame()->getAt() * -1;
    sampleX.cross( sampleY, sampleZ );
    sampleX.normalize();
    sampleY.cross( sampleZ, sampleX );
    sampleY.normalize();
    sampleLTM.set( 
        sampleX[0], sampleX[1], sampleX[2], 0.0f,
        sampleY[0], sampleY[1], sampleY[2], 0.0f,
        sampleZ[0], sampleZ[1], sampleZ[2], 0.0f,
        0.0f, 0.0f, 0.0f, 1.0f
    );
    // turn canopy by random angle
    sampleLTM = Gameplay::iEngine->rotateMatrix( sampleLTM, sampleZ, angle );
    // move clump behind jumper
    sampleP -= sampleZ * 80.0f;

    sampleLTM[3][0] = sampleP[0];
    sampleLTM[3][1] = sampleP[1];
    sampleLTM[3][2] = sampleP[2];

    _canopy->open( wrap( sampleLTM ), _phActor->getLinearVelocity(), leftLOW, rightLOW, linetwistsAngle );

    // reconnect pilotchute to canopy
    _canopy->getClump()->getFrame()->getLTM();
    _pilotchute->connect( 
        _canopy->getNxActor(), 
        CanopySimulator::getPilotCordJoint( _canopy->getClump() ),
        _canopy->getPilotAnchor()
    );
	//_pilotchute->setFreebag(_canopy == _jumper->getCanopyReserveSimulator()); set in jumper constructor and jumper::fireReserveCanopy()

    // put to sleep freefall simulator
    phFreeFall->putToSleep();
    phFreeFall->raiseActorFlag( NX_AF_DISABLE_COLLISION );

    // show risers
    Jumper::getRisers( _clump )->setFlags( engine::afRender );

    // animation controller
    engine::IAnimationController* animCtrl = _clump->getAnimationController();

    // capture blend source
    animCtrl->captureBlendSrc();

    // reset animation mixer
    for( unsigned int i=0; i<engine::maxAnimationTracks; i++ )
    {
        if( animCtrl->getTrackAnimation( i ) ) animCtrl->setTrackActivity( i, false );
    }

    // setup animation
    animCtrl->setTrackAnimation( 0, &openingSequence );
    animCtrl->setTrackActivity( 0, true );
    animCtrl->setTrackSpeed( 0, 0.75f );
    animCtrl->setTrackWeight( 0, 1.0f );
    animCtrl->resetTrackTime( 0 );
    animCtrl->advance( 0.0f );

    // capture blend destination
    animCtrl->captureBlendDst();
    animCtrl->blend( 0.0f );
}
Example #27
0
int main(int argc, char **argv)
{
    //init and PVD
    bool initialized = false;
    NxPhysicsSDK *physicsSDK = NxCreatePhysicsSDK(NX_PHYSICS_SDK_VERSION);
    if (!physicsSDK)
        return 0;
    else
        physicsSDK->getFoundationSDK().getRemoteDebugger()->connect("localhost", 5425);
    physicsSDK->setParameter(NX_CONTINUOUS_CD, true);

    initialized = true;

    //create a scene
    bool sceneInit = false;
    NxSceneDesc sceneDesc;
    sceneDesc.gravity.set(0, -9.81f, 0);
    gScene = physicsSDK->createScene(sceneDesc);

    if (gScene != NULL)
        sceneInit = true;

    //create a plane
    {
        NxActorDesc actorDesc;
        NxPlaneShapeDesc planeDesc;
        //planeDesc.normal = NxVec3(0, 0, 1);
        //planeDesc.d = -10.0f;

        actorDesc.shapes.pushBack(&planeDesc);
        gScene->createActor(actorDesc);
    }

    //create material
    NxMaterial *defaultMaterial = gScene->getMaterialFromIndex(0);
    defaultMaterial->setRestitution(0.3f);
    defaultMaterial->setStaticFriction(0.5f);
    defaultMaterial->setDynamicFriction(0.5f);



    //create a box
    {
        NxActorDesc actorDesc;
        NxBodyDesc bodyDesc;
        bodyDesc.angularDamping = 0.5;
        bodyDesc.linearVelocity = NxVec3(1, 0, 0);
        actorDesc.body = &bodyDesc;

        NxBoxShapeDesc boxDesc;
        boxDesc.dimensions = NxVec3(2.0f, 3.0f, 4.0f);
        actorDesc.shapes.pushBack(&boxDesc);
        actorDesc.density = 10.0f;
        actorDesc.globalPose.t = NxVec3(10.0f, 10.0f, 10.0f);
        gScene->createActor(actorDesc)->userData = NULL;
    }

    //create a cloth
    {
        // Create the objects in the scene
        NxActor* sphere1 = CreateSphere(NxVec3(-1, 0, -0.5), 1, 10);
        NxActor* box1 = CreateBox(NxVec3(1, 0, -1), NxVec3(1, 1, 1), 10);
        NxActor* box2 = CreateBox(NxVec3(0, 6.5, 0), NxVec3(5, 0.5, 0.5), 10);
        NxActor* box3 = CreateBox(NxVec3(0, 6.5, -7), NxVec3(5, 0.5, 0.5), 10);

        box2->setLinearDamping(5);
        box3->setLinearDamping(5);
        NxD6JointDesc d6Desc;
        d6Desc.actor[0] = NULL;
        d6Desc.actor[1] = box2;
        NxVec3 globalAnchor(0, 7, 0);
        d6Desc.localAnchor[0] = globalAnchor;
        box2->getGlobalPose().multiplyByInverseRT(globalAnchor, d6Desc.localAnchor[1]);
        box2->raiseBodyFlag(NX_BF_DISABLE_GRAVITY);

        box3->getGlobalPose().multiplyByInverseRT(globalAnchor, d6Desc.localAnchor[1]);
        box3->raiseBodyFlag(NX_BF_DISABLE_GRAVITY);

        d6Desc.localAxis[0] = NxVec3(1, 0, 0);
        d6Desc.localNormal[0] = NxVec3(0, 1, 0);
        d6Desc.localAxis[1] = NxVec3(1, 0, 0);
        d6Desc.localNormal[1] = NxVec3(0, 1, 0);

        d6Desc.twistMotion = NX_D6JOINT_MOTION_LOCKED;
        d6Desc.swing1Motion = NX_D6JOINT_MOTION_LOCKED;
        d6Desc.swing2Motion = NX_D6JOINT_MOTION_LOCKED;
        d6Desc.xMotion = NX_D6JOINT_MOTION_FREE;
        d6Desc.yMotion = NX_D6JOINT_MOTION_FREE;
        d6Desc.zMotion = NX_D6JOINT_MOTION_FREE;

        NxJoint* d6Joint = gScene->createJoint(d6Desc);

        NxClothDesc clothDesc;
        clothDesc.globalPose.t = NxVec3(4, 7, 0);
        clothDesc.thickness = 0.2;
        //clothDesc.density = 1;
        clothDesc.bendingStiffness = 0.5;
        clothDesc.stretchingStiffness = 1;
        //clothDesc.dampingCoefficient = 0.5;
        clothDesc.friction = 0.5;
        //clothDesc.collisionResponseCoefficient = 1;
        //clothDesc.attachmentResponseCoefficient = 1;
        //clothDesc.solverIterations = 5;
        //clothDesc.flags |= NX_CLF_STATIC;
        //clothDesc.flags |= NX_CLF_DISABLE_COLLISION;
        //clothDesc.flags |= NX_CLF_VISUALIZATION;
        //clothDesc.flags |= NX_CLF_GRAVITY;
        clothDesc.flags |= NX_CLF_BENDING;
        //clothDesc.flags |= NX_CLF_BENDING_ORTHO;
        clothDesc.flags |= NX_CLF_DAMPING;
        //clothDesc.flags |= NX_CLF_COMDAMPING;
        clothDesc.flags |= NX_CLF_COLLISION_TWOWAY;

        clothDesc.flags &= ~NX_CLF_HARDWARE;
        clothDesc.flags |= NX_CLF_FLUID_COLLISION;
        clothDesc.selfCollisionThickness = 10.0f;


        NxReal w = 8;
        NxReal h = 7;
        NxReal d = 0.05;
        NxClothMeshDesc meshDesc;
        bool mInitDone = false;

        int numX = (int)(w / d) + 1;
        int numY = (int)(h / d) + 1;


        meshDesc.numVertices = (numX + 1) * (numY + 1);
        meshDesc.numTriangles = numX*numY * 2;
        meshDesc.pointStrideBytes = sizeof(NxVec3);
        meshDesc.triangleStrideBytes = 3 * sizeof(NxU32);
        meshDesc.vertexMassStrideBytes = sizeof(NxReal);
        meshDesc.vertexFlagStrideBytes = sizeof(NxU32);
        meshDesc.points = (NxVec3*)malloc(sizeof(NxVec3)*meshDesc.numVertices);
        meshDesc.triangles = (NxU32*)malloc(sizeof(NxU32)*meshDesc.numTriangles * 3);
        meshDesc.vertexMasses = 0;
        meshDesc.vertexFlags = 0;
        meshDesc.flags = 0;

        int i, j;
        NxVec3 *p = (NxVec3*)meshDesc.points;
        for (i = 0; i <= numY; i++) {
            for (j = 0; j <= numX; j++) {
                p->set(-d*j, 0.0f, -d*i);
                p++;
            }
        }

        NxU32 *id = (NxU32*)meshDesc.triangles;
        for (i = 0; i < numY; i++) {
            for (j = 0; j < numX; j++) {
                NxU32 i0 = i * (numX + 1) + j;
                NxU32 i1 = i0 + 1;
                NxU32 i2 = i0 + (numX + 1);
                NxU32 i3 = i2 + 1;
                if ((j + i) % 2) {
                    *id++ = i0;
                    *id++ = i2;
                    *id++ = i1;
                    *id++ = i1;
                    *id++ = i2;
                    *id++ = i3;
                }
                else {
                    *id++ = i0;
                    *id++ = i2;
                    *id++ = i3;
                    *id++ = i0;
                    *id++ = i3;
                    *id++ = i1;
                }
            }
        }
        // if we want tearing we must tell the cooker
        // this way it will generate some space for particles that will be generated during tearing
        if (meshDesc.flags & NX_CLF_TEARABLE)
            meshDesc.flags |= NX_CLOTH_MESH_TEARABLE;


        //cooking
        static NxCookingInterface *gCooking = 0;
        gCooking = NxGetCookingLib(NX_PHYSICS_SDK_VERSION);
        gCooking->NxInitCooking();

        gCooking->NxCookClothMesh(meshDesc, UserStream("e:\\cooked.bin", false));

        //Meshdata Buffers
        NxMeshData mReceiveBuffers;
        // here we setup the buffers through which the SDK returns the dynamic cloth data
        // we reserve more memory for vertices than the initial mesh takes
        // because tearing creates new vertices
        // the SDK only tears cloth as long as there is room in these buffers
        NxU32 numVertices = meshDesc.numVertices;
        NxU32 numTriangles = meshDesc.numTriangles;

        NxU32 maxVertices = 2 * numVertices;
        mReceiveBuffers.verticesPosBegin = (NxVec3*)malloc(sizeof(NxVec3)*maxVertices);
        mReceiveBuffers.verticesNormalBegin = (NxVec3*)malloc(sizeof(NxVec3)*maxVertices);
        mReceiveBuffers.verticesPosByteStride = sizeof(NxVec3);
        mReceiveBuffers.verticesNormalByteStride = sizeof(NxVec3);
        mReceiveBuffers.maxVertices = maxVertices;
        mReceiveBuffers.numVerticesPtr = (NxU32*)malloc(sizeof(NxU32));

        // the number of triangles is constant, even if the cloth is torn
        NxU32 maxIndices = 3 * numTriangles;
        mReceiveBuffers.indicesBegin = (NxU32*)malloc(sizeof(NxU32)*maxIndices);
        mReceiveBuffers.indicesByteStride = sizeof(NxU32);
        mReceiveBuffers.maxIndices = maxIndices;
        mReceiveBuffers.numIndicesPtr = (NxU32*)malloc(sizeof(NxU32));

        // the parent index information would be needed if we used textured cloth
        NxU32 maxParentIndices = maxVertices;
        mReceiveBuffers.parentIndicesBegin = (NxU32*)malloc(sizeof(NxU32)*maxParentIndices);
        mReceiveBuffers.parentIndicesByteStride = sizeof(NxU32);
        mReceiveBuffers.maxParentIndices = maxParentIndices;
        mReceiveBuffers.numParentIndicesPtr = (NxU32*)malloc(sizeof(NxU32));

        // init the buffers in case we want to draw the mesh
        // before the SDK as filled in the correct values
        *mReceiveBuffers.numVerticesPtr = 0;
        *mReceiveBuffers.numIndicesPtr = 0;



        clothDesc.clothMesh = physicsSDK->createClothMesh(UserStream("e:\\cooked.bin", true));
        clothDesc.meshData = mReceiveBuffers;

        NxCloth *mCloth;
        mCloth = gScene->createCloth(clothDesc);
        mCloth->attachToShape(*box2->getShapes(), NX_CLOTH_ATTACHMENT_TWOWAY);
        mCloth->attachToShape(*box3->getShapes(), NX_CLOTH_ATTACHMENT_TWOWAY);
    }

    //create fluid 1
    {
        //fluid = CreateFluid(NxVec3(0, 12, -3.5), 15, 0.1, gScene);
    }
    //create fluid 2
    {
        //Create a set of initial particles
        ParticleSDK*	initParticles = new ParticleSDK[max_particles];
        unsigned initParticlesNum = 0;

        //Create particle filled sphere in buffer.
        NxVec3 fluidPos(0, 2, 0);
        NxVec3 offsetPos(0, 12, -3.5);
        float distance = 0.1f;
        //#ifdef __PPCGEKKO__
        //	unsigned sideNum = 12;
        //#else
        unsigned sideNum = 16;
        //#endif

        //Setup structure to pass initial particles.
        NxParticleData initParticleData;
        initParticlesNum = 0;
        initParticleData.numParticlesPtr = &initParticlesNum;
        initParticleData.bufferPos = &initParticles[0].position.x;
        initParticleData.bufferPosByteStride = sizeof(ParticleSDK);
        initParticleData.bufferVel = &initParticles[0].velocity.x;
        initParticleData.bufferVelByteStride = sizeof(ParticleSDK);

        CreateParticleSphere(initParticleData, max_particles, false, offsetPos, NxVec3(0, 0, 0), 0.0f, distance, sideNum);

        //Setup fluid descriptor
        NxFluidDesc fluidDesc;
        fluidDesc.maxParticles = max_particles;
        fluidDesc.kernelRadiusMultiplier = 2.0f;
        fluidDesc.restParticlesPerMeter = 10.0f;
        fluidDesc.motionLimitMultiplier = 3.0f;
        fluidDesc.packetSizeMultiplier = 8;
        fluidDesc.collisionDistanceMultiplier = 0.1;
        fluidDesc.stiffness = 50.0f;
        fluidDesc.viscosity = 40.0f;
        fluidDesc.restDensity = 1000.0f;
        fluidDesc.damping = 0.0f;
        fluidDesc.restitutionForStaticShapes = 0.0f;
        fluidDesc.dynamicFrictionForStaticShapes = 0.05f;
        fluidDesc.simulationMethod = NX_F_SPH;
        fluidDesc.flags &= ~NX_FF_HARDWARE;

        //Add initial particles to fluid creation.
        fluidDesc.initialParticleData = initParticleData;

        //Create user fluid.
        //- create NxFluid in NxScene
        //- setup the buffers to read from data from the SDK
        //- set NxFluid::userData field to MyFluid instance
        bool trackUserData = false;
        bool provideCollisionNormals = false;
        MyFluid* fluid = new MyFluid(gScene, fluidDesc, trackUserData, provideCollisionNormals, NxVec3(0.4f, 0.5f, 0.9f), 0.03f);
        assert(fluid);
        gMyFluids.pushBack(fluid);
    }
    //simulate
    for (int i = 0; i < 3000; i++)
    {
        gScene->simulate(1.0f / 60.f);
        gScene->flushStream();
        //GetPhysicsResults
        gScene->fetchResults(NX_RIGID_BODY_FINISHED, true);

        // update fluid status
        if (i == 400)
        {
            MyFluid* fluid = gMyFluids[0];
            const ParticleSDK* particles = fluid->getParticles();
            unsigned particlesNum = fluid->getParticlesNum();
            if (!gUpdates)
            {
                gUpdates = new ParticleUpdateSDK[max_particles];
            }
            for (unsigned i = 0; i < particlesNum; i++)
            {
                ParticleUpdateSDK& update = gUpdates[i];
                NxVec3& force = update.force;
                force.set(0, 0, 0);
                NxU32& flags = update.flags;
                if (i >= particlesNum/2)
                {
                    flags = 0;
                    flags |= NX_FP_DELETE;
                }
                else
                {
                    flags = 0;
                }

            }
            //在这里更改粒子的属性
            NxParticleUpdateData updateData;
            updateData.bufferFlag = &gUpdates[0].flags;
            updateData.bufferFlagByteStride = sizeof(ParticleUpdateSDK);
            fluid->getNxFluid()->updateParticles(updateData);
        }
    }


    //release
    if (physicsSDK != NULL)
    {
        if (gScene != NULL)
            physicsSDK->releaseScene(*gScene);
        gScene = NULL;
        NxReleasePhysicsSDK(physicsSDK);
        physicsSDK = NULL;
    }
    return 1;
}
void Jumper::AirplaneJump::update(float dt)
{
    updateAnimation( dt );

    bool useWingsuit = database::Suit::getRecord( _jumper->getVirtues()->equipment.suit.id )->wingsuit;
    float phaseTime = useWingsuit ? trackInvSpeed * ( FRAMETIME(2113) - FRAMETIME(2104) ) : trackInvSpeed * ( FRAMETIME(1673) - FRAMETIME(1669) );

    if( _actionTime > _blendTime + phaseTime )
    {
        if( _phActor->isSleeping() )
        {
            // place jumper to airplane exit
            Matrix4f clumpLTM = _clump->getFrame()->getLTM();
            Vector3f clumpScale = calcScale( clumpLTM );
            Matrix4f exitLTM = _jumper->getAirplaneExit()->getLTM();
            orthoNormalize( exitLTM );
            exitLTM[0][0] *= clumpScale[0], exitLTM[0][1] *= clumpScale[0], exitLTM[0][2] *= clumpScale[0];
            exitLTM[1][0] *= clumpScale[1], exitLTM[1][1] *= clumpScale[1], exitLTM[1][2] *= clumpScale[1];
            exitLTM[2][0] *= clumpScale[2], exitLTM[2][1] *= clumpScale[2], exitLTM[2][2] *= clumpScale[2];
            _clump->getFrame()->setMatrix( exitLTM );
            _clump->getFrame()->getLTM();

            Matrix4f sampleLTM = Jumper::getCollisionFF( _clump )->getFrame()->getLTM();
            _phActor->setGlobalPose( wrap( sampleLTM ) );
            _phActor->wakeUp();
            NxVec3 velH = wrap( _clump->getFrame()->getAt() );
            velH.normalize();
            velH *= 3.0f;
            NxVec3 velV = wrap( _clump->getFrame()->getUp() );
            velV.normalize();
            velV *= 0.25f;
			
            NxVec3 velA = wrap( _jumper->getAirplane()->getVel() );
            _phActor->setLinearVelocity( velH + velV + velA );
            _jumper->initOverburdenCalculator( velH + velV + velA );

			// modified exits (only fixed wing, not heli)
			bool helicopter = strcmp(_jumper->getAirplane()->getDesc()->templateClump->getName(), "Helicopter01") == 0;
			if (!helicopter) {
				if (_jumper->getSpinalCord()->left) {
					_phActor->addLocalTorque(NxVec3(0,5700.0f,0));
					//_phActor->setAngularDamping(2.0f);
				} else if (_jumper->getSpinalCord()->right) {
					_phActor->addLocalTorque(NxVec3(0,-5700.0f,0));
					//_phActor->setAngularDamping(2.0f);
				}

				if (_jumper->getSpinalCord()->up) {		// headdown exit
					_phActor->addLocalTorque(NxVec3(5700.0f,0,0));
				} else if (_jumper->getSpinalCord()->down) {	// sitfly exit
					_phActor->addLocalTorque(NxVec3(-8700.0f,0,0));
					_phActor->addLocalForce(NxVec3(0,0,10000.0f));
				}
				_phActor->setAngularDamping(2.0f);
			}
        }
        else
        {
			if (_jumper->getSpinalCord()->left) {
				_phActor->addLocalTorque(NxVec3(0,2000.0f*dt,0));
			} else if (_jumper->getSpinalCord()->right) {
				_phActor->addLocalTorque(NxVec3(0,-2000.0f*dt,0));
			}
            _clump->getFrame()->setMatrix( _matrixConversion->convert( wrap( _phActor->getGlobalPose() ) ) );
        }
    }
    else
    {
        // place jumper to airplane exit
        Matrix4f clumpLTM = _clump->getFrame()->getLTM();
        Vector3f clumpScale = calcScale( clumpLTM );

        Matrix4f exitLTM = _jumper->getAirplaneExit()->getLTM();
		Vector3f pos = _jumper->getAirplaneExit()->getPos();
		getCore()->logMessage("exit pos: %2.2f %2.2f %2.2f",  pos[0], pos[1], pos[2]);
        orthoNormalize( exitLTM );
        exitLTM[0][0] *= clumpScale[0], exitLTM[0][1] *= clumpScale[0], exitLTM[0][2] *= clumpScale[0];
        exitLTM[1][0] *= clumpScale[1], exitLTM[1][1] *= clumpScale[1], exitLTM[1][2] *= clumpScale[1];
        exitLTM[2][0] *= clumpScale[2], exitLTM[2][1] *= clumpScale[2], exitLTM[2][2] *= clumpScale[2];

        _clump->getFrame()->setMatrix( exitLTM );
    }

	if( _clump->getAnimationController()->isEndOfAnimation( 0 )) // || (_jumper->getSpinalCord()->modifier && _jumper->isPlayer() &&   _actionTime > _blendTime + phaseTime ))
    {
        _endOfAction = true;
    }
}
Example #29
0
void Controller::move(SweptVolume& volume, const NxVec3& disp, NxU32 activeGroups, NxF32 minDist, NxU32& collisionFlags, NxF32 sharpness, const NxGroupsMask* groupsMask, bool constrainedClimbingMode)
	{
	// Dynamic-load the utility library
	if(!gUtilLib)
		gUtilLib = NxGetUtilLib();
	assert(gUtilLib);
	if(!gUtilLib)	return;

	SweepTest* ST = &cctModule;

	// Init CCT with per-controller settings
	ST->debugData		= manager->debugData;
	ST->mSkinWidth		= skinWidth;
	ST->mStepOffset		= stepOffset;
	ST->mUpDirection	= upDirection;
	ST->mHandleSlope	= handleSlope;
	ST->mSlopeLimit		= slopeLimit;
	ST->mFirstUpdate	= true;

	///////////

	Controller** boxUserData = NULL;
	NxExtendedBounds3* boxes = NULL;
	NxU32 nbBoxes = 0;

	Controller** capsuleUserData = NULL;
	NxExtendedCapsule* capsules = NULL;
	NxU32 nbCapsules = 0;

	if(1)
		{
		// Experiment - to do better
		NxU32 nbControllers = manager->getNbControllers();
		Controller** controllers = manager->getControllers();

		boxes = (NxExtendedBounds3*)NxAlloca(nbControllers*sizeof(NxExtendedBounds3));
		capsules = (NxExtendedCapsule*)NxAlloca(nbControllers*sizeof(NxExtendedCapsule));	// It's evil to waste that ram
		boxUserData = (Controller**)NxAlloca(nbControllers*sizeof(Controller*));
		capsuleUserData = (Controller**)NxAlloca(nbControllers*sizeof(Controller*));

		while(nbControllers--)
			{
			Controller* currentController = *controllers++;
			if(currentController==this)	continue;

			NxActor* pActor = currentController->getActor();
			int nbShapes = pActor->getNbShapes();
			NX_ASSERT( nbShapes == 1 );
			NxShape* pCurrentShape= pActor->getShapes()[0];

			// Depending on user settings the current controller can be:
			// - discarded
			// - always kept
			// - or tested against filtering flags
			NxCCTInteractionFlag interactionFlag = currentController->getInteraction();
			bool keepController = true;
			if(interactionFlag==NXIF_INTERACTION_EXCLUDE)			keepController = false;
			else if(interactionFlag==NXIF_INTERACTION_USE_FILTER)	keepController = (activeGroups & ( 1 << pCurrentShape->getGroup()))!=0;

			if(keepController)
				{
				if(currentController->type==NX_CONTROLLER_BOX)
					{
					currentController->getWorldBox(boxes[nbBoxes]);
					boxUserData[nbBoxes++] = currentController;
					}
				else if(currentController->type==NX_CONTROLLER_CAPSULE)
					{
					CapsuleController* CC = static_cast<CapsuleController*>(currentController);
					NxExtendedVec3 p0 = CC->position;
					NxExtendedVec3 p1 = CC->position;
					p0[ST->mUpDirection] -= CC->height*0.5f;
					p1[ST->mUpDirection] += CC->height*0.5f;
					capsules[nbCapsules].p0 = p0;
					capsules[nbCapsules].p1 = p1;
					capsules[nbCapsules].radius = CC->radius;
					capsuleUserData[nbCapsules++] = currentController;
					}
				else ASSERT(0);
				}
			}
		}

	///////////

	ST->mWalkExperiment = false;

	NxExtendedVec3 Backup = volume.mCenter;
	ST->MoveCharacter(scene,
		(Controller*)this,
		volume, disp,
		nbBoxes, nbBoxes ? boxes : NULL, nbBoxes ? (const void**)boxUserData : NULL,
		nbCapsules, nbCapsules ? capsules : NULL, nbCapsules ? (const void**)capsuleUserData : NULL,
		activeGroups, minDist, collisionFlags, groupsMask, constrainedClimbingMode);

	if(ST->mHitNonWalkable)
		{
		// A bit slow, but everything else I tried was less convincing...
		ST->mWalkExperiment = true;
		volume.mCenter = Backup;
		ST->MoveCharacter(scene,
			(Controller*)this,
			volume, disp,
			nbBoxes, nbBoxes ? boxes : NULL, nbBoxes ? (const void**)boxUserData : NULL,
			nbCapsules, nbCapsules ? capsules : NULL, nbCapsules ? (const void**)capsuleUserData : NULL,
			activeGroups, minDist, collisionFlags, groupsMask, constrainedClimbingMode);
		ST->mWalkExperiment = false;
		}

if(sharpness<0.0f)
volume.mCenter = Backup;

	// Copy results back
	position = volume.mCenter;

	NxVec3 Delta = Backup - volume.mCenter;
	NxF32 deltaM2 = Delta.magnitudeSquared();
	if(deltaM2!=0.0f)
		{
		// Update kinematic actor
		if(kineActor)
			kineActor->moveGlobalPosition(NxVec3((float)position.x, (float)position.y, (float)position.z));
		}

	filteredPosition = position;

sharpness = fabsf(sharpness);

	// Apply feedback filter if needed
	if(sharpness<1.0f)
		filteredPosition[upDirection] = feedbackFilter(position[upDirection], memory, sharpness);

//	if(manager->debugData)
//		manager->debugData->addAABB(cctModule.mCachedTBV, NX_ARGB_YELLOW);
	}
Example #30
0
float * NovodexPhysicSystem::getGravity() const
{
	static NxVec3 g(0,0,0);
	m_scene->getGravity(g);
	return g.get();
}