?? clothsim.java
字號:
{
normals[((xTotal-1)*2*(yTotal-2)+2*(i-1))*3*3+12]= normalsAverage.x;
normals[((xTotal-1)*2*(yTotal-2)+2*(i-1))*3*3+13]=normalsAverage.y;
normals[((xTotal-1)*2*(yTotal-2)+2*(i-1))*3*3+14]=normalsAverage.z;
}
}
}//優化三角面頂點法向量,以使得三角面平滑過渡
//頂點法向量坐標求平均值
public float NormalsAverage(float nromalsa,float normalsCout)
{
float normalsb=0.0f;
normalsb=nromalsa/normalsCout;
return normalsb;
}
//頂點法向量坐標相加
public float NormalsAdd(float nromals1,float normals2)
{
float normalsb=0.0f;
normalsb= nromals1+normals2;
return normalsb;
}
}
///////////////////////////////////////////////////////////
// 物理模型Physics內部類 //
// //
// 創建一個質點位置更新模型,根據當前質點的位置, //
// 計算質點的內力,外力,然后利用簡單的歐拉公式 //
// 計算質點的加速度,速度,質點的位移,計算下個 //
// 時間點的位置 //
// //
// //
///////////////////////////////////////////////////////////
//物理模型內部類
class Physics
{
//根據內部彈簧位移計算內力,并結合風力,空氣阻力計算質點的總受力
public void calculateF(Point3d pointPosition1[][],Vector3d vectorF1[][],Vector3d vector3dV1[][])
{
for(int i=0;i<xTotal;i++)
for(int j=0;j<yTotal;j++)
{
vectorF1[i][j]=add(new Vector3d(0.0,0.0,0.0),new Vector3d(0.0,0.0,0.0));
//初始化質點力矢量為零矢量
if(j<(yTotal-1))vectorF1[i][j]=add(vectorF1[i][j],neighborF(pointPosition1[i][j],pointPosition1[i][j+1],lstretch));
if(j>0)vectorF1[i][j]=add(vectorF1[i][j],neighborF(pointPosition1[i][j],pointPosition1[i][j-1],lstretch));
if(i!=(xTotal-1))vectorF1[i][j]=add(vectorF1[i][j],neighborF(pointPosition1[i][j],pointPosition1[i+1][j],lstretch));
if(i!=0)vectorF1[i][j]=add(vectorF1[i][j],neighborF(pointPosition1[i][j],pointPosition1[i-1][j],lstretch));
//計算質點由于結構彈簧所受的力
if(i!=(xTotal-1)&j!=0)vectorF1[i][j]=add(vectorF1[i][j],neighborF(pointPosition1[i][j],pointPosition1[i+1][j-1],lshear));
if(i!=(xTotal-1)&j!=(yTotal-1))vectorF1[i][j]=add(vectorF1[i][j],neighborF(pointPosition1[i][j],pointPosition1[i+1][j+1],lshear));
if(i!=0&j!=0)vectorF1[i][j]=add(vectorF1[i][j],neighborF(pointPosition1[i][j],pointPosition1[i-1][j-1],lshear));
if(i!=0&j!=(yTotal-1))vectorF1[i][j]=add(vectorF1[i][j],neighborF(pointPosition1[i][j],pointPosition1[i-1][j+1],lshear));
//計算質點由于剪切彈簧所受的力
if(i>1)vectorF1[i][j]=add(vectorF1[i][j],neighborF(pointPosition1[i][j],pointPosition1[i-2][j],lbend));
if(i<(xTotal-2))vectorF1[i][j]=add(vectorF1[i][j],neighborF(pointPosition1[i][j],pointPosition1[i+2][j],lbend));
if(j>1)vectorF1[i][j]=add(vectorF1[i][j],neighborF(pointPosition1[i][j],pointPosition1[i][j-2],lbend));
if(j<(yTotal-2))vectorF1[i][j]=add(vectorF1[i][j],neighborF(pointPosition1[i][j],pointPosition1[i][j+2],lbend));
//計算質點由于彎曲彈簧所受的力
vectorF1[i][j]=add(vectorF1[i][j],new Vector3d(0.0,-mg,0.0));
//計算重力
Vector3d vectorF1wind=new Vector3d(Fwindx*(1.0-Math.random()*0.8),-0.1*Math.random(),Fwindz*(1.0-Math.random()*0.8));
vectorF1[i][j]=add(vectorF1[i][j],vectorF1wind);
Vector3d vectorFwind=new Vector3d(500.0,0.0,-250.0);
Vector3d a=new Vector3d(vectorFwind.x-vector3dV1[i][j].x,vectorFwind.y-vector3dV1[i][j].y,vectorFwind.z-vector3dV1[i][j].z);
Vector3d b=new Vector3d(0.0,0.0,0.0);
b=pointNormal[i][j];
if(b.length()!=0)
b.normalize() ;
b.dot(a);
vectorFwind.x=-kvi*b.length()*pointNormal[i][j].x;
vectorFwind.y=-kvi*b.length()*pointNormal[i][j].y;
vectorFwind.z=-kvi*b.length()*pointNormal[i][j].z;
//vectorF1[i][j]=add(vectorF1[i][j],vectorFwind);
//計算風力
Vector3d vectorF1air=new Vector3d(vector3dV1[i][j]);
if(vector3dV1[i][j].length()!=0.0)
vectorF1air.normalize();
vectorF1air.x=-kair*vector3dV1[i][j].length()*vector3dV1[i][j].length()*vectorF1air.x;
vectorF1air.y=-kair*vector3dV1[i][j].length()*vector3dV1[i][j].length()*vectorF1air.y;
vectorF1air.z=-kair*vector3dV1[i][j].length()*vector3dV1[i][j].length()*vectorF1air.z;
vectorF1[i][j]=add(vectorF1[i][j],vectorF1air);
//計算空氣阻力
vectorF1[i][j].x=vectorF1[i][j].x/m;
vectorF1[i][j].y=vectorF1[i][j].y/m;
vectorF1[i][j].z=vectorF1[i][j].z/m;
//計算質點加速度
}
}
//矢量相加函數
public Vector3d add(Vector3d vector1,Vector3d vector2)
{
Vector3d vector3d0=new Vector3d();
vector3d0.x=(vector1.x+vector2.x);
vector3d0.y=(vector1.y+vector2.y);
vector3d0.z=(vector1.z+vector2.z);
return vector3d0;
}
// 根據質點加速度,計算質點速度
public void calculateV(Vector3d vector3dV1[][])
{
for(int i=0;i<xTotal;i++)
for(int j=0;j<yTotal;j++)
{
if(i==0&downFlage==false)
{
}
else
{
if(((pointPosition[i][j].x<50.0&pointPosition[i][j].x>-50))&(pointPosition[i][j].z<50&pointPosition[i][j].z>-50)&pointPosition[i][j].y<-0.990)
{vector3dV1[i][j].x=vector3dV[i][j].x+vectorF[i][j].x*t/2;
vector3dV1[i][j].y=0.0;
vector3dV1[i][j].z=vector3dV[i][j].z+vectorF[i][j].z*t/2;
}
else if(pointPosition[i][j].x>-0.015&pointPosition[i][j].x<0.015&pointPosition[i][j].y>-0.990)
{
vector3dV1[i][j].x=0.1;
vector3dV1[i][j].y=vector3dV[i][j].y+vectorF[i][j].y*t/2;
vector3dV1[i][j].z=0.0;
}
else
vector3dV1[i][j]=add(vector3dV[i][j],new Vector3d(vectorF[i][j].x*t/2,vectorF[i][j].y*t/2,vectorF[i][j].z*t/2));
}
}
}
//根據質點速度計算質點的位移
public void calculatePosition(Point3d pointPosition1[][],Vector3d vector3dV1[][])
{
for(int i=0;i<xTotal;i++)
for(int j=0;j<yTotal;j++)
{
pointPosition1[i][j].x=pointPosition[i][j].x+vector3dV1[i][j].x*t;
pointPosition1[i][j].y=pointPosition[i][j].y+vector3dV1[i][j].y*t;
pointPosition1[i][j].z=pointPosition[i][j].z+vector3dV1[i][j].z*t;
}
}
//根據兩質點間的距離,由虎克定律計算質點間的受力
public Vector3d neighborF(Point3d point2,Point3d point1,double constanlength)
{
Vector3d vector3d=new Vector3d(point1.x-point2.x,point1.y-point2.y,point1.z-point2.z);
Vector3d vector3dBack=new Vector3d(vector3d);
vector3d.normalize();
Vector3d vector3dF=new Vector3d(k*(vector3dBack.length()-constanlength)*vector3d.x,k*(vector3dBack.length()-constanlength)*vector3d.y,k*(vector3dBack.length()-constanlength)*vector3d.z);
return vector3dF;
}
//計算兩個向量的平均值
public void VecotorAverage(Vector3d v1[][],Vector3d v2[][])
{
for(int i=0;i<xTotal;i++)
for(int j=0;j<yTotal;j++)
{
v1[i][j].x=(v1[i][j].x+v2[i][j].x)/2;
v1[i][j].y=(v1[i][j].y+v2[i][j].y)/2;
v1[i][j].z=(v1[i][j].z+v2[i][j].z)/2;
}
}
//利用簡單歐拉公式和改進歐拉公式混合計算刷新質點位置
public void oulaCalculate()
{if(ouLaFlage%3!=2)
{ calculateF(pointPosition,vectorF,vector3dV);
calculateV(vector3dV);
calculatePosition(pointPosition,vector3dV);//利用簡單歐拉公式刷新計算質點位置
ouLaFlage++;
if(ouLaFlage==3)ouLaFlage=0;
}
else
{ calculateF(pointPosition,vectorF,vector3dV);
calculateV(vectorVBack);
calculatePosition(pointPositionBack,vectorVBack);
calculateF(pointPositionBack,vectorABack,vectorVBack);
VecotorAverage(vectorF,vectorABack);
calculateV(vector3dV);
calculatePosition(pointPosition,vector3dV);//利用改進歐拉公式刷新計算質點位置
ouLaFlage++;
if(ouLaFlage==3)ouLaFlage=0;}
}
//物理類構造函數
public Physics()
{
}
}
/////////////////////////////////////////////////////////////
// clothSim鍵盤響應內部類 //
// //
// 響應鍵盤的輸入,調整風速,改變面模型形式 //
// //
// //
/////////////////////////////////////////////////////////////
// 鍵盤響應行為類
public class ClothSimBehavior extends Behavior{
// 構造函數
ClothSimBehavior()
{
}
// initialize 方法
public void initialize()
{
this.wakeupOn(new WakeupOnAWTEvent(KeyEvent.KEY_PRESSED));
//設置喚醒條件為有鍵按下
}
// processStimulus方法
public void processStimulus(Enumeration criteria)
{
WakeupCriterion wakeup = null;
AWTEvent[] event = null;
// 對獲得的事件進行解析,并作出響應的反應
wakeup = (WakeupCriterion)criteria.nextElement( );
// 獲得當前的喚醒條件
if ( wakeup instanceof WakeupOnAWTEvent )
{
event = ((WakeupOnAWTEvent)wakeup).getAWTEvent( );
// 獲得當前的喚醒事件
KeyEvent keyevent = (KeyEvent)event[0];
// 轉化為鍵盤事件
// 判斷是否為0鍵,并做相應參數變化
if(keyevent.getKeyCode()==KeyEvent.VK_0)
{
k=500.0;//彈性模量常數
kair=0.5;//空氣阻力常數
kvi=0.25;//空氣流參數
Fwindx=0.0;
Fwindz=0.0;
tWait=2;}
if(keyevent.getKeyCode()==KeyEvent.VK_1)
{
k=500.0;//彈性模量常數
kair=0.018;//空氣阻力常數
kvi=0.25;//空氣流參數
Fwindx=0.65;
Fwindz=-0.45;
tWait=2;}
if(keyevent.getKeyCode()==KeyEvent.VK_2)
{
k=500.0;//彈性模量常數
kair=0.018;//空氣阻力常數
kvi=0.25;//空氣流參數
Fwindx=2.5;
Fwindz=-1.5;
tWait=2;}
if(keyevent.getKeyCode()==KeyEvent.VK_3)
{
k=1500.0;//彈性模量常數
kair=0.0025;//空氣阻力常數
kvi=0.25;//空氣流參數
Fwindx=10.0;
Fwindz=-7.5;
tWait=3; }
if(keyevent.getKeyCode()==KeyEvent.VK_ENTER)
{
if(clothSimFaceType==1)
{s.setWhichChild(1);//顯示線模型
sPoint.setWhichChild(0);//顯示質點模型
tWait=0;//設置刷新線程刷新等待時間
clothSimFaceType--;
}
else
{s.setWhichChild(0);//顯示面模型
sPoint.setWhichChild(Switch.CHILD_NONE);//不顯示質點球模型
tWait=0;//設置刷新線程刷新等待時間
clothSimFaceType++;
}
}
if(keyevent.getKeyCode()==KeyEvent.VK_S)
{if(timerFlagevcout==0)
{timerFlage=false;
timerFlagevcout++;}
else
{
timerFlage=true;
timerFlagevcout--; }//刷新線程暫停
}
if(keyevent.getKeyCode()==KeyEvent.VK_D)
{
downFlage=true;
}
}
this.wakeupOn(new WakeupOnAWTEvent(KeyEvent.KEY_PRESSED));// 設置下一次的喚醒條件
}
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -