Blame | Last modification | View Log | Download
╚ёяюы№чє чръюэ ёюїЁрэхэш шьяєы№ёр, яюыєўрхь ЇюЁьєыє ЁрёўхЄр тхъЄюЁют ёъюЁюёЄш °рЁют 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 - ьюцхЄ яю тшЄ№ё ш фы тЁхьхээ√ї Ёхчєы№ЄрЄют т√ўшёыхэшщ, ш фрцх эш ё Єюую эш ё ёхую) - эх яюьюуыю
ьхЄър ю°шсюўэю ухэхЁшЁєхЄё ё Єрсєы Ўшхщ, эю ¤Єю, тЁюфх с√, эх трцэю