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

    if( _actionTime < _blendTime ) return;

    if( _actionTime > _blendTime + ( FRAMETIME(245) - FRAMETIME(225) ) )
    {
        if( _phActor->isSleeping() )
        {
            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 *= 1.5f;
            _phActor->setLinearVelocity( velH + velV );
            _jumper->initOverburdenCalculator( velH + velV );
        }
        else
        {
            _clump->getFrame()->setMatrix( _matrixConversion->convert( wrap( _phActor->getGlobalPose() ) ) );
        }
		if( _jumper->getSpinalCord()->modifier) _endOfAction = true;
    }

    if( _clump->getAnimationController()->isEndOfAnimation( 0 ) )
    {
        _endOfAction = true;
    }
}
Beispiel #2
0
	NX_INLINE void CollisionResponse(NxExtendedVec3& target_position, const NxExtendedVec3& current_position, const NxVec3& current_dir, const NxVec3& hit_normal, NxF32 bump, NxF32 friction, bool normalize=false)
	{
		// Compute reflect direction
		NxVec3 ReflectDir;
		ComputeReflexionVector(ReflectDir, current_dir, hit_normal);
		ReflectDir.normalize();

		// Decompose it
		NxVec3 NormalCompo, TangentCompo;
		DecomposeVector(NormalCompo, TangentCompo, ReflectDir, hit_normal);

		// Compute new destination position
		const Extended Amplitude = target_position.distance(current_position);

		target_position = current_position;
		if(bump!=0.0f)
		{
			if(normalize)	NormalCompo.normalize();
			target_position += NormalCompo*float(bump*Amplitude);
		}
		if(friction!=0.0)
		{
			if(normalize)	TangentCompo.normalize();
			target_position += TangentCompo*float(friction*Amplitude);
		}
	}
Beispiel #3
0
void DXApp::Frame()
{
    UINT64 CurrentTime;
    UINT64 DeltaCount;
    QueryPerformanceCounter((LARGE_INTEGER*)&CurrentTime);
    DeltaCount = CurrentTime - OldCount;
    OldCount = CurrentTime;

    DeltaTime = (double)DeltaCount/(double)Frequency;

    {
        NxVec3 Temp;
        Cam.location+=Cam.ViewDir*40*fFoward;

        Temp = Cam.ViewDir;
        Temp.y = 0;
        Temp.normalize();
        Temp = Temp.cross(NxVec3(0.0f, 1.0f, 0.0f));
        Cam.location+=Temp*40*fStrafe;;
    }

    if(!bPaused)
    {
        DoParticles();
        _p_scene->simulate(_time_step);
        _p_scene->flushStream();
    }
    RenderFrame();
    if(!bPaused)
        _p_scene->fetchResults(NX_RIGID_BODY_FINISHED, true);

}
Beispiel #4
0
static void MotionCallback(int x, int y)
{
    int dx = gMouseX - x;
    int dy = gMouseY - y;

    gDir.normalize();		//カメラの視線ベクトルを正規化
    gViewY.cross(gDir, NxVec3(0,1,0));	//

    if( gMouseButton[0] && gMouseButton[1] ) {
        //Zoom: Left + Center Buttons Drag
        gEye -= gDir * 0.5f * dy;
    } else {
        if( gMouseButton[0] ) {
            //Rotate: Left Button Drag
            NxQuat qx(NxPiF32 * dx * 10/ 180.0f, NxVec3(0,1,0));
            qx.rotate(gDir);
            NxQuat qy(NxPiF32 * dy * 10/ 180.0f, gViewY);
            qy.rotate(gDir);
        } else if( gMouseButton[1] ) {
            //Move: Center Button Drag
            gEye += 0.1f * (gViewY * dx - NxVec3(0, 1, 0) * dy);
        }
    }
    gMouseX = x;
    gMouseY = y;
    glutPostRedisplay();
}
static void KeyboardCallback(unsigned char key, int x, int y)
	{
	switch (key)
		{
		case 27:	exit(0); break;
		case '1':			CreateCube(NxVec3(-40.0f, 60.0f, -18.0f)); break;
		case '2':			CreateCube(NxVec3(0.0f, 60.0f, -18.0f)); break;
		case '3':			CreateCube(NxVec3(40.0f, 60.0f, -18.0f)); break;

		case '4':			CreateCube(NxVec3(-40.0f, 60.0f, 40.0f)); break;
		case '5':			CreateCube(NxVec3(0.0f, 60.0f, 40.0f)); break;
		case '6':			CreateCube(NxVec3(40.0f, 60.0f, 40.0f)); break;

		case 'p':			gPause = !gPause; break;
		case 101: 			Eye += Dir * 2.0f; break;
		case 103: 			Eye -= Dir * 2.0f; break;
		case 100: 			Eye -= N * 2.0f; break;
		case 102: 			Eye += N * 2.0f; break;
		case 'w':
			{
			NxVec3 t = Eye;
			NxVec3 Vel = Dir;
			Vel.normalize();
			Vel*=100.0f;
			CreateCube(t, &Vel);
			}
			break;
		}
	
	}
static void KeyboardCallback(unsigned char key, int x, int y)
{
	static Random random;
	int sceneIndex = random.rand()&1;

	switch (key)
	{
	case 27:	exit(0); break;
	case ' ':			CreateCube(sceneIndex, NxVec3(0.0f, 20.0f, 0.0f), 1+(rand()&3)); break;
	case 's':			CreateStack(sceneIndex, 10); break;
	case 'b':			CreateStack(sceneIndex, 30); break;
	case 't':			CreateTower(sceneIndex, 30); break;
	case 'x':			gShadows = !gShadows; break;
	case 'p':			gPause = !gPause; break;
	case 101: case '8':	Eye += Dir * 2.0f; break;
	case 103: case '2':	Eye -= Dir * 2.0f; break;
	case 100: case '4':	Eye -= N * 2.0f; break;
	case 102: case '6':	Eye += N * 2.0f; break;
	case 'w':
		{
		NxVec3 t = Eye;
		NxVec3 Vel = Dir;
		Vel.normalize();
		Vel*=200.0f;
		CreateCube(sceneIndex, t, 8, &Vel);
		}
		break;
	}
}
void MotionCallback(int x, int y)
{
	int dx = mx - x;
	int dy = my - y;

	if (gMouseSphere) // Move the mouse sphere
	{
		NxVec3 pos;
		ViewUnProject(x,y, gMouseDepth, pos);
		gMouseSphere->setGlobalPosition(pos);
		gHitActor->wakeUp();
	}
	else if (gHitCloth) // Attach the cloth vertex
	{
		NxVec3 pos; 
		ViewUnProject(x,y, gMouseDepth, pos);
		gHitCloth->attachVertexToGlobalPosition(gHitClothVertex, pos);
	}
	else if (bLeftMouseButtonPressed) // Set camera
	{   
		gCameraForward.normalize();
		gCameraRight.cross(gCameraForward,NxVec3(0,1,0));

		NxQuat qx(NxPiF32 * dx * 20 / 180.0f, NxVec3(0,1,0));
		qx.rotate(gCameraForward);
		NxQuat qy(NxPiF32 * dy * 20 / 180.0f, gCameraRight);
		qy.rotate(gCameraForward);
	}

    mx = x;
    my = y;
}
Beispiel #8
0
static void computeBasis(const NxVec3& dir, NxVec3& right, NxVec3& up)
{
	// Derive two remaining vectors
	if(fabsf(dir.y)>0.9999f)	right = NxVec3(1.0f, 0.0f, 0.0f);
	else						right = (NxVec3(0.0f, 1.0f, 0.0f) ^ dir);
	right.normalize();
	up = dir ^ right;
}
Beispiel #9
0
void PhysX::CreateCubeFromEye(float cubeSize)
{
	NxVec3 t = m_Eye;
	NxVec3 vel = m_Dir;
	vel.normalize();
	vel*=200.0f;
	CreateCube(t, cubeSize, DENSITY, &vel);
}
Beispiel #10
0
void CreateCubeFromEye(int size)
{
	NxVec3 t = g_CameraPos;
	NxVec3 vel = g_CameraForward;
	vel.normalize();
	vel*=200.0f;
	CreateCube(t, size, &vel);
}
Beispiel #11
0
void PhysX::CreateSphereFromEye(int radius)
{
	NxVec3 t = m_Eye;
	NxVec3 vel = m_Dir;
	vel.normalize();
	vel *= 200.0f;
	CreateSphere(t, radius, DENSITY , &vel);
}
Beispiel #12
0
void pWheel1::_tick(float dt)
{

	if(!hasGroundContact())
		updateContactPosition();
	
	//################################################################
	//
	// Calculate the wheel rotation around the roll axis
	//
	updateAngularVelocity(dt*0.001f, false);

	float motorTorque=0.0;

	if(getWheelFlag(WF_Accelerated)) 
	{
		/*if (handBrake && getWheelFlag(NX_WF_AFFECTED_BY_HANDBRAKE)) 
		{
			// Handbrake, blocking!
		}*/
		
		if (hasGroundContact()) 
		{
			// Touching, force applies
			NxVec3 steeringDirection;
			getSteeringDirection(steeringDirection);
			steeringDirection.normalize();
			NxReal localTorque = motorTorque;
			NxReal wheelForce = localTorque / _radius;
			steeringDirection *= wheelForce;
			wheelCapsule->getActor().addForceAtPos(steeringDirection, contactInfo->contactPosition);
			if(contactInfo->otherActor->isDynamic())
				contactInfo->otherActor->addForceAtPos(-steeringDirection, contactInfo->contactPosition);
		} 
	}
	
	NxMat34& wheelPose = getWheelCapsule()->getGlobalPose();
	NxMat33 rot, axisRot, rollRot;
	rot.rotY( _angle );
	axisRot.rotY(0);
	rollRot.rotX(_turnAngle);
	wheelPose.M = rot * wheelPose.M * axisRot * rollRot;

	float a = _angle;
	float b = getWheelRollAngle();

	
	setWheelPose(wheelPose);
	//setWheelOrientation(wheelPose.M);


	contactInfo->reset();
}
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;
    }
}
Beispiel #14
0
void pWheel1::tick(bool handbrake, float motorTorque, float brakeTorque, float dt)
{

	if(getWheelFlag(WF_Accelerated)) 
	{
		if (handbrake && getWheelFlag(WF_AffectedByHandbrake)) 
		{
			// Handbrake, blocking!
		}
		else if (hasGroundContact()) 
		{
			// Touching, force applies
			NxVec3 steeringDirection;
			getSteeringDirection(steeringDirection);
			steeringDirection.normalize();
			NxReal localTorque = motorTorque;
			NxReal wheelForce = localTorque / _radius;
			steeringDirection *= wheelForce;
			wheelCapsule->getActor().addForceAtPos(steeringDirection, contactInfo->contactPosition);
			if(contactInfo->otherActor->isDynamic())
				contactInfo->otherActor->addForceAtPos(-steeringDirection, contactInfo->contactPosition);
		} 
	}

	NxReal OneMinusBreakPedal = 1-brakeTorque;

	/*
	if(handBrake && getWheelFlag(WF_AffectedByHandbrake)) 
	{
	material->setDynamicFrictionV(1);
	material->setStaticFrictionV(4);
	material->setDynamicFriction(0.4f);
	material->setStaticFriction(1.0f);
	} 
	else 
	{
	NxReal newv = OneMinusBreakPedal * _frictionToFront + brakeTorque;
	NxReal newv4= OneMinusBreakPedal * _frictionToFront + brakeTorque*4;
	material->setDynamicFrictionV(newv);
	material->setDynamicFriction(_frictionToSide);

	material->setStaticFrictionV(newv*4);
	material->setStaticFriction(2);
	}*/

	if(!hasGroundContact())
		updateContactPosition();
	updateAngularVelocity(dt, handbrake);

	contactInfo->reset();
}
void MotionCallback(int x, int y)
{
	int dx = mx - x;
	int dy = my - y;

	gCameraForward.normalize();
	gCameraRight.cross(gCameraForward,NxVec3(0,1,0));

	NxQuat qx(NxPiF32 * dx * 20 / 180.0f, NxVec3(0,1,0));
	qx.rotate(gCameraForward);
	NxQuat qy(NxPiF32 * dy * 20 / 180.0f, gCameraRight);
	qy.rotate(gCameraForward);

	mx = x;
	my = y;
}
static void MotionCallback(int x, int y)
{
	int dx = mx - x;
	int dy = my - y;
	
	Dir.normalize();
	N.cross(Dir,NxVec3(0,1,0));

	NxQuat qx(NxPiF32 * dx * 20/ 180.0f, NxVec3(0,1,0));
	qx.rotate(Dir);
	NxQuat qy(NxPiF32 * dy * 20/ 180.0f, N);
	qy.rotate(Dir);

	mx = x;
	my = y;
}
Beispiel #17
0
void DXApp::HandleMouseMove(bool bMouseDown, int X, int Y)
{
    if(bMouseDown)
    {
        NxVec3 Temp;
        Temp = Cam.location;
        Temp.y = 0;
        Temp.normalize();
        Temp = Temp.cross(NxVec3(0.0f, 1.0f, 0.0f));
        NxQuat(((float)(Y-OldMY))/20.0f, Temp).rotate(Cam.ViewDir);

        Temp = NxVec3(0.0f, 1.0f, 0.0f);
        NxQuat(((float)(X-OldMX))/20.0f, Temp).rotate(Cam.ViewDir);
    }
    OldMX = X;
    OldMY = Y;
}
Beispiel #18
0
void MouseMotion(int x, int y )
{
	if(g_isButtonDown[0] || g_isButtonDown[2])
	{
		int dx = g_last_x - x;
		int dy = g_last_y - y;

		g_CameraForward.normalize();
		g_CameraRight.cross(g_CameraForward, NxVec3(0,1,0));

		NxQuat qx(NxPiF32 * dx * 20/ 180.0f, NxVec3(0,1,0));
		qx.rotate(g_CameraForward);
		NxQuat qy(NxPiF32 * dy * 20/ 180.0f, g_CameraRight);
		qy.rotate(g_CameraForward);

		g_last_x = x;
		g_last_y = y;
	}

	if (g_isButtonDown[1])
	{
		float dt = 0.1f;

		if ((float) (x-g_last_x)>0)
		{
			g_CameraPos -= g_CameraRight*g_Speed*dt;
		}
		else if ((float) (x-g_last_x)<0)
		{
			g_CameraPos += g_CameraRight*g_Speed*dt;
		}

		if ((float) (y-g_last_y)>0)
		{
			g_CameraPos +=NxVec3(0.0f,1.0f,0.0f)*g_Speed*dt;
		}
		else if ((float) (y-g_last_y)<0)
		{
			g_CameraPos -=NxVec3(0.0f,1.0f,0.0f)*g_Speed*dt;
		}

		g_last_x = x;
		g_last_y = y;
	}
	glutPostRedisplay();
}
unsigned int Forest::onCollideCanopy(unsigned int id, Matrix4f* matrix, void* data)
{
    Forest* __this = reinterpret_cast<Forest*>( data );

    // determine obb of instance
    NxBox instanceOBB = calculateOBB( 
        __this->_canopyBatch->getBatchScheme()->lodGeometry[0], 
        *matrix,
        __this->_desc.collScale
    );
    __this->_debugBoxes.push_back( instanceOBB );

    // collide obbs
    if( NxBoxBoxIntersect( instanceOBB, __this->_canopyOBB ) )
    {
        CanopySimulator* canopy = dynamic_cast<CanopySimulator*>( __this->_currentCanopy );
        // calculate intersection details
        float volume;
        NxVec3 globalIntersectionCenter;
        calculateIntersectionDetails( instanceOBB, __this->_canopyOBB, volume, globalIntersectionCenter );
        assert( volume <= 1.0f );
        // add force to canopy
        NxVec3 linearVelocity = __this->_currentCanopyActor->getLinearVelocity();
        float linearVelocityMagnitude = linearVelocity.magnitude();
        linearVelocity.normalize();
        NxVec3 force = linearVelocity * 0.2f * sqr( linearVelocityMagnitude ) * __this->_currentCanopyInfo->square * -volume;
        __this->_currentCanopyActor->addForceAtPos( force, globalIntersectionCenter, NX_FORCE );
        // damage canopy
        canopy->rip( __this->_desc.ripFactor * force.magnitude() );
        // entangle canopy
        if( volume > __this->_desc.entangleFactor )
        {            
            canopy->entangle( globalIntersectionCenter );
            __this->playSqueakSound( wrap( globalIntersectionCenter ) );
        }
        else
        {
            __this->playRustleSound( wrap( globalIntersectionCenter ) );
        }
    }

    return id;
}
//-----------------------------------------------------------------------------
//  ApplyExplosionPart
//-----------------------------------------------------------------------------
void    CPhysicObj::ApplyExplosionPart (int nPartIdx, float fForce, const NxVec3& vPos)
{
    assert( m_bActivated && (nPartIdx < GetNumParts()) );

	// Solo podemos aplicar fuerzas a objetos físicos dinámicos
	if (!IsDynamic())	return;

    NxActor*    pActor = GetActor( nPartIdx );

    // Aplicamos una fuerza en cada shape, proporcional a su volumen.
    // NOTA: Para que fuese mas realista realmente habria que modular la 
    //       fuerza en funcion de la superficie de proyeccion de cada shape
    //       hacia el punto de origen de la explosion, para aproximar lo que
    //       seria la superficie de impacto.
    uint    nNumShapes = pActor->getNbShapes();
    assert( nNumShapes > 0 );

    NxShape* const* pShapes = pActor->getShapes(); 
    for (uint i = 0; i < nNumShapes; i++)
    {
        NxShape*    pShape = pShapes[i];
        // - Calcular BBox de la shape
        NxBox       shapeBox = PhysicUtils::CalcOBBox( *pShape );
        // - Calcular punto de impacto de la explosion
        NxVec3      vImpactPoint = PhysicUtils::CalcExplosionImpact( shapeBox, vPos );
        //NxVec3      vImpactPoint = shapeBox.GetCenter();
        // - Modular la fuerza de la explosion por el area expuesta de la shape
        float       fVolume     = (shapeBox.extents * 2.f).magnitudeSquared();            
        float       fForceMod   = fForce * fVolume;
        // - Modular a su vez en funcion de la distancia al centro de la explosion
        //   usando una funcion exponencial de atenuacion
        NxVec3      vImpactDir  = vImpactPoint - vPos;
        float       fDist       = vImpactDir.normalize();
        // NOTA: vamos a marcar una zona de radio minimo donde se aplique la fuerza maxima
        //static float s_fMinDist = 0.1f;
        //fDist += s_fMinDist;
        static float s_fAttenuationFactor = 0.05f;
        fForceMod *= exp( -s_fAttenuationFactor * fDist );
        // - Aplicar la fuerza en el punto de impacto
        pActor->addForceAtPos( vImpactDir * fForceMod, vImpactPoint, NX_IMPULSE );
    }
}
Beispiel #21
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 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 ) );
   }
}
Beispiel #23
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;
}
Beispiel #24
0
void CanopySimulator::Rope::initialize(NxActor* actor1, NxVec3 anchor1, NxActor* actor2, NxVec3 anchor2)
{
    _nxActor1 = actor1; assert( _nxActor1 );
    _nxActor2 = actor2; assert( _nxActor2 );
    _anchor1 = anchor1;
    _anchor2 = anchor2;

    // calculate worldspace positions for connections points
    Matrix4f ltm1  = wrap( _nxActor1->getGlobalPose() );
    Matrix4f ltm2  = wrap( _nxActor2->getGlobalPose() );
    NxVec3 pos1 = wrap( Gameplay::iEngine->transformCoord( wrap( _anchor1 ), ltm1 ) );
    NxVec3 pos2 = wrap( Gameplay::iEngine->transformCoord( wrap( _anchor2 ), ltm2 ) );
    NxVec3 dir  = pos2 - pos1;

    // check distance btw connection points (correction just for stability purpose)
    float idist = dir.magnitude();
    dir.normalize();

    // create intermediate segment bodies
    NxVec3 pos = pos1;
    float step = idist / _numJoints;
    for( unsigned int i=0; i<_numJoints-1; i++ )
    {
        // segment position
        pos += dir * step;
        // create segment body
        NxBodyDesc nxBodyDesc;
        nxBodyDesc.mass = _mass / ( _numJoints - 1 );
        nxBodyDesc.massSpaceInertia.set( nxBodyDesc.mass, nxBodyDesc.mass, nxBodyDesc.mass );
        nxBodyDesc.linearDamping = 2.0f;
        nxBodyDesc.angularDamping = 0.0f;
        nxBodyDesc.flags = NX_BF_VISUALIZATION;
        nxBodyDesc.solverIterationCount = 32;
        NxActorDesc nxActorDesc;
        nxActorDesc.body = &nxBodyDesc;
        nxActorDesc.globalPose.M.id();
        nxActorDesc.globalPose.t = pos;
        _nxSegmentBody[i] = _nxScene->createActor( nxActorDesc );
        assert( _nxSegmentBody[i] );
        // initialize velocity
        _nxSegmentBody[i]->addForce( _nxActor1->getLinearVelocity(), NX_VELOCITY_CHANGE );
    }

    // create joints
    for( i=0; i<_numJoints; i++ )
    {
        // first joint (actor1-segment1)
        if( i == 0 )
        {
            NxDistanceJointDesc jointDesc;
            jointDesc.actor[0] = _nxActor1;
            jointDesc.actor[1] = _nxSegmentBody[0];
            jointDesc.maxDistance = _length / _numJoints;
            jointDesc.minDistance = 0.0f;
            jointDesc.flags = NX_DJF_MAX_DISTANCE_ENABLED;
            jointDesc.localAnchor[0] = _anchor1;
            jointDesc.localAnchor[1].set( 0,0,0 );
            jointDesc.jointFlags = NX_JF_VISUALIZATION;
            _nxSegmentJoint[i] = _nxScene->createJoint( jointDesc );
            assert( _nxSegmentJoint[i] );
        }
        // last joint (segmentN-actor2)
        else if( i == _numJoints-1 )
        {
            NxDistanceJointDesc jointDesc;
            jointDesc.actor[0] = _nxSegmentBody[_numJoints-2];
            jointDesc.actor[1] = _nxActor2;
            jointDesc.maxDistance = _length / _numJoints;
            jointDesc.minDistance = 0.0f;
            jointDesc.flags = NX_DJF_MAX_DISTANCE_ENABLED;
            jointDesc.localAnchor[0].set( 0,0,0 );
            jointDesc.localAnchor[1] = _anchor2;
            jointDesc.jointFlags = NX_JF_VISUALIZATION;
            _nxSegmentJoint[i] = _nxScene->createJoint( jointDesc );
            assert( _nxSegmentJoint[i] );
        }
        // intermediate joint
        else
        {
            NxDistanceJointDesc jointDesc;
            jointDesc.actor[0] = _nxSegmentBody[i-1];
            jointDesc.actor[1] = _nxSegmentBody[i];
            jointDesc.maxDistance = _length / _numJoints;
            jointDesc.minDistance = 0.0f;
            jointDesc.flags = NX_DJF_MAX_DISTANCE_ENABLED;
            jointDesc.localAnchor[0].set( 0,0,0 );
            jointDesc.localAnchor[1].set( 0,0,0 );
            jointDesc.jointFlags = NX_JF_VISUALIZATION;
            _nxSegmentJoint[i] = _nxScene->createJoint( jointDesc );
            assert( _nxSegmentJoint[i] );
        }
    }
}
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 );
}
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 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;
    }
}
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 );
}
Beispiel #29
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;
}
void Airplane::onUpdatePhysics()
{
    if (_phActor != NULL) {
        if (_phActor->isSleeping()) {
            _phActor->wakeUp();
            return;
        }

        /// PHYSICS
        // altitude [m]
        NxVec3 pos = _phActor->getGlobalPosition();
        NxVec3 velocity = _phActor->getLinearVelocity();
        float altitude = pos.y;

        // speed (m/s) squared
        const float Vsq = velocity.magnitudeSquared();

        // 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);

        // AOA
        NxMat34 globalPose = _phActor->getGlobalPose();
        NxVec3 x = globalPose.M.getColumn(0);
        NxVec3 y = globalPose.M.getColumn(1);
        NxVec3 z = globalPose.M.getColumn(2);

        NxVec3 velocityN = velocity;
        velocityN.normalize();
        const float AOA = -::calcAngle( z, velocityN, x );

        // ADD DRAG
        const float Cd = 0.027f;
        const float Fd = 0.5f * AirDensityOld * Vsq * Cd * 10.0f;

        // crosssectional objects
        const unsigned int xsections_c = 1;
        NxVec3 xsections[xsections_c];
        // fuselage
        //_phActor->addLocalForce(wrap(_propellerFrame->getAt()) * 100.0f);

        // synchronize physics & render
        //_clump->getFrame()->setPos(wrap(_phActor->getGlobalPosition()));
        //_clump->getFrame()->setMatrix(wrap(_phActor->getGlobalPose()));
    }

    if( !_roughMode )
    {
        float dt = ::simulationStepTime;

        _clump->getAnimationController()->advance( dt * _desc.animationSpeed );
        _clump->getFrame()->getLTM();

        // landing mode
        if( _landingMode && _clump->getFrame()->getPos()[1] > _desc.lastAltitude )
        {
            _clump->getFrame()->translate( Vector3f( 0.0f, -_desc.loweringSpeed * dt, 0.0f ) );
        }

        // calculate velocity
        Vector3f currPoint = _propellerFrame->getPos();
        _velocity = ( currPoint - _prevPoint ) / ( dt );
        _prevPoint = currPoint;
    }

    // fly by waypoints
    if( _desc.waypoints.size() && _waypointId < _desc.waypoints.size() - 1 )
    {
        // current waypoints
        AirplaneDesc::WayPoint waypoint1 = _desc.waypoints[_waypointId];
        AirplaneDesc::WayPoint waypoint2 = _desc.waypoints[_waypointId+1];

        // trajectory vector
        Vector3f trajectory = waypoint2.pos - waypoint1.pos;

        // current velocity
        float vel = waypoint1.vel * ( 1 - _waypointFactor ) + waypoint2.vel * _waypointFactor;

        // motion distance
        float distance = vel * ::simulationStepTime;

        // determine factor distance
        float fDistance = distance / trajectory.length();

        // move in factor space
        _waypointFactor += fDistance;

        // out of current waypoints?
        if( _waypointFactor > 1 )
        {
            // determine rest of distance
            fDistance = _waypointFactor - 1;
            distance = fDistance * trajectory.length();
            _waypointFactor = 0;
            _waypointId++;

            if( _waypointId < _desc.waypoints.size() - 1 )
            {
                // new waypoints
                waypoint1 = _desc.waypoints[_waypointId];
                waypoint2 = _desc.waypoints[_waypointId+1];

                // new trajectory vector
                trajectory = waypoint2.pos - waypoint1.pos;

                // new factor distance
                fDistance = distance / trajectory.length();

                // move in factor space
                _waypointFactor += fDistance;
            }
            else
            {
                _waypointFactor = 0;
            }
        }
    }
}