📄 cloth.cpp
字号:
#include "Cloth.h"
// Define cloth point mass template GUID
// template ClothMasses {
// <F5AD0F93-9BF2-4bcf-B7CF-D68CD6B54156>
// DWORD NumPoints;
// array FLOAT Mass[NumPoints];
// }
DEFINE_GUID(ClothMasses,
0xf5ad0f93, 0x9bf2, 0x4bcf,
0xb7, 0xcf, 0xd6, 0x8c, 0xd6, 0xb5, 0x41, 0x56);
// Define cloth spring template GUID
// template ClothSprings {
// <8C08B088-728E-46c8-BE87-72672B81DB11>
// DWORD NumSprings;
// DWORD NumVertices; // NumSprings * 2
// array DWORD Vertex[NumVertices];
// }
DEFINE_GUID(ClothSprings,
0x8c08b088, 0x728e, 0x46c8,
0xbe, 0x87, 0x72, 0x67, 0x2b, 0x81, 0xdb, 0x11);
//////////////////////////////////////////////////////////////
// cClothMesh class functions
//////////////////////////////////////////////////////////////
cClothMesh::cClothMesh()
{
// Clear all class data
m_NumPoints = 0;
m_Points = NULL;
m_NumSprings = 0;
m_Springs = NULL;
m_NumFaces = 0;
m_Faces = NULL;
m_VertexStride = 0;
}
cClothMesh::~cClothMesh()
{
Free();
}
BOOL cClothMesh::ParseObject(IDirectXFileData *pDataObj,
IDirectXFileData *pParentDataObj,
DWORD Depth,
void **Data, BOOL Reference)
{
const GUID *Type = GetObjectGUID(pDataObj);
char *Name = GetObjectName(pDataObj);
DWORD Size;
DWORD *DataPtr = (DWORD*)GetObjectData(pDataObj, &Size);
float *MassPtr;
// Read in cloth point masses - apply to current mesh
if(*Type == ClothMasses && m_NumPoints && m_Points) {
// Get number of assignments to follow
// and make sure it matches # of points in cloth
DWORD NumPoints = *DataPtr++;
if(NumPoints == m_NumPoints) {
// Copy over mass values
MassPtr = (float*)DataPtr;
for(DWORD i=0;i<NumPoints;i++)
SetMass(i, *MassPtr++);
}
}
// If springs exist, wipe out current ones and add new ones
if(*Type == ClothSprings) {
// Clear current springs
delete m_Springs;
m_Springs = NULL;
m_NumSprings = 0;
// Get new number of springs and vertices
DWORD NumSprings = *DataPtr++;
DWORD NumVertices = *DataPtr++;
// Load each spring
for(DWORD i=0;i<NumSprings;i++) {
DWORD Vertex1 = *DataPtr++;
DWORD Vertex2 = *DataPtr++;
AddSpring(Vertex1, Vertex2);
}
}
return ParseChildObjects(pDataObj, Depth, Data, Reference);
}
void cClothMesh::SetForces(float LinearDamping,
D3DXVECTOR3 *vecGravity,
D3DXVECTOR3 *vecWind,
D3DXMATRIX *matTransform,
BOOL TransformAllPoints)
{
DWORD i;
// Error checking
if(!m_NumPoints || m_Points == NULL)
return;
// Clear forces, apply transformation, set gravity, and apply linear damping
for(i=0;i<m_NumPoints;i++) {
// Clear force
m_Points[i].m_vecForce = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
// Move point using transformation if specified
if(matTransform && (TransformAllPoints == TRUE || m_Points[i].m_Mass == 0.0f)) {
D3DXVec3TransformCoord(&m_Points[i].m_vecPos, &m_Points[i].m_vecOriginalPos, matTransform);
}
// Only apply gravity and linear damping to points w/mass
if(m_Points[i].m_Mass != 0.0f) {
// Apply gravity if specified
if(vecGravity != NULL)
m_Points[i].m_vecForce += (*vecGravity) * m_Points[i].m_Mass;
// Apply linear damping
m_Points[i].m_vecForce += (m_Points[i].m_vecVelocity * LinearDamping);
}
}
// Apply wind
if(vecWind != NULL && m_NumFaces) {
// Go through each face and apply wind vector to
// vertex on all faces
for(i=0;i<m_NumFaces;i++) {
// Get three vertices that construct face
DWORD Vertex1 = m_Faces[i*3];
DWORD Vertex2 = m_Faces[i*3+1];
DWORD Vertex3 = m_Faces[i*3+2];
// Calculate face's normal
D3DXVECTOR3 vecV12 = m_Points[Vertex2].m_vecPos - m_Points[Vertex1].m_vecPos;
D3DXVECTOR3 vecV13 = m_Points[Vertex3].m_vecPos - m_Points[Vertex1].m_vecPos;
D3DXVECTOR3 vecNormal;
D3DXVec3Cross(&vecNormal, &vecV12, &vecV13);
D3DXVec3Normalize(&vecNormal, &vecNormal);
// Get dot product between normal and wind
float Dot = D3DXVec3Dot(&vecNormal, vecWind);
// Amplify normal by dot product
vecNormal *= Dot;
// Apply normal to point's force vector
m_Points[Vertex1].m_vecForce += vecNormal;
m_Points[Vertex2].m_vecForce += vecNormal;
m_Points[Vertex3].m_vecForce += vecNormal;
}
}
// Process springs
cClothSpring *Spring = m_Springs;
while(Spring) {
// Get the current spring vector
D3DXVECTOR3 vecSpring = m_Points[Spring->m_Point2].m_vecPos -
m_Points[Spring->m_Point1].m_vecPos;
// Get the current length of the spring
float SpringLength = D3DXVec3Length(&vecSpring);
// Get the relative velocity of the points
D3DXVECTOR3 vecVelocity = m_Points[Spring->m_Point2].m_vecVelocity -
m_Points[Spring->m_Point1].m_vecVelocity;
float Velocity = D3DXVec3Dot(&vecVelocity, &vecSpring) / SpringLength;
// Calculate forces
float SpringForce = Spring->m_Ks * (SpringLength - Spring->m_RestingLength);
float DampingForce = Spring->m_Kd * Velocity;
// Normalize the spring
vecSpring /= SpringLength;
// Calculate force vector
D3DXVECTOR3 vecForce = (SpringForce + DampingForce) * vecSpring;
// Apply force to vectors
if(m_Points[Spring->m_Point1].m_Mass != 0.0f)
m_Points[Spring->m_Point1].m_vecForce += vecForce;
if(m_Points[Spring->m_Point2].m_Mass != 0.0f)
m_Points[Spring->m_Point2].m_vecForce -= vecForce;
// Go to next spring
Spring = Spring->m_Next;
}
}
void cClothMesh::ProcessForces(float Elapsed)
{
// Error checking
if(!m_NumPoints || !m_Points)
return;
// Resolve forces on points
for(DWORD i=0;i<m_NumPoints;i++) {
// Points w/0 mass don't move
if(m_Points[i].m_Mass != 0.0f) {
// Update velocity
m_Points[i].m_vecVelocity += (m_Points[i].m_OneOverMass * Elapsed * m_Points[i].m_vecForce);
// Update position
m_Points[i].m_vecPos += (Elapsed * m_Points[i].m_vecVelocity);
}
}
}
void cClothMesh::ProcessCollisions(cCollision *pCollision,
D3DXMATRIX *matTransform)
{
D3DXMATRIX matITTransform;
BOOL MatrixInversedAndTransposed = FALSE;
// Error checking
if(!pCollision || !pCollision->m_NumObjects || !pCollision->m_Objects)
return;
// Go through all points
for(DWORD i=0;i<m_NumPoints;i++) {
// Don't process points w/0 mass
if(m_Points[i].m_Mass != 0.0f) {
// Go through each collision object
cCollisionObject *pObject = pCollision->m_Objects;
while(pObject) {
// Check if point collides with a sphere object
if(pObject->m_Type == COLLISION_SPHERE) {
// Put sphere coordinates into local vector
D3DXVECTOR3 vecSphere = pObject->m_vecPos;
// Translate sphere by transformation
if(matTransform) {
vecSphere.x += matTransform->_41; // Translate x
vecSphere.y += matTransform->_42; // Translate y
vecSphere.z += matTransform->_43; // Translate z
}
// Calculate a distance vector
D3DXVECTOR3 vecDist = vecSphere - m_Points[i].m_vecPos;
// Get the squared length of the difference
float Length = vecDist.x * vecDist.x + \
vecDist.y * vecDist.y + \
vecDist.z * vecDist.z;
// If the length of the difference less than radius?
if(Length <= (pObject->m_Radius*pObject->m_Radius)) {
// Collision occurred!
// Normalize the distance vector
Length = (float)sqrt(Length);
vecDist /= Length;
// Calculate the difference in distance from the
// point to the sphere's edge
float Diff = pObject->m_Radius - Length;
// Scale the vector by difference
vecDist *= Diff;
// Push the point out and adjust velocity
m_Points[i].m_vecPos -= vecDist;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -