void rameneEnContact(Particule* a, Particule* b, Vec3 normale, float valPenetration) { // On applique sur cet axe la moitié de la distance de pénetration; Vec3 separateur = Vec3_Mul_Scal_out(normale, -0.5*valPenetration); Vec3_Sub(&a->position, separateur); if (b != NULL) Vec3_Add(&b->position, separateur); else Vec3_Sub(&a->position, separateur); }
void CollisionResolver_Resolve(ElemContact* tetepile) { ElemContact* curseur = tetepile; Particule* a = NULL; Particule* b = NULL; while (curseur != NULL) { a = curseur->contact.a; b = curseur->contact.b; // Vecteur de la vitesse de rapprochement de b vers a Vec3 vitRelative = a->vitesse; if (b != NULL) Vec3_Sub(&vitRelative, b->vitesse); // Projection de la vitesse relative sur la normale de la collision Vec3 impulsionA = Vec3_Project(vitRelative, curseur->contact.normale); float totalInverseMass = 1 / a->masse; if (b != NULL) totalInverseMass += (1 / b->masse); Vec3_Div_Scal(&impulsionA, totalInverseMass); Vec3 impulsionB = impulsionA; // En dessous d'un certain seuil de vitesse, on annule l'élasticité pour réduire les instabilités float coeffA = a->coeffRebond, coeffB; if (b != NULL) coeffB = b->coeffRebond; // if (abs(a->vitesse.y) + abs(a->vitesse.x) + abs(a->vitesse.z) < 0.001) // coeffA = 0; // // if (abs(b->vitesse.y) + abs(b->vitesse.x) + abs(b->vitesse.z) < 0.001) // coeffB = 0; Vec3_Mul_Scal(&impulsionA, (1 + coeffA) / a->masse); if (b != NULL) Vec3_Mul_Scal(&impulsionB, (1 + coeffB) / b->masse); Vec3_Sub(&a->vitesse, impulsionA); if (b != NULL) Vec3_Add(&b->vitesse, impulsionB); rameneEnContact(a, b, curseur->contact.normale, curseur->contact.interpenetration); curseur = curseur->suivant; } }
float MDTRA_Compact_PDB_File :: get_distance( int atIndex1, int atIndex2 ) const { const MDTRA_Compact_PDB_Atom* at1 = fetchAtomBySerialNumber( atIndex1 ); const MDTRA_Compact_PDB_Atom* at2 = fetchAtomBySerialNumber( atIndex2 ); if (!at1 || !at2) return 0.0f; float vecDist[3]; float len; Vec3_Sub( vecDist, at1->original_xyz, at2->original_xyz ); Vec3_Len( len, vecDist ); return len; }
void Player_Update( float timeStep ) { if( player ) { TVec3 vAxis = Vec3_Set( 0.0f, 1.0f, 0.0f ); // get correct vectors for moving TVec3 look = Entity_GetLookVector( player->pivot ); TVec3 right = Entity_GetRightVector( player->pivot ); TVec3 listenerPosition = Entity_GetGlobalPosition( player->cameraPivot ); Lightprobe_LightEntity( player->weapon->model ); player->onGround = false; for( int i = 0; i < player->body.contactCount; i++ ) { TContact * contact = &player->body.contacts[i]; // check angle between contact normal and vertical axis, it must be less than 60 degrees if( Vec3_Angle( vAxis, contact->normal ) < M_PI / 3.0 ) { player->onGround = true; } } // ==================== // moving player->destVelocity = Vec3_Zero(); player->move = false; if( Input_IsKeyDown( KEY_W )) { player->destVelocity = Vec3_Add( player->destVelocity, look ); player->move = true; } if( Input_IsKeyDown( KEY_S )) { player->destVelocity = Vec3_Sub( player->destVelocity, look ); player->move = true; } if( Input_IsKeyDown( KEY_A )) { player->destVelocity = Vec3_Add( player->destVelocity, right ); player->move = true; } if( Input_IsKeyDown( KEY_D )) { player->destVelocity = Vec3_Sub( player->destVelocity, right ); player->move = true; } if( Input_IsKeyDown( KEY_C ) ) { player->crouch = true; if( player->body.shape->sphereRadius > player->crouchRadius ) { player->body.shape->sphereRadius -= 0.05f; } else { player->body.shape->sphereRadius = player->crouchRadius; } } else { player->crouch = false; char standUp = 1; // before stand up, we must trace ray up on player's head, to ensure, that // there enough space to stand up. TVec3 end = Vec3_Set( player->body.position.x, player->body.position.y + 1.0f, player->body.position.z ); TRay headRay = Ray_Set( player->body.position, end ); TRayTraceResult out; Ray_TraceWorldStatic( &headRay, &out ); if( out.body ) { float maxRadius = player->shape.sphereRadius + 0.4f; if( Vec3_SqrDistance( out.position, player->body.position ) < maxRadius * maxRadius ) { standUp = 0; player->crouch = true; } } if( standUp ) { if( player->body.shape->sphereRadius < player->standRadius ) { player->body.shape->sphereRadius += 0.04f; } else { player->body.shape->sphereRadius = player->standRadius; } } } // sync step sound position with player position for( int i = 0; i < player->stepSoundGroup->count; i++ ) { SoundSource_SetPosition( &player->stepSoundGroup->sounds[i], &listenerPosition ); if( player->crouch ) { SoundSource_SetVolume( &player->stepSoundGroup->sounds[i], 0.5f ); } else { SoundSource_SetVolume( &player->stepSoundGroup->sounds[i], 1.0f ); } } // emit step sound only if got contact with the ground if( player->body.contactCount > 0 ) { TContact * lowestContact = &player->body.contacts[0]; for( int i = 0; i < player->body.contactCount; i++ ) { if( player->body.contacts[i].position.y < lowestContact->position.y ) { lowestContact = &player->body.contacts[i]; } } // select emittable sounds if( lowestContact->triangle ) { // iterate over all possible step sound groups for( int i = 0; i < STEP_GROUP_COUNT; i++ ) { // iterate over each material in group for( int j = 0; j < player->stepSounds[i].materialCount; j++ ) { if( lowestContact->triangle->material == player->stepSounds[i].material[j] ) { player->stepSoundGroup = &player->stepSounds[i]; } } } } if( player->pathLength > 15 * player->speed ) { int randomSound = rand() % player->stepSoundGroup->count; if( randomSound >= 4 ) { randomSound = 3; } SoundSource_Play( &player->stepSoundGroup->sounds[ randomSound ] ); player->pathLength = 0.0f; } } float realSpeed = player->speed; player->run = false; if( Input_IsKeyDown( KEY_LeftShift ) && !player->crouch ) { realSpeed *= player->speedMultiplier; player->run = true; } if( player->crouch ) { realSpeed *= 0.65f; } if( player->move ) { // prevent divide by zero player->destVelocity = Vec3_Normalize( player->destVelocity ); player->pathLength += realSpeed * 0.5f; } float interpCoeff = 0.25f; if( !player->onGround ) { interpCoeff = 0.0035f; } player->destVelocity.x *= realSpeed; player->destVelocity.z *= realSpeed; player->velocity.x += ( player->destVelocity.x - player->velocity.x ) * interpCoeff; player->velocity.z += ( player->destVelocity.z - player->velocity.z ) * interpCoeff; // do not overwrite gravity component (y), apply only x and z player->body.linearVelocity.x = player->velocity.x * timeStep; player->body.linearVelocity.z = player->velocity.z * timeStep; // ==================== // jump if( Input_IsKeyHit( KEY_Space ) ) { if( player->onGround ) { player->body.linearVelocity.y += player->jumpStrength; } } // sync pivot's position with physical body player->pivot->localPosition = player->body.position; // ==================== // mouse look player->yaw -= Input_GetMouseXSpeed() * player->mouseSensivity * timeStep; player->pitch += Input_GetMouseYSpeed() * player->mouseSensivity * timeStep; // clamp pitch if( player->pitch > player->maxPitch ) { player->pitch = player->maxPitch; } if( player->pitch < -player->maxPitch ) { player->pitch = -player->maxPitch; } right = Vec3_Set( 1, 0, 0 ); vAxis = Vec3_Set( 0, 1, 0 ); player->pivot->localRotation = Quaternion_SetAxisAngle( vAxis, player->yaw ); player->cameraPivot->localRotation = Quaternion_SetAxisAngle( right, player->pitch ); // sound TVec3 up = Entity_GetUpVector( player->cameraPivot ); SoundListener_SetPosition( &listenerPosition ); SoundListener_SetOrientation( &look, &up ); // weapon Weapon_Update( player->weapon ); if( Input_IsMouseDown( MB_Left )) { Weapon_Shoot( player->weapon ); } player->weapon->moveSpeed = player->body.linearVelocity; Player_CameraShake( ); } }
void Octree_BuildRecursiveInternal( TOctreeNode * node, TTriangle * triangles, int triangleCount, int * indices, int indexCount, int maxTrianglesPerNode ) { if( indexCount < maxTrianglesPerNode ) { int sizeBytes = sizeof( int ) * indexCount; node->indexCount = indexCount; node->indices = Memory_AllocateClean( sizeBytes ); memcpy( node->indices, indices, sizeBytes ); return; } Octree_SplitNode( node ); for( int childNum = 0; childNum < 8; childNum++ ) { TOctreeNode * child = node->childs[childNum]; TVec3 middle = Vec3_Middle( child->min, child->max ); TVec3 halfSize = Vec3_Scale( Vec3_Sub( child->max, child->min ), 0.5f ); float center[3] = {middle.x, middle.y, middle.z}; float half[3] = {halfSize.x, halfSize.y, halfSize.z}; // count triangles in each leaf int leafTriangleCount = 0; for( int i = 0; i < triangleCount; i++ ) { TTriangle * triangle = triangles + i; float triverts[3][3] = { {triangle->a.x,triangle->a.y, triangle->a.z}, {triangle->b.x,triangle->b.y, triangle->b.z}, {triangle->c.x,triangle->c.y, triangle->c.z} }; if( triBoxOverlap( center, half, triverts ) || Octree_IsPointInsideNode( child, &triangle->a ) || Octree_IsPointInsideNode( child, &triangle->b ) || Octree_IsPointInsideNode( child, &triangle->c ) ) { leafTriangleCount++; } } // allocate memory for temporary leaf and fill it with data int * leafIndices = Memory_NewCount( leafTriangleCount, int ); int triangleNum = 0; for( int i = 0; i < triangleCount; i++ ) { TTriangle * triangle = triangles + i; float triverts[3][3] = { {triangle->a.x,triangle->a.y, triangle->a.z}, {triangle->b.x,triangle->b.y, triangle->b.z}, {triangle->c.x,triangle->c.y, triangle->c.z} }; if( triBoxOverlap( center, half, triverts )|| Octree_IsPointInsideNode( child, &triangle->a ) || Octree_IsPointInsideNode( child, &triangle->b ) || Octree_IsPointInsideNode( child, &triangle->c ) ) { *(leafIndices + triangleNum) = i; triangleNum++; } } // recursively process childs of this node Octree_BuildRecursiveInternal( child, triangles, triangleCount, leafIndices, triangleNum, maxTrianglesPerNode ); // leafFaces data already copied to another node, so we can free temporary array Memory_Free( leafIndices ); } }