Login

Subversion Repositories NedoOS

Rev

Blame | Last modification | View Log | Download | RSS feed

╚ёяюы№чє  чръюэ ёюїЁрэхэш  шьяєы№ёр, яюыєўрхь ЇюЁьєыє ЁрёўхЄр тхъЄюЁют ёъюЁюёЄш °рЁют W1 ш W2 яюёых єфрЁр:

W1 = V1 + M2*(1+k)/(M1+M2)*(|V1|*cos(fi1) + |V2|*cos(fi2))*n1;
W2 = V2 + M1*(1+k)/(M1+M2)*(|V1|*cos(fi1) + |V2|*cos(fi2))*n2;

╟фхё№ fi1 ш fi2 - єуы√ ьхцфє ышэшхщ юс∙хщ эюЁьрыш ш тхъЄюЁрьш ёъюЁюёЄхщ V1 ш V2 т ьюьхэЄ єфрЁр.

n1 ш n2 - тхъЄюЁ√ хфшэшўэ√ї эюЁьрыхщ ъ яютхЁїэюёЄш °рЁют т Єюўъх ъюэЄръЄр.
|V1| ш |V2| - ьюфєыш тхъЄюЁют ёъюЁюёЄхщ V1 ш V2. 





    void PlayRoomActors::Tick()
    {
      Actors::Tick();
      Vertex3Df min, max;
      min = *playRoomLevelInfo->GetMin();
      max = *playRoomLevelInfo->GetMax();
      // ╬сЁрсюЄрЄ№ яЁюфтшцхэшх ръЄхЁют
      float time = timer->Intervalf();
      int count = 0;
      while ( time > 0 )
      {
        float timeToHit = time;
        PlayRoomActor *actor;
        PlayRoomActor *who = NULL;
        PlayRoomActor *whom = NULL;
        Vertex3Df normal, normal2;
        float when;
        // ═рїюфшь сышцрщ°хх ёЄюыъэютхэшх
        for ( actor = (PlayRoomActor *) actors.GetFirst(); actor;
              actor = (PlayRoomActor *) actor->GetNext() )
        {
          // ╧ЁютхЁшь ёЄюыъэютхэш  ё юуЁрэшўшЄхы ьш яюы 
          for ( int i = 0; i <= 2; i++ )
          {
            if ( actor->speed[ i ] )
            {
              float dist = max[ i ] - actor->pos[ i ] - actor->radius;
              when = dist / actor->speed[ i ];
              //if ( (when >= -maxE) && (when <= maxE) )
              //  when = 0;
              if ( (when > 0) && (when < timeToHit) )
              {
                timeToHit = when;
                who = actor;
                whom = NULL;
                normal.x = normal.y = normal.z = 0;
                normal[ i ] = -1.0f;
              }
              else if ( (dist < 0) && (actor->speed[ i ] > 0) )
              {
                Vertex3Df normal2( 0, 0, 0 );
                normal2[ i ] = -1.0f;
                //actor->speed[ i ] = -dist;
                actor->DoHit( NULL, normal2, -dist );
              };
     
              dist = actor->pos[ i ] - min[ i ] - actor->radius;
              when = -dist / actor->speed[ i ];
              if ( (when >= -maxE) && (when <= maxE) )
                when = 0;
              if ( (when > 0) && (when < timeToHit) )
              {
                timeToHit = when;
                who = actor;
                whom = NULL;
                normal.x = normal.y = normal.z = 0;
                normal[ i ] = +1.0f;
              }
              else if ( (dist <= 0) && (actor->speed[ i ] < 0) )
              {
                Vertex3Df normal2( 0, 0, 0 );
                normal2[ i ] = +1.0f;
                //actor->speed[ i ] = dist;
                actor->DoHit( NULL, normal2, -dist );
              };
            };
          };
          // ╧ЁютхЁшь ёЄюыъэютхэш  ё фЁєушьш °рЁрьш
          for ( PlayRoomActor *other = (PlayRoomActor *) actor->GetNext();
                other; other = (PlayRoomActor *) other->GetNext() )
          {
            if ( IntersectSphereBySphere( actor->pos, actor->radius, actor->speed,
                                          other->pos, other->radius, other->speed,
                                          &when, &normal2 ) )
            {
              if ( (when >= -maxE) && (when <= maxE) )
                when = 0;
              if ( (when > 0) && (when < timeToHit) )
              {
                timeToHit = when;
                who = actor;
                whom = other;
                normal = normal2;
              };
              if ( (when == 0) && ((actor->speed & other->speed) < 0) )
              {
                actor->DoHit( other, normal2 );
              };
            };
          };
          // ╧ЁютхЁшь х∙х ёЄюыъэютхэш ...
          for ( int i = 0; i < 4; i++ )
          {
            if ( IntersectTrisBySphere( playRoomLevel->GetPyramid( i )[ 0 ],
                                        playRoomLevel->GetPyramid( i )[ 1 ],
                                        playRoomLevel->GetPyramid( i )[ 2 ],
                    actor->pos, actor->radius, actor->speed, &when, &normal2 ) )
            {
              if ( (when >= -maxE) && (when <= maxE) )
                when = 0;
              if ( (when > 0) && (when < timeToHit) )
              {
                timeToHit = when;
                who = actor;
                whom = NULL;
                normal = normal2;
              }
              float dist = when * actor->speed.Length();
              if ( (dist < 0) && (dist >= -actor->radius) && ((actor->speed & normal2) < 0) )
              {
                actor->DoHit( other, normal2, -dist );
              };
            };
          };
        };
        // ╤фхырхь °ру
        if ( count++ > 20 )
          timeToHit = time;
        time -= timeToHit;
        for ( actor = (PlayRoomActor *) actors.GetFirst(); actor;
              actor = (PlayRoomActor *) actor->GetNext() )
        {
          actor->DoStep( timeToHit );
        };
        // ╧Ёютхфхь ёЄюыъэютхэшх
        if ( who )
        {
          who->DoHit( whom, normal );
        };
      };
    }; 





    float k = 2.0f; // k = [ 1.0f ... 2.0f ]
    float coef = mass / (mass + whom->mass);
    Vertex3Df relSpeed = speed - whom->speed;
    Vertex3Df nRelSpeed = -((-normal) & relSpeed) * normal;
    nRelSpeed *= k;
    speed -= (1.0f - coef) * nRelSpeed;
    whom->speed += coef * nRelSpeed;

mass, whom->mass - ьрёё√ Єхъє∙хую, ш фЁєуюую °рЁр
speed, whom-speed - ёъюЁюёЄш Єхъє∙хую ш фЁєуюую °рЁр (тхъЄюЁ√)
normal - эюЁьры№ т Єюўъх ёюєфрЁхэш  (эряЁртыхэр тэєЄЁ№ Єхъє∙хую °рЁр) (Єюцх тхъЄюЁ)
k - ъю¤ЇЇшЎшхэЄ єяЁєуюёЄш. яЁш ъ = 2 єфрЁ рсёюы■Єэю єяЁєу, яЁш k = 1 - рсё. эхєяЁєу

фы  эрїюцфхэш  эюЁьрыш ёюяЁшъюёэютхэш  шёяюы№чютрырё№ Єрър  Ї- :

// IntersectSphereBySphere: тючтЁр∙рхЄ true, хёыш юъЁєцэюёЄш ё Ёрфшєёрьш
// r1 ш r2 ё ЎхэЄЁрьш т Єюўърї c1 ш ё2, фтшцє∙шхё  ёю ёъюЁюёЄ ьш v1 ш v2
// ёюяЁшъюёэєЄё  т Ёхчєы№ЄрЄх ётюхую фтшцхэш .
// ┼ёыш тючтЁр∙рхЄ true, Єю т ярЁрьхЄЁ time ёюїЁрэ хЄё  тЁхь  ъюЄюЁюх фюыцэю
// яЁющЄш фю ьюьхэЄр ёюяЁшъюёэютхэш , р т ярЁрьхЄЁ normal - эюЁьры№ ёюяЁшъюёэютрэш , Є.х.
// хфшэшўэ√щ тхъЄюЁ, ыхцр∙шщ эр юЄЁхчъх, ёюхфшэ ■∙хщ ЎхэЄЁ√ юъЁєцэюёЄхщ т ьюьхэЄ
// ёюяЁшъюёэютхэш , эряЁртыхээ√щ т ёЄюЁюэє ЎхэЄЁр яхЁтющ юъЁєцэюёЄш c1.
template < class T >
bool IntersectSphereBySphere( const Vertex3D< T > &c1, T r1, const Vertex3D< T > &v1,
                              const Vertex3D< T > &c2, T r2, const Vertex3D< T > &v2,
                              T *time, Vertex3D< T > *normal )
{
  Vertex3D< T > nPos = c1 - c2;
  Vertex3D< T > nSpeed = v1 - v2;
  T nSpeedLen = nSpeed.Length();
  if ( nSpeedLen <= 0 )
    return false;
  Vertex3D< T > nSpeedDir = nSpeed / nSpeedLen;
  T dist = (-nPos) & nSpeedDir;
  if ( dist <= 0 )
    return false;
  T nPosLen = nPos.Length();
  T r = r1 + r2;
  T x = nPosLen * nPosLen - dist * dist;
  if ( x > r * r )
    return false;
  T z = dist - sqrtf( r * r - x );
  *time = z / nSpeedLen;
  *normal = +nPos + nSpeedDir * z;
  normal->Normalize();
  return true;
};

ЄєЄ ╬╬╧-э√щ ъюф, Єхъє∙шщ юс·хъЄ - °рЁ, р whom - °рЁ ё ъюЄюЁ√ь ёЄюыъэютхэшх яЁюшёїюфшЄ.
mass, speed яюы  ьрёё ш ёъюЁюёЄхщ ёююЄтхЄёЄтхээю, raduis т фрээюь ЁрёўхЄх эх эєцхэ
normal - эюЁьры№ ёЄюыъэютхэш , т ёє∙эюёЄш тхъЄюЁ ёюхфшэ ■∙шщ ЎхэЄЁ√ °рЁют, эю хфшэшўэющ фышэ√. т ъръє■ ёЄюЁюэє эряЁртыхэ єцх эх яюьэ■.
хёёхёэю шёяюы№чєхЄё  тхъЄюЁэр  рыухсЁр, Єръ ўЄю operator& - ёъры Ёэюх єьэюцхэшх тхъЄюЁют (dot product).
k ъюэЄЁюышЁєхЄ ёЄхяхэ№ єяЁєуюёЄш єфрЁр, яЁш 2 - рсёюы■Єэю єяЁєушщ.




TVector pb1,pb2,xaxis,U1x,U1y,U2x,U2y,V1x,V1y,V2x,V2y;

double a,b;

// ═рщЄш Ёрёяюыюцхэшх яхЁтюую °рЁр

pb1=OldPos[BallColNr1]+ArrayVel[BallColNr1]*BallTime;

// ═рщЄш Ёрёяюыюцхэшх тЄюЁюую °рЁр

pb2=OldPos[BallColNr2]+ArrayVel[BallColNr2]*BallTime;

xaxis=(pb2-pb1).unit(); // ═рщЄш X-Axis

a=xaxis.dot(ArrayVel[BallColNr1]); // ═рщЄш яЁюхъЎш■

U1x=xaxis*a;      // ═рщЄш ёяЁюхЎшЁютрээ√х тхъЄюЁр

U1y=ArrayVel[BallColNr1]-U1x;

xaxis=(pb1-pb2).unit(); // ╤фхырЄ№ Єръцх, ъръ т√°х

b=xaxis.dot(ArrayVel[BallColNr2]); // ═рщЄш яЁюхъЎш■

U2x=xaxis*b; // ┬хъЄюЁ√ фы  фЁєуюую °рЁр

U2y=ArrayVel[BallColNr2]-U2x;

V1x=(U1x+U2x-(U1x-U2x))*0.5; // ╤хщўрё эрщЄш эют√х ёъюЁюёЄш

V2x=(U1x+U2x-(U2x-U1x))*0.5;

V1y=U1y;

V2y=U2y;

for (j=0;j<NrOfBalls;j++) // ╬сэютшЄ№ тёх эют√х Ёрёяюыюцхэш 

ArrayPos[j]=OldPos[j]+ArrayVel[j]*BallTime;

ArrayVel[BallColNr1]=V1x+V1y; // ╙ёЄрэютшЄ№ эют√х тхъЄюЁр ёъюЁюёЄш

ArrayVel[BallColNr2]=V2x+V2y; // ёЄюыъэєт°шьё  °рЁрь

 



яєёЄ№ 1щ °рЁ т яЁюЎхёёх ёЄюыъэютхэш  яюыєўрхЄ шчьхэхэшх шьяєы№ёр p, т юЄёєЄёЄтшш ЄЁхэш  юэю эряЁртыхээю яю эюЁьрыш  n (ышэшш, ёюхф. ЎхэЄЁ√ °рЁют т ьюьхэЄ єфрЁр), p = p*n, Єюуфр яю ╟╤╚ 2щ °рЁ яюыєўрхЄ -p,
Єюуфр эют√х ёъюЁюёЄш
v1'=v1+p/m1
v2'=v2 -p/m2
яЁш рсё.єяЁєуюь єфрЁх шч ╟╤▌
m1*v1^2+m2*v2^2=m1*(v1+p*n/m1)^2+m2*(v2-p*n/m2)^2
2*p*(n,v1-v2)+p^2*(1/m1+1/m2)=0
p=2*(v2-v1,n)/(1/m1+1/m2) 





dx1n-dx1=Rx
dx2n-dx2=-Rx
dy1n-dy1=Ry
dy2n-dy2=-Ry
dx1^2 + dy1^2 + dx2^2 + dy2^2 = dx1n^2 + dy1n^2 + dx2n^2 + dy2n^2
dx2n=(dx1+dx2)-dx1n
dy2n=(dy1+dy2)-dy1n

R - "ёшыр" ЁхръЎшш эряЁртыхэр тфюы№ яЁ ьющ, ёюхфшэ ■∙хщ ЎхэЄЁ√ °рЁют
ърър  є эх╕ фышэр? чртшёшЄ юЄ яЁюхъЎшш шёїюфэющ юЄэюёшЄхы№эющ ёъюЁюёЄш эр эюЁьры№ ьхцфє °рЁрьш


х╕ ьюфєы№ - ёъры Ёэюх яЁюшчтхфхэшх (v2-v1,n)?




TODO:
яЁшЄ уштрэшх ъ ыєчрь
ыєч√ ъЁєяэхх
ЄЁ ёЄш ёЄюы ъэюяъющ





ьхЄъш эх фюыцэ√ яхЁхёхърЄ№ё  яю эюьхЁрь ё ртЄюьхЄърьш?
хёыш ьхЄър т ЇєэъЎшш, ъюЄюЁр  т√°х ёюфхЁцшЄ for/do/if (ё яхЁхїюфюь, р эх ret CC) шыш ъръшх-Єю х∙╕ эхяюэ Єэ√х єёыютш , Єю юэр эх ьюцхЄ яюёўшЄрЄ№ ъръющ-Єю ЁрчьхЁ
єсЁры ёЄхъЇЁхщь (___sdcc_enter_ix - ьюцхЄ яю тшЄ№ё  ш фы  тЁхьхээ√ї Ёхчєы№ЄрЄют т√ўшёыхэшщ, ш фрцх эш ё Єюую эш ё ёхую) - эх яюьюуыю
ьхЄър ю°шсюўэю ухэхЁшЁєхЄё  ё Єрсєы Ўшхщ, эю ¤Єю, тЁюфх с√, эх трцэю