📄 mycollision1view.cpp
字号:
if (posi.dist(OldPos[j])<=40)
{
point=posi;
if (Timedummy>(MyTime-Add)) Timedummy=MyTime-Add;
BallNr1=i;
BallNr2=j;
break;
}
}
}
}
if (Timedummy!=10000)
{
TimePoint=Timedummy;
return 1;
}
return 0;
}
// 主函数,当前步长中运动所有的球,检查碰撞现象
void CMyCollision1View::idle()
{
double rt,rt2,rt4,lamda=10000;
CVector norm,uveloc;
CVector normal,point,time;
double RestTime,BallTime;
CVector Pos2;
int BallNr=0,dummy=0,BallColNr1,BallColNr2;
CVector Nc;
if (!hook_toball1)
{
camera_rotation+=0.1f;
if (camera_rotation>360)
camera_rotation=0;
}
RestTime=Time;
lamda=1000;
// 使用Euler方程计算下一步的速度
for (int j=0;j<NrOfBalls;j++)
ArrayVel[j]+=accel*RestTime;
// 当时间没有结束
while (RestTime>ZERO)
{
lamda=10000;
// 对所有的球在球与平面/圆柱体之间找到最近的相交点
for (int i=0;i<NrOfBalls;i++)
{
// 计算新的位置和距离
OldPos[i]=ArrayPos[i];
CVector::unit(ArrayVel[i],uveloc);
ArrayPos[i]=ArrayPos[i]+ArrayVel[i]*RestTime;
rt2=OldPos[i].dist(ArrayPos[i]);
// 测试在球与5个平面之间是否发生碰撞
if (TestIntersionPlane(pl1,OldPos[i],uveloc,rt,norm))
{
// 查找相交时间
rt4=rt*RestTime/rt2;
if (rt4<=lamda)
{
if (rt4<=RestTime+ZERO)
if (! ((rt<=ZERO)&&(uveloc.dot(norm)>ZERO)) )
{
normal=norm;
point=OldPos[i]+uveloc*rt;
lamda=rt4;
BallNr=i;
}
}
}
if (TestIntersionPlane(pl2,OldPos[i],uveloc,rt,norm))
{
rt4=rt*RestTime/rt2;
if (rt4<=lamda)
{
if (rt4<=RestTime+ZERO)
if(! ((rt<=ZERO)&&(uveloc.dot(norm)>ZERO)) )
{
normal=norm;
point=OldPos[i]+uveloc*rt;
lamda=rt4;
BallNr=i;
dummy=1;
}
}
}
if (TestIntersionPlane(pl3,OldPos[i],uveloc,rt,norm))
{
rt4=rt*RestTime/rt2;
if (rt4<=lamda)
{
if (rt4<=RestTime+ZERO)
if (! ((rt<=ZERO)&&(uveloc.dot(norm)>ZERO)) )
{
normal=norm;
point=OldPos[i]+uveloc*rt;
lamda=rt4;
BallNr=i;
}
}
}
if (TestIntersionPlane(pl4,OldPos[i],uveloc,rt,norm))
{
rt4=rt*RestTime/rt2;
if (rt4<=lamda)
{
if (rt4<=RestTime+ZERO)
if (! ((rt<=ZERO)&&(uveloc.dot(norm)>ZERO)) )
{
normal=norm;
point=OldPos[i]+uveloc*rt;
lamda=rt4;
BallNr=i;
}
}
}
if (TestIntersionPlane(pl5,OldPos[i],uveloc,rt,norm))
{
rt4=rt*RestTime/rt2;
if (rt4<=lamda)
{
if (rt4<=RestTime+ZERO)
if (! ((rt<=ZERO)&&(uveloc.dot(norm)>ZERO)) )
{
normal=norm;
point=OldPos[i]+uveloc*rt;
lamda=rt4;
BallNr=i;
}
}
}
// 测试球与3个圆柱体是否发生碰撞
if (TestIntersionCylinder(cyl1,OldPos[i],uveloc,rt,norm,Nc))
{
rt4=rt*RestTime/rt2;
if (rt4<=lamda)
{
if (rt4<=RestTime+ZERO)
if (! ((rt<=ZERO)&&(uveloc.dot(norm)>ZERO)) )
{
normal=norm;
point=Nc;
lamda=rt4;
BallNr=i;
}
}
}
if (TestIntersionCylinder(cyl2,OldPos[i],uveloc,rt,norm,Nc))
{
rt4=rt*RestTime/rt2;
if (rt4<=lamda)
{
if (rt4<=RestTime+ZERO)
if (! ((rt<=ZERO)&&(uveloc.dot(norm)>ZERO)) )
{
normal=norm;
point=Nc;
lamda=rt4;
BallNr=i;
}
}
}
if (TestIntersionCylinder(cyl3,OldPos[i],uveloc,rt,norm,Nc))
{
rt4=rt*RestTime/rt2;
if (rt4<=lamda)
{
if (rt4<=RestTime+ZERO)
if (! ((rt<=ZERO)&&(uveloc.dot(norm)>ZERO)) )
{
normal=norm;
point=Nc;
lamda=rt4;
BallNr=i;
}
}
}
}
// 检查球之间是否发生碰撞
if (FindBallCol(Pos2,BallTime,RestTime,BallColNr1,BallColNr2))
{
if (sounds)
PlaySound("Data/Explode.wav",NULL,SND_FILENAME|SND_ASYNC);
if ( (lamda==10000) || (lamda>BallTime) )
{
RestTime=RestTime-BallTime;
CVector 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();
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;
// 更新爆炸序列
for(j=0;j<20;j++)
{
if (ExplosionArray[j]._Alpha<=0)
{
ExplosionArray[j]._Alpha=1;
ExplosionArray[j]._Position=ArrayPos[BallColNr1];
ExplosionArray[j]._Scale=1;
break;
}
}
continue;
}
}
if (lamda!=10000)
{
RestTime-=lamda;
for (j=0;j<NrOfBalls;j++)
ArrayPos[j]=OldPos[j]+ArrayVel[j]*lamda;
rt2=ArrayVel[BallNr].mag();
ArrayVel[BallNr].unit();
ArrayVel[BallNr]=CVector::unit( (normal*(2*normal.dot(-ArrayVel[BallNr]))) + ArrayVel[BallNr] );
ArrayVel[BallNr]=ArrayVel[BallNr]*rt2;
for(j=0;j<20;j++)
{
if (ExplosionArray[j]._Alpha<=0)
{
ExplosionArray[j]._Alpha=1;
ExplosionArray[j]._Position=point;
ExplosionArray[j]._Scale=1;
break;
}
}
}
else RestTime=0;
}
}
// 初始化各种变量
void CMyCollision1View::InitVars()
{
//create palnes
pl1._Position=CVector(0,-300,0);
pl1._Normal=CVector(0,1,0);
pl2._Position=CVector(300,0,0);
pl2._Normal=CVector(-1,0,0);
pl3._Position=CVector(-300,0,0);
pl3._Normal=CVector(1,0,0);
pl4._Position=CVector(0,0,300);
pl4._Normal=CVector(0,0,-1);
pl5._Position=CVector(0,0,-300);
pl5._Normal=CVector(0,0,1);
// 创建圆柱体
cyl1._Position=CVector(0,0,0);
cyl1._Axis=CVector(0,1,0);
cyl1._Radius=60+20;
cyl2._Position=CVector(200,-300,0);
cyl2._Axis=CVector(0,0,1);
cyl2._Radius=60+20;
cyl3._Position=CVector(-200,0,0);
cyl3._Axis=CVector(0,1,1);
cyl3._Axis.unit();
cyl3._Radius=30+20;
cylinder_obj= gluNewQuadric();
gluQuadricTexture(cylinder_obj, GL_TRUE);
// 设置球的最初位置和运动速度
NrOfBalls=10;
ArrayVel[0]=veloc;
ArrayPos[0]=CVector(199,180,10);
ExplosionArray[0]._Alpha=0;
ExplosionArray[0]._Scale=1;
ArrayVel[1]=veloc;
ArrayPos[1]=CVector(0,150,100);
ExplosionArray[1]._Alpha=0;
ExplosionArray[1]._Scale=1;
ArrayVel[2]=veloc;
ArrayPos[2]=CVector(-100,180,-100);
ExplosionArray[2]._Alpha=0;
ExplosionArray[2]._Scale=1;
for (int i=3; i<10; i++)
{
ArrayVel[i]=veloc;
ArrayPos[i]=CVector(-500+i*75, 300, -500+i*50);
ExplosionArray[i]._Alpha=0;
ExplosionArray[i]._Scale=1;
}
for (i=10; i<20; i++)
{
ExplosionArray[i]._Alpha=0;
ExplosionArray[i]._Scale=1;
}
}
// 测试直线是否与平面相交函数
int CMyCollision1View::TestIntersionPlane(const Plane& plane,const CVector& position,const CVector& direction, double& lamda, CVector& pNormal)
{
double DotProduct=direction.dot(plane._Normal);
double l2;
// 检查直线是否与平面平行
if ((DotProduct<ZERO)&&(DotProduct>-ZERO))
return 0;
l2=(plane._Normal.dot(plane._Position-position))/DotProduct;
if (l2<-ZERO)
return 0;
pNormal=plane._Normal;
lamda=l2;
return 1;
}
// 测试直线是否与圆柱体相交
int CMyCollision1View::TestIntersionCylinder(const Cylinder& cylinder,const CVector& position,const CVector& direction, double& lamda, CVector& pNormal,CVector& newposition)
{
CVector RC;
double d;
double t,s;
CVector n,D,O;
double ln;
double in,out;
CVector::subtract(position,cylinder._Position,RC);
CVector::cross(direction,cylinder._Axis,n);
ln=n.mag();
if ( (ln<ZERO)&&(ln>-ZERO) ) return 0;
n.unit();
d= fabs( RC.dot(n) );
if (d<=cylinder._Radius)
{
CVector::cross(RC,cylinder._Axis,O);
t= - O.dot(n)/ln;
CVector::cross(n,cylinder._Axis,O);
O.unit();
s= fabs( sqrt(cylinder._Radius*cylinder._Radius - d*d) / direction.dot(O) );
in=t-s;
out=t+s;
if (in<-ZERO){
if (out<-ZERO) return 0;
else lamda=out;
}
else
if (out<-ZERO) {
lamda=in;
}
else
if (in<out) lamda=in;
else lamda=out;
newposition=position+direction*lamda;
CVector HB=newposition-cylinder._Position;
pNormal=HB - cylinder._Axis*(HB.dot(cylinder._Axis));
pNormal.unit();
return 1;
}
return 0;
}
void CMyCollision1View::LoadGLTextures()
{
// 装入纹理
Image *image1, *image2, *image3, *image4;
// 为纹理分配存储空间
image1 = (Image *) malloc(sizeof(Image));
if (image1 == NULL) {
printf("Error allocating space for image");
exit(0);
}
image2 = (Image *) malloc(sizeof(Image));
if (image2 == NULL) {
printf("Error allocating space for image");
exit(0);
}
image3 = (Image *) malloc(sizeof(Image));
if (image3 == NULL) {
printf("Error allocating space for image");
exit(0);
}
image4 = (Image *) malloc(sizeof(Image));
if (image4 == NULL) {
printf("Error allocating space for image");
exit(0);
}
if (!m_MyImage.ImageLoad("data/marble.bmp", image1)) {
exit(1);
}
if (!m_MyImage.ImageLoad("data/spark.bmp", image2)) {
exit(1);
}
if (!m_MyImage.ImageLoad("data/boden.bmp", image3)) {
exit(1);
}
if (!m_MyImage.ImageLoad("data/wand.bmp", image4)) {
exit(1);
}
// 创建纹理
glGenTextures(2, &texture[0]);
glBindTexture(GL_TEXTURE_2D, texture[0]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexImage2D(GL_TEXTURE_2D, 0, 3, image1->sizeX, image1->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, image1->data);
glBindTexture(GL_TEXTURE_2D, texture[1]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexImage2D(GL_TEXTURE_2D, 0, 3, image2->sizeX, image2->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, image2->data);
glGenTextures(2, &texture[2]);
glBindTexture(GL_TEXTURE_2D, texture[2]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexImage2D(GL_TEXTURE_2D, 0, 3, image3->sizeX, image3->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, image3->data);
glBindTexture(GL_TEXTURE_2D, texture[3]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexImage2D(GL_TEXTURE_2D, 0, 3, image4->sizeX, image4->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, image4->data);
free(image1->data);
free(image1);
free(image2->data);
free(image2);
free(image3->data);
free(image3);
free(image4->data);
free(image4);
};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -