📄 cloth.cpp
字号:
m_Points[i].m_vecVelocity -= vecDist;
}
}
// Check if point collides with a plane object
if(pObject->m_Type == COLLISION_PLANE) {
// Put plane in a local variable
D3DXPLANE Plane = pObject->m_Plane;
// Transform plane if needed
if(matTransform) {
// Inverse and transpose the transformation
// but do it only once to save time
if(MatrixInversedAndTransposed == FALSE) {
MatrixInversedAndTransposed = TRUE;
D3DXMatrixInverse(&matITTransform, NULL, matTransform);
D3DXMatrixTranspose(&matITTransform, &matITTransform);
}
// Transform the plane
D3DXPlaneTransform(&Plane, &Plane, &matITTransform);
}
// Get the normal vector
D3DXVECTOR3 vecNormal = D3DXVECTOR3(Plane.a, \
Plane.b, \
Plane.c);
// Get the dot product between the plane's normal
// and the point's position
float Dot = D3DXVec3Dot(&m_Points[i].m_vecPos, \
&vecNormal) + Plane.d;
// Check if point is behind plane
if(Dot < 0.0f) {
// Scale the plane's normal by the
// absolute dot product.
vecNormal *= (-Dot);
// Move point and adjust velocity by normal vector
m_Points[i].m_vecPos += vecNormal;
m_Points[i].m_vecVelocity += vecNormal;
}
}
// Go to next collision object
pObject = pObject->m_Next;
}
}
}
}
void cClothMesh::RebuildMesh(ID3DXMesh *Mesh)
{
DWORD i;
// Error checking
if(!m_NumPoints || !m_Points || !Mesh)
return;
// Lock vertex buffer
char *Vertices;
Mesh->LockVertexBuffer(0, (void**)&Vertices);
// Store each point in list
for(i=0;i<m_NumPoints;i++) {
// Get pointer to vertex data in buffer
sClothVertexPos *Vertex = (sClothVertexPos*)Vertices;
// Store vertex coordinates
Vertex->vecPos = m_Points[i].m_vecPos;
// Go to next vertex
Vertices += m_VertexStride;
}
// Unlock vertex buffer
Mesh->UnlockVertexBuffer();
// Recompute normals
D3DXComputeNormals(Mesh, NULL);
}
BOOL cClothMesh::Create(ID3DXMesh *Mesh, char *PointSpringXFile)
{
DWORD i;
// Free a prior mesh
Free();
// Error checking
if(!Mesh)
return FALSE;
// Calculate vertex pitch (size of vertex data)
m_VertexStride = D3DXGetFVFVertexSize(Mesh->GetFVF());
////////////////////////////////////////////////////////////
// Calculate the spring information from the loaded mesh
////////////////////////////////////////////////////////////
// Get the # of faces and allocate array
m_NumFaces = Mesh->GetNumFaces();
m_Faces = new DWORD[m_NumFaces*3];
// Lock index buffer and copy over data (16-bit indices)
unsigned short *Indices;
Mesh->LockIndexBuffer(0, (void**)&Indices);
for(i=0;i<m_NumFaces*3;i++)
m_Faces[i] = (DWORD)*Indices++;
Mesh->UnlockIndexBuffer();
// Get the # of points in mesh and allocate structures
m_NumPoints = Mesh->GetNumVertices();
m_Points = new cClothPoint[m_NumPoints]();
// Lock vertex buffer and stuff data into cloth points
char *Vertices;
Mesh->LockVertexBuffer(0, (void**)&Vertices);
for(i=0;i<m_NumPoints;i++) {
// Get pointer to vertex coordinates
sClothVertexPos *Vertex = (sClothVertexPos*)Vertices;
// Store position, velocity, force, and mass
m_Points[i].m_vecOriginalPos = Vertex->vecPos;
m_Points[i].m_vecPos = m_Points[i].m_vecOriginalPos;
m_Points[i].m_Mass = 1.0f;
m_Points[i].m_OneOverMass = 1.0f;
// Setup point's states
m_Points[i].m_vecVelocity = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
m_Points[i].m_vecForce = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
// Go to next vertex
Vertices += m_VertexStride;
}
Mesh->UnlockVertexBuffer();
// Build list of springs from face vertices
for(i=0;i<m_NumFaces;i++) {
// Get vertices that construct a face
DWORD Vertex1 = m_Faces[i*3];
DWORD Vertex2 = m_Faces[i*3+1];
DWORD Vertex3 = m_Faces[i*3+2];
// Add springs from 1->2, 2->3, and 3->1
AddSpring(Vertex1, Vertex2);
AddSpring(Vertex2, Vertex3);
AddSpring(Vertex3, Vertex1);
}
// Parse cloth masses and springs from file
if(PointSpringXFile)
Parse(PointSpringXFile);
return TRUE;
}
void cClothMesh::Free()
{
m_NumPoints = 0; // Delete cloth points array
delete [] m_Points;
m_Points = NULL;
m_NumSprings = 0; // Delete spring linked list
delete m_Springs;
m_Springs = NULL;
m_NumFaces = 0; // Delete faces array
delete [] m_Faces;
m_Faces = NULL;
m_VertexStride = 0; // Reset values
}
void cClothMesh::Reset()
{
// Error checking
if(!m_NumPoints || !m_Points)
return;
// Go through each point
for(DWORD i=0;i<m_NumPoints;i++) {
// Copy original points
m_Points[i].m_vecPos = m_Points[i].m_vecOriginalPos;
// Clear forces
m_Points[i].m_vecVelocity = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
}
}
void cClothMesh::AddSpring(DWORD Point1, DWORD Point2, float Ks, float Kd)
{
cClothSpring *Spring = m_Springs;
// Don't add springs that share the same point
if(Point1 == Point2)
return;
// Search for a duplicate spring already in list
while(Spring != NULL) {
// Check if a match and return if so (no duplicates)
if(Point1 == Spring->m_Point1 && Point2 == Spring->m_Point2)
return;
if(Point1 == Spring->m_Point2 && Point2 == Spring->m_Point1)
return;
// Make sure the two points are not the same
if(Point1 == Point2)
return;
// Go to next spring
Spring = Spring->m_Next;
}
// Allocate a spring and link to list (increasing count)
Spring = new cClothSpring();
Spring->m_Next = m_Springs;
m_Springs = Spring;
m_NumSprings++;
// Set spring's data
Spring->m_Point1 = Point1;
Spring->m_Point2 = Point2;
Spring->m_Ks = Ks;
Spring->m_Kd = Kd;
// Calculate resting length of spring
D3DXVECTOR3 vecDist = m_Points[Point2].m_vecPos -
m_Points[Point1].m_vecPos;
Spring->m_RestingLength = D3DXVec3Length(&vecDist);
}
void cClothMesh::SetMass(DWORD Point, float Mass)
{
// Only set mass if it's a valid point value
if(Point < m_NumPoints) {
m_Points[Point].m_Mass = Mass;
m_Points[Point].m_OneOverMass = (Mass==0.0f)?0.0f:1.0f/Mass;
}
}
DWORD cClothMesh::GetNumPoints()
{
return m_NumPoints;
}
cClothPoint *cClothMesh::GetPoints()
{
return m_Points;
}
DWORD cClothMesh::GetNumSprings()
{
return m_NumSprings;
}
cClothSpring *cClothMesh::GetSprings()
{
return m_Springs;
}
DWORD cClothMesh::GetNumFaces()
{
return m_NumFaces;
}
DWORD *cClothMesh::GetFaces()
{
return m_Faces;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -