📄 physenv.cpp
字号:
if (m_ParticleSys[1])
{
free(m_ParticleSys[1]);
m_ParticleSys[1] = NULL;
}
if (m_ParticleSys[2])
{
free(m_ParticleSys[2]);
m_ParticleSys[2] = NULL; // RESET BUFFER
}
for (int i = 0; i < 5; i++)
{
if (m_TempSys[i])
{
free(m_TempSys[i]);
m_TempSys[i] = NULL; // RESET BUFFER
}
}
if (m_Contact)
{
free(m_Contact);
m_Contact = NULL;
}
if (m_Spring)
{
free(m_Spring);
m_Spring = NULL;
}
m_SpringCnt = 0;
m_ParticleCnt = 0;
}
////// FreeSystem //////////////////////////////////////////////////////////////
void CPhysEnv::LoadData(FILE *fp)
{
fread(&m_UseGravity,sizeof(BOOL),1,fp);
fread(&m_UseDamping,sizeof(BOOL),1,fp);
fread(&m_UserForceActive,sizeof(BOOL),1,fp);
fread(&m_Gravity,sizeof(tVector),1,fp);
fread(&m_UserForce,sizeof(tVector),1,fp);
fread(&m_UserForceMag,sizeof(float),1,fp);
fread(&m_Kd,sizeof(float),1,fp);
fread(&m_Kr,sizeof(float),1,fp);
fread(&m_Ksh,sizeof(float),1,fp);
fread(&m_Ksd,sizeof(float),1,fp);
fread(&m_ParticleCnt,sizeof(int),1,fp);
m_CurrentSys = (tParticle *)malloc(sizeof(tParticle) * m_ParticleCnt);
m_TargetSys = (tParticle *)malloc(sizeof(tParticle) * m_ParticleCnt);
m_ParticleSys[2] = (tParticle *)malloc(sizeof(tParticle) * m_ParticleCnt);
for (int i = 0; i < 5; i++)
{
m_TempSys[i] = (tParticle *)malloc(sizeof(tParticle) * m_ParticleCnt);
}
m_ParticleSys[0] = m_CurrentSys;
m_ParticleSys[1] = m_TargetSys;
m_Contact = (tContact *)malloc(sizeof(tContact) * m_ParticleCnt);
fread(m_ParticleSys[0],sizeof(tParticle),m_ParticleCnt,fp);
fread(m_ParticleSys[1],sizeof(tParticle),m_ParticleCnt,fp);
fread(m_ParticleSys[2],sizeof(tParticle),m_ParticleCnt,fp);
fread(&m_SpringCnt,sizeof(int),1,fp);
m_Spring = (tSpring *)malloc(sizeof(tSpring) * (m_SpringCnt));
fread(m_Spring,sizeof(tSpring),m_SpringCnt,fp);
fread(m_Pick,sizeof(int),2,fp);
fread(&m_SphereCnt,sizeof(int),1,fp);
m_Sphere = (tCollisionSphere *)malloc(sizeof(tCollisionSphere) * (m_SphereCnt));
fread(m_Sphere,sizeof(tCollisionSphere),m_SphereCnt,fp);
}
void CPhysEnv::SaveData(FILE *fp)
{
fwrite(&m_UseGravity,sizeof(BOOL),1,fp);
fwrite(&m_UseDamping,sizeof(BOOL),1,fp);
fwrite(&m_UserForceActive,sizeof(BOOL),1,fp);
fwrite(&m_Gravity,sizeof(tVector),1,fp);
fwrite(&m_UserForce,sizeof(tVector),1,fp);
fwrite(&m_UserForceMag,sizeof(float),1,fp);
fwrite(&m_Kd,sizeof(float),1,fp);
fwrite(&m_Kr,sizeof(float),1,fp);
fwrite(&m_Ksh,sizeof(float),1,fp);
fwrite(&m_Ksd,sizeof(float),1,fp);
fwrite(&m_ParticleCnt,sizeof(int),1,fp);
fwrite(m_ParticleSys[0],sizeof(tParticle),m_ParticleCnt,fp);
fwrite(m_ParticleSys[1],sizeof(tParticle),m_ParticleCnt,fp);
fwrite(m_ParticleSys[2],sizeof(tParticle),m_ParticleCnt,fp);
fwrite(&m_SpringCnt,sizeof(int),1,fp);
fwrite(m_Spring,sizeof(tSpring),m_SpringCnt,fp);
fwrite(m_Pick,sizeof(int),2,fp);
fwrite(&m_SphereCnt,sizeof(int),1,fp);
fwrite(m_Sphere,sizeof(tCollisionSphere),m_SphereCnt,fp);
}
// RESET THE SIM TO INITIAL VALUES
void CPhysEnv::ResetWorld()
{
memcpy(m_CurrentSys,m_ParticleSys[2],sizeof(tParticle) * m_ParticleCnt);
memcpy(m_TargetSys,m_ParticleSys[2],sizeof(tParticle) * m_ParticleCnt);
}
void CPhysEnv::SetWorldProperties()
{
CDlgSimProp dialog;
dialog.m_CoefRest = m_Kr;
dialog.m_Damping = m_Kd;
dialog.m_GravX = m_Gravity.x;
dialog.m_GravY = m_Gravity.y;
dialog.m_GravZ = m_Gravity.z;
dialog.m_SpringConst = m_Ksh;
dialog.m_SpringDamp = m_Ksd;
dialog.m_UserForceMag = m_UserForceMag;
if (dialog.DoModal() == IDOK)
{
m_Kr = dialog.m_CoefRest;
m_Kd = dialog.m_Damping;
m_Gravity.x = dialog.m_GravX;
m_Gravity.y = dialog.m_GravY;
m_Gravity.z = dialog.m_GravZ;
m_UserForceMag = dialog.m_UserForceMag;
m_Ksh = dialog.m_SpringConst;
m_Ksd = dialog.m_SpringDamp;
for (int loop = 0; loop < m_SpringCnt; loop++)
{
m_Spring[loop].Ks = m_Ksh;
m_Spring[loop].Kd = m_Ksd;
}
}
}
void CPhysEnv::SetVertexProperties()
{
CDlgVertexMass dialog;
dialog.m_VertexMass = m_CurrentSys[m_Pick[0]].oneOverM;
if (dialog.DoModal() == IDOK)
{
m_ParticleSys[0][m_Pick[0]].oneOverM = dialog.m_VertexMass;
m_ParticleSys[0][m_Pick[1]].oneOverM = dialog.m_VertexMass;
m_ParticleSys[1][m_Pick[0]].oneOverM = dialog.m_VertexMass;
m_ParticleSys[1][m_Pick[1]].oneOverM = dialog.m_VertexMass;
m_ParticleSys[2][m_Pick[0]].oneOverM = dialog.m_VertexMass;
m_ParticleSys[2][m_Pick[1]].oneOverM = dialog.m_VertexMass;
}
}
void CPhysEnv::ApplyUserForce(tVector *force)
{
ScaleVector(force, m_UserForceMag, &m_UserForce);
m_UserForceActive = TRUE;
}
///////////////////////////////////////////////////////////////////////////////
// Function: SetMouseForce
// Purpose: Allows the user to interact with selected points by dragging
// Arguments: Delta distance from clicked point, local x and y axes
///////////////////////////////////////////////////////////////////////////////
void CPhysEnv::SetMouseForce(int deltaX,int deltaY, tVector *localX, tVector *localY)
{
/// Local Variables ///////////////////////////////////////////////////////////
tVector tempX,tempY;
///////////////////////////////////////////////////////////////////////////////
ScaleVector(localX, (float)deltaX * 0.03f, &tempX);
ScaleVector(localY, -(float)deltaY * 0.03f, &tempY);
if (m_Pick[0] > -1)
{
VectorSum(&m_CurrentSys[m_Pick[0]].pos,&tempX,&m_MouseDragPos[0]);
VectorSum(&m_MouseDragPos[0],&tempY,&m_MouseDragPos[0]);
}
if (m_Pick[1] > -1)
{
VectorSum(&m_CurrentSys[m_Pick[1]].pos,&tempX,&m_MouseDragPos[1]);
VectorSum(&m_MouseDragPos[1],&tempY,&m_MouseDragPos[1]);
}
}
/// SetMouseForce /////////////////////////////////////////////////////////////
void CPhysEnv::AddSpring()
{
tSpring *spring;
// MAKE SURE TWO PARTICLES ARE PICKED
if (m_Pick[0] > -1 && m_Pick[1] > -1)
{
spring = (tSpring *)malloc(sizeof(tSpring) * (m_SpringCnt + 1));
if (m_Spring != NULL)
memcpy(spring,m_Spring,sizeof(tSpring) * m_SpringCnt);
m_Spring = spring;
spring = &m_Spring[m_SpringCnt++];
spring->Ks = m_Ksh;
spring->Kd = m_Ksd;
spring->p1 = m_Pick[0];
spring->p2 = m_Pick[1];
spring->restLen =
sqrt(VectorSquaredDistance(&m_CurrentSys[m_Pick[0]].pos,
&m_CurrentSys[m_Pick[1]].pos));
spring->type = MANUAL_SPRING;
}
}
void CPhysEnv::AddSpring(int v1, int v2,float Ksh,float Ksd, int type)
{
tSpring *spring;
// MAKE SURE TWO PARTICLES ARE PICKED
if (v1 > -1 && v2 > -1)
{
spring = (tSpring *)malloc(sizeof(tSpring) * (m_SpringCnt + 1));
if (m_Spring != NULL)
{
memcpy(spring,m_Spring,sizeof(tSpring) * m_SpringCnt);
free(m_Spring);
}
m_Spring = spring;
spring = &m_Spring[m_SpringCnt++];
spring->type = type;
spring->Ks = Ksh;
spring->Kd = Ksd;
spring->p1 = v1;
spring->p2 = v2;
spring->restLen =
sqrt(VectorSquaredDistance(&m_CurrentSys[v1].pos,
&m_CurrentSys[v2].pos));
}
}
void CPhysEnv::ComputeForces( tParticle *system )
{
int loop;
tParticle *curParticle,*p1, *p2;
tSpring *spring;
float dist, Hterm, Dterm;
tVector springForce,deltaV,deltaP;
curParticle = system;
for (loop = 0; loop < m_ParticleCnt; loop++)
{
MAKEVECTOR(curParticle->f,0.0f,0.0f,0.0f) // CLEAR FORCE VECTOR
if (m_UseGravity && curParticle->oneOverM != 0)
{
curParticle->f.x += (m_Gravity.x / curParticle->oneOverM);
curParticle->f.y += (m_Gravity.y / curParticle->oneOverM);
curParticle->f.z += (m_Gravity.z / curParticle->oneOverM);
}
if (m_UseDamping)
{
curParticle->f.x += (-m_Kd * curParticle->v.x);
curParticle->f.y += (-m_Kd * curParticle->v.y);
curParticle->f.z += (-m_Kd * curParticle->v.z);
}
else
{
curParticle->f.x += (-DEFAULT_DAMPING * curParticle->v.x);
curParticle->f.y += (-DEFAULT_DAMPING * curParticle->v.y);
curParticle->f.z += (-DEFAULT_DAMPING * curParticle->v.z);
}
curParticle++;
}
// CHECK IF THERE IS A USER FORCE BEING APPLIED
if (m_UserForceActive)
{
if (m_Pick[0] != -1)
{
VectorSum(&system[m_Pick[0]].f,&m_UserForce,&system[m_Pick[0]].f);
}
if (m_Pick[1] != -1)
{
VectorSum(&system[m_Pick[1]].f,&m_UserForce,&system[m_Pick[1]].f);
}
MAKEVECTOR(m_UserForce,0.0f,0.0f,0.0f); // CLEAR USER FORCE
}
// NOW DO ALL THE SPRINGS
spring = m_Spring;
for (loop = 0; loop < m_SpringCnt; loop++)
{
p1 = &system[spring->p1];
p2 = &system[spring->p2];
VectorDifference(&p1->pos,&p2->pos,&deltaP); // Vector distance
dist = VectorLength(&deltaP); // Magnitude of deltaP
Hterm = (dist - spring->restLen) * spring->Ks; // Ks * (dist - rest)
VectorDifference(&p1->v,&p2->v,&deltaV); // Delta Velocity Vector
Dterm = (DotProduct(&deltaV,&deltaP) * spring->Kd) / dist; // Damping Term
ScaleVector(&deltaP,1.0f / dist, &springForce); // Normalize Distance Vector
ScaleVector(&springForce,-(Hterm + Dterm),&springForce); // Calc Force
VectorSum(&p1->f,&springForce,&p1->f); // Apply to Particle 1
VectorDifference(&p2->f,&springForce,&p2->f); // - Force on Particle 2
spring++; // DO THE NEXT SPRING
}
// APPLY THE MOUSE DRAG FORCES IF THEY ARE ACTIVE
if (m_MouseForceActive)
{
// APPLY TO EACH PICKED PARTICLE
if (m_Pick[0] > -1)
{
p1 = &system[m_Pick[0]];
VectorDifference(&p1->pos,&m_MouseDragPos[0],&deltaP); // Vector distance
dist = VectorLength(&deltaP); // Magnitude of deltaP
if (dist != 0.0f)
{
Hterm = (dist) * m_MouseForceKs; // Ks * dist
ScaleVector(&deltaP,1.0f / dist, &springForce); // Normalize Distance Vector
ScaleVector(&springForce,-(Hterm),&springForce); // Calc Force
VectorSum(&p1->f,&springForce,&p1->f); // Apply to Particle 1
}
}
if (m_Pick[1] > -1)
{
p1 = &system[m_Pick[1]];
VectorDifference(&p1->pos,&m_MouseDragPos[1],&deltaP); // Vector distance
dist = VectorLength(&deltaP); // Magnitude of deltaP
if (dist != 0.0f)
{
Hterm = (dist) * m_MouseForceKs; // Ks * dist
ScaleVector(&deltaP,1.0f / dist, &springForce); // Normalize Distance Vector
ScaleVector(&springForce,-(Hterm),&springForce); // Calc Force
VectorSum(&p1->f,&springForce,&p1->f); // Apply to Particle 1
}
}
}
}
///////////////////////////////////////////////////////////////////////////////
// Function: IntegrateSysOverTime
// Purpose: Does the Integration for all the points in a system
// Arguments: Initial Position, Source and Target Particle Systems and Time
// Notes: Computes a single integration step
///////////////////////////////////////////////////////////////////////////////
void CPhysEnv::IntegrateSysOverTime(tParticle *initial,tParticle *source, tParticle *target, float deltaTime)
{
/// Local Variables ///////////////////////////////////////////////////////////
int loop;
float deltaTimeMass;
///////////////////////////////////////////////////////////////////////////////
for (loop = 0; loop < m_ParticleCnt; loop++)
{
deltaTimeMass = deltaTime * initial->oneOverM;
// DETERMINE THE NEW VELOCITY FOR THE PARTICLE
target->v.x = initial->v.x + (source->f.x * deltaTimeMass);
target->v.y = initial->v.y + (source->f.y * deltaTimeMass);
target->v.z = initial->v.z + (source->f.z * deltaTimeMass);
target->oneOverM = initial->oneOverM;
// SET THE NEW POSITION
target->pos.x = initial->pos.x + (deltaTime * source->v.x);
target->pos.y = initial->pos.y + (deltaTime * source->v.y);
target->pos.z = initial->pos.z + (deltaTime * source->v.z);
initial++;
source++;
target++;
}
}
///////////////////////////////////////////////////////////////////////////////
// Function: EulerIntegrate
// Purpose: Calculate new Positions and Velocities given a deltatime
// Arguments: DeltaTime that has passed since last iteration
// Notes: This integrator uses Euler's method
///////////////////////////////////////////////////////////////////////////////
void CPhysEnv::EulerIntegrate( float DeltaTime)
{
// JUST TAKE A SINGLE STEP
IntegrateSysOverTime(m_CurrentSys,m_CurrentSys, m_TargetSys,DeltaTime);
}
///////////////////////////////////////////////////////////////////////////////
// Function: MidPointIntegrate
// Purpose: Calculate new Positions and Velocities given a deltatime
// Arguments: DeltaTime that has passed since last iteration
// Notes: This integrator uses the Midpoint method
///////////////////////////////////////////////////////////////////////////////
void CPhysEnv::MidPointIntegrate( float DeltaTime)
{
/// Local Variables ///////////////////////////////////////////////////////////
float halfDeltaT;
///////////////////////////////////////////////////////////////////////////////
halfDeltaT = DeltaTime / 2.0f;
// TAKE A HALF STEP AND UPDATE VELOCITY AND POSITION
IntegrateSysOverTime(m_CurrentSys,m_CurrentSys,m_TempSys[0],halfDeltaT);
// COMPUTE FORCES USING THESE NEW POSITIONS AND VELOCITIES
ComputeForces(m_TempSys[0]);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -