Fusion360-Addons/usr/Src/Core/pCloth/pCloth.cpp
2021-10-31 19:39:29 +01:00

515 lines
12 KiB
C++

#include <StdAfx.h>
#include "vtPhysXAll.h"
#include "Stream.h"
#include "cooking.h"
pCloth::~pCloth()
{
if (!getCloth())
{
return;
}
getWorld()->getScene()->releaseCloth(*mCloth);
//getWorld()->getScene()->
releaseReceiveBuffers();
setEntityID(-1);
}
void pCloth::detachFromShape(CKBeObject *shape)
{
if (!shape)
{
return;
}
NxShape *aShape = getWorld()->getShapeByEntityID(shape->GetID());
if (aShape)
{
getCloth()->detachFromShape(aShape);
}
}
void pCloth::dominateVertex(int vertexId, float expirationTime, float dominanceWeight)
{
getCloth()->dominateVertex(vertexId,expirationTime,dominanceWeight);
}
void pCloth::freeVertex(const int vertexId)
{
getCloth()->freeVertex(vertexId);
}
void pCloth::attachVertexToGlobalPosition(const int vertexId, const VxVector &pos)
{
getCloth()->attachVertexToGlobalPosition(vertexId,getFrom(pos));
}
void pCloth::attachVertexToShape(int vertexId, CKBeObject *shape, const VxVector &localPos, int attachmentFlags)
{
if (!shape)
{
return;
}
if (!getWorld())
return;
NxShape *aShape = getWorld()->getShapeByEntityID(shape->GetID());
if (aShape)
{
getCloth()->attachVertexToShape(vertexId,aShape,getFrom(localPos),attachmentFlags);
}
}
void pCloth::attachToCore(CK3dEntity *body, float impulseThreshold, float penetrationDepth, float maxDeformationDistance)
{
pRigidBody *rbody = GetPMan()->getBody(body);
if (!body)
{
return ;
}
if (rbody->getWorld() != getWorld() )
{
return;
}
getCloth()->attachToCore(rbody->getActor(),impulseThreshold,penetrationDepth,maxDeformationDistance);
}
void pCloth::attachToCollidingShapes(int attachmentFlags)
{
mCloth->attachToCollidingShapes(attachmentFlags);
}
void pCloth::attachToShape(CKBeObject *shape, int attachmentFlags)
{
if (!shape)
{
return;
}
if (!getWorld())
return;
NxShape *aShape = getWorld()->getShapeByEntityID(shape->GetID());
if (aShape)
{
getCloth()->attachToShape(aShape,attachmentFlags);
}
}
void pCloth::setCollisionResponseCoefficient(float coefficient)
{
mCloth->setCollisionResponseCoefficient(coefficient);
}
void pCloth::addDirectedForceAtPos(const VxVector& position, const VxVector& force, float radius, ForceMode mode /* = FM_Force */)
{
mCloth->addDirectedForceAtPos(getFrom(position),getFrom(force),(NxForceMode)mode );
}
void pCloth::addForceAtVertex(const VxVector& force, int vertexId, ForceMode mode /* = FM_Force */)
{
mCloth->addForceAtVertex(getFrom(force),vertexId,(NxForceMode)mode);
}
void pCloth::addForceAtPos(const VxVector& position, float magnitude, float radius, ForceMode mode /* = FM_Force */)
{
mCloth->addForceAtPos(getFrom(position),magnitude,radius,(NxForceMode)mode);
}
void pCloth::wakeUp(float wakeCounterValue /* = NX_SLEEP_INTERVAL */)
{
mCloth->wakeUp(wakeCounterValue);
}
void pCloth::putToSleep()
{
mCloth->putToSleep();
}
void pCloth::setFlags(int flags)
{
mCloth->setFlags(flags);
}
void pCloth::setSleepLinearVelocity(float threshold)
{
mCloth->setSleepLinearVelocity(threshold);
}
void pCloth::setExternalAcceleration(VxVector acceleration)
{
mCloth->setExternalAcceleration(getFrom(acceleration));
}
void pCloth::setWindAcceleration(VxVector acceleration)
{
mCloth->setWindAcceleration(getFrom(acceleration));
}
void pCloth::setMinAdhereVelocity(float velocity)
{
mCloth->setMinAdhereVelocity(velocity);
}
void pCloth::setToFluidResponseCoefficient(float coefficient)
{
mCloth->setToFluidResponseCoefficient(coefficient);
}
void pCloth::setFromFluidResponseCoefficient(float coefficient)
{
mCloth->setFromFluidResponseCoefficient(coefficient);
}
void pCloth::setAttachmentResponseCoefficient(float coefficient)
{
mCloth->setAttachmentResponseCoefficient(coefficient);
}
void pCloth::setVelocity(const VxVector& velocity, int vertexId)
{
mCloth->setVelocity(getFrom(velocity),vertexId);
}
void pCloth::setValidBounds(const VxBbox& validBounds)
{
NxBounds3 box;
box.set( getFrom(validBounds.Min), getFrom(validBounds.Max));
mCloth->setValidBounds(box);
}
void pCloth::setGroup(int collisionGroup)
{
mCloth->setGroup(collisionGroup);
}
void pCloth::setSolverIterations(int iterations)
{
mCloth->setSolverIterations(iterations);
}
void pCloth::setThickness(float thickness)
{
mCloth->setThickness(thickness);
}
void pCloth::setAttachmentTearFactor(float factor)
{
mCloth->setAttachmentTearFactor(factor);
}
void pCloth::setTearFactor(float factor)
{
mCloth->setTearFactor(factor);
}
void pCloth::setPressure(float pressure)
{
mCloth->setPressure(pressure);
}
void pCloth::setFriction(float friction)
{
mCloth->setFriction(friction);
}
void pCloth::setDampingCoefficient(float dampingCoefficient)
{
mCloth->setDampingCoefficient(dampingCoefficient);
}
void pCloth::setStretchingStiffness(float stiffness)
{
mCloth->setStretchingStiffness(stiffness);
}
void pCloth::setBendingStiffness(float stiffness)
{
mCloth->setBendingStiffness(stiffness);
}
void pCloth::updateVirtoolsMesh()
{
NxMeshData *data = getReceiveBuffers();
CK3dEntity *srcEntity =(CK3dEntity*) GetPMan()->GetContext()->GetObject(getEntityID());
if (!srcEntity)
{
return;
}
/*
if (getCloth()->isSleeping())
{
return;
}
*/
CKMesh *mesh = srcEntity->GetCurrentMesh();
NxReal *vertices = (NxReal*)data->verticesPosBegin;
VxVector pos;
srcEntity->GetPosition(&pos);
for (int i = 0 ; i< mesh->GetVertexCount() ; i++ )
{
VxVector v;
v.x = vertices[i * 3];
v.y = vertices[i * 3 + 1];
v.z = vertices[i * 3 + 2];
VxVector outIV;
srcEntity->InverseTransform(&outIV,&v);
mesh->SetVertexPosition(i,&outIV);
}
int t = 3;
}
bool pCloth::cookMesh(NxClothMeshDesc* desc)
{
// we cook the mesh on the fly through a memory stream
// we could also use a file stream and pre-cook the mesh
MemoryWriteBuffer wb;
int dValid = desc->isValid();
bool status = InitCooking();
if (!status) {
xLogger::xLog(ELOGERROR,E_LI_AGEIA,"Couldn't initiate cooking lib!");
return NULL;
}
bool success = CookClothMesh(*desc, wb);
if (!success)
return false;
MemoryReadBuffer rb(wb.data);
mClothMesh = GetPMan()->getPhysicsSDK()->createClothMesh(rb);
CloseCooking();
return true;
}
bool pCloth::generateMeshDesc(pClothDesc cDesc,NxClothMeshDesc *desc, CKMesh*mesh)
{
if (!mesh)
{
return false;
}
int numVerts = mesh->GetVertexCount();
int numFaces = mesh->GetFaceCount();
// allocate flag buffer
if(desc->vertexFlags == 0)
desc->vertexFlags = malloc(sizeof(NxU32)*desc->numVertices);
// create tear lines
NxU32* flags = (NxU32*)desc->vertexFlags;
NxReal *vertices = new float[3 * numVerts];
//NxVec3 *verts = new NxVec3[numVerts];
for (int i = 0 ; i< numVerts ; i++ )
{
VxVector v;
mesh->GetVertexPosition(i,&v);
vertices[i * 3] = v.x;
vertices[i * 3 + 1] =v.y;
vertices[i * 3 + 2] = v.z;
if (desc->flags & NX_CLOTH_MESH_TEARABLE)
{
DWORD vColor = mesh->GetVertexColor(i);
DWORD cColor = RGBAFTOCOLOR(&cDesc.tearVertexColor);
if (vColor == cColor )
{
int op2 =0;
flags[i] = NX_CLOTH_VERTEX_TEARABLE;
int k = 0 ;
k++;
}
}
}
NxU32 *indices2 = new NxU32[numFaces*3];
for(int j = 0 ; j < numFaces ; j++)
{
int findicies[3];
mesh->GetFaceVertexIndex(j,findicies[0],findicies[1],findicies[2]);
indices2[ j *3 ] = findicies[0];
indices2[ j *3 + 1 ] = findicies[1];
indices2[ j *3 + 2 ] = findicies[2];
}
desc->numVertices = numVerts;
desc->pointStrideBytes = sizeof(NxReal)*3;
desc->points = vertices;
desc->numTriangles = numFaces;
desc->triangles = indices2;
desc->triangleStrideBytes = sizeof(NxU32)*3;
desc->flags = 0;
desc->vertexMasses = 0;
desc->vertexFlags = 0;
desc->flags = NX_CLOTH_MESH_WELD_VERTICES;
desc->weldingDistance = 0.0001f;
return true;
}
void pCloth::allocateClothReceiveBuffers(int numVertices, int numTriangles)
{
// here we setup the buffers through which the SDK returns the dynamic cloth data
// we reserve more memory for vertices than the initial mesh takes
// because tearing creates new vertices
// the SDK only tears cloth as long as there is room in these buffers
mReceiveBuffers = new NxMeshData();
NxU32 maxVertices = 3 * numVertices;
mReceiveBuffers->verticesPosBegin = (NxVec3*)malloc(sizeof(NxVec3)*maxVertices);
mReceiveBuffers->verticesNormalBegin = (NxVec3*)malloc(sizeof(NxVec3)*maxVertices);
mReceiveBuffers->verticesPosByteStride = sizeof(NxVec3);
mReceiveBuffers->verticesNormalByteStride = sizeof(NxVec3);
mReceiveBuffers->maxVertices = maxVertices;
mReceiveBuffers->numVerticesPtr = (NxU32*)malloc(sizeof(NxU32));
// the number of triangles is constant, even if the cloth is torn
NxU32 maxIndices = 3*numTriangles;
mReceiveBuffers->indicesBegin = (NxU32*)malloc(sizeof(NxU32)*maxIndices);
mReceiveBuffers->indicesByteStride = sizeof(NxU32);
mReceiveBuffers->maxIndices = maxIndices;
mReceiveBuffers->numIndicesPtr = (NxU32*)malloc(sizeof(NxU32));
// the parent index information would be needed if we used textured cloth
NxU32 maxParentIndices = maxVertices;
mReceiveBuffers->parentIndicesBegin = (NxU32*)malloc(sizeof(NxU32)*maxParentIndices);
mReceiveBuffers->parentIndicesByteStride = sizeof(NxU32);
mReceiveBuffers->maxParentIndices = maxParentIndices;
mReceiveBuffers->numParentIndicesPtr = (NxU32*)malloc(sizeof(NxU32));
// init the buffers in case we want to draw the mesh
// before the SDK as filled in the correct values
*mReceiveBuffers->numVerticesPtr = 0;
*mReceiveBuffers->numIndicesPtr = 0;
}
void pCloth::releaseReceiveBuffers()
{
// Parent Indices is always allocated
/* free (mReceiveBuffers.parentIndicesBegin);
mReceiveBuffers.setToDefault();*/
}
void pCloth::releaseMeshDescBuffers(const NxClothMeshDesc* desc)
{
NxVec3* p = (NxVec3*)desc->points;
NxU32* t = (NxU32*)desc->triangles;
NxReal* m = (NxReal*)desc->vertexMasses;
NxU32* f = (NxU32*)desc->vertexFlags;
free(p);
free(t);
free(m);
free(f);
}
pCloth::pCloth()
{
}
/*----------------------------------------------------------------------------*/
pClothDesc::pClothDesc()
{
//setToDefault();
}
/*----------------------------------------------------------------------------*/
void pClothDesc::setToDefault()
{
thickness = 0.01f;
density = 1.0f;
bendingStiffness = 1.0f;
stretchingStiffness = 1.0f;
dampingCoefficient = 0.5f;
friction = 0.5f;
pressure = 1.0f;
tearFactor = 1.5f;
attachmentTearFactor = 1.5f;
attachmentResponseCoefficient = 0.2f;
attachmentTearFactor = 1.5f;
collisionResponseCoefficient = 0.2f;
toFluidResponseCoefficient = 1.0f;
fromFluidResponseCoefficient = 1.0f;
minAdhereVelocity = 1.0f;
flags = PCF_Gravity|PCF_CollisionTwoway;
solverIterations = 5;
wakeUpCounter = NX_SLEEP_INTERVAL;
sleepLinearVelocity = -1.0f;
collisionGroup = 0;
forceFieldMaterial = 0;
externalAcceleration =VxVector(0.0f, 0.0f, 0.0f);
windAcceleration=VxVector(0.0f, 0.0f, 0.0f);
groupsMask.bits0 = 0;
groupsMask.bits1 = 0;
groupsMask.bits2 = 0;
groupsMask.bits3 = 0;
validBounds = VxBbox();
relativeGridSpacing = 0.25f;
tearVertexColor.Set(1.0f);
}
/*----------------------------------------------------------------------------*/
bool pClothDesc::isValid() const
{
// if (flags & NX_CLF_SELFCOLLISION) return false; // not supported at the moment
if(thickness < 0.0f) return false;
if(density <= 0.0f) return false;
if(bendingStiffness < 0.0f || bendingStiffness > 1.0f) return false;
if(stretchingStiffness <= 0.0f || stretchingStiffness > 1.0f) return false;
if(pressure < 0.0f) return false;
if(tearFactor <= 1.0f) return false;
if(attachmentTearFactor <= 1.0f) return false;
if(solverIterations < 1) return false;
if(friction < 0.0f || friction > 1.0f) return false;
if(dampingCoefficient < 0.0f || dampingCoefficient > 1.0f) return false;
if(collisionResponseCoefficient < 0.0f) return false;
if(wakeUpCounter < 0.0f) return false;
if(attachmentResponseCoefficient < 0.0f || attachmentResponseCoefficient > 1.0f) return false;
if(toFluidResponseCoefficient < 0.0f) return false;
if(fromFluidResponseCoefficient < 0.0f) return false;
if(minAdhereVelocity < 0.0f) return false;
if(relativeGridSpacing < 0.01f) return false;
if(collisionGroup >= 32) return false; // We only support 32 different collision groups
return true;
}