NVIDIAGameWorks / FleX

Other
664 stars 100 forks source link

Fluid & Cloth Issues #8

Closed ghost closed 7 years ago

ghost commented 7 years ago

I tested nearly all sample scenes in Flex 1.1.0 on Windows10 64bit D3D11 (NV Driver v381.65) and was able to successfully combine cloth, rigid, softbody and fluid emitters into a new custom Scene). Flex is great!

But when adding a custom cloth to one of the Bath Dam scenes things go wrong. UPDATE: solved. (I fixed some bugs in my test, upgraded to Flex 1.2.0 beta.1 and changed some parameters)


Soft Body <=> Rigid Bodies (CreateParticleShape) interaction function void SkinMesh(); in helpers.h uses same index for rigidRotations and rigidMeshSize: const Matrix33 rotation = g_buffers->rigidRotations[r]; const int numVertices = g_buffers->rigidMeshSize[r];

CreateParticleShape(..) from from bouyancy adds entries for both.

But "CreateSoftBody" in the "SoftBody" class only adds elements to g_buffers->rigidRotations not to rigidMeshSize ! And so combining soft bodys and rigid bodies can cause a crash in SkinMesh() function To solve this I added "g_buffers->rigidMeshSize.push_back(0); " in "CreateSoftBody" function (in SoftBody.h) in the loop for all asset->numShapes (the original scenes are not affected, cause they don't combine soft bodies with rigid bodies;


Additional Suggestion: there's no "universal sphere" collision constraint in "NvFlexCollisionShapeType" enum, with a radius for X, Y and Z (as in old D3D11 NVIDIA Hair Sample). And yet also no "cylinder" constraint (was also present in D3D11 NVIDIA Hair Sample). Maybe such a pre-defined collision constraint would be faster than always submitting a mesh with such a simple geometry

ghost commented 7 years ago

UPDATE:
A similar problem occurs with the cloth, when using more than one custom mesh EDIT: MyCustomCloth file removed. both meshes, if applied in separate sample Scenes work fine, but together they fail. They are exactly build with the same logic. And all "g_buffers->..." accesses are made relative, so that those both cloth meshes simply should be appended. The only dependency is, that they must be done first in a scene yet, but in this sample there's no other object which could influence them. But they are both disturbed yet. UPDATE 2: solved.

mmacklin commented 7 years ago

I think the problem here is probably due to the fact that the indices are note correctly offset:

g_buffers->springIndices.push_back(mCloth->springIndices[i]);

For the second cloth the indices need to be shifted by the number of particles in the first cloth. So before adding particles for the second cloth, record the current number of particles, e.g.:

int particleOffset = g_buffers->positions.size();

Then, when adding indices for the second cloth:

for (int i = 0; i < numsprings * 2; ++i)
   g_buffers->springIndices.push_back(mCloth->springIndices[i] + particleOffset);
ghost commented 7 years ago

Thanks You Miles @mmacklin for your answer. As you suggested, I added "start_cloth_index":

g_buffers->triangles.push_back(mesh->m_indices[i] + start_cloth_index);
g_buffers->springIndices.push_back(mCloth->springIndices[i] + start_cloth_index); 

And finally it works! Great! My updated code was wrong. Thank you for the help. (I removed the MyCustomCloth file in the post cause of that invalid part)

However, it still fails in the Bath Dam scene. So I will again investigate the "Fluid Cloth Coupling Goo" Scene, which works fine for cloth and water interaction. There adding adhesion works fine, too. UPDATE: solved.

I also noticed a loop in the "Voxelize" function in voxelize.cpp which can cause a very high time penalty, if the mesh of a soft body object has a different topology. So I limited the rays for each voxel to 10. Do you know a better threshold for this?

ghost commented 7 years ago

I debugged the original scenes. On "Soft Bowl" "Soft Rod", "Soft Armadillo", "Soft Bunny", "Plastic Bunnies" during the call to "NvFlexSetRigids" this error can occur:

_D3D11 ERROR: ID3D11DeviceContext::Dispatch: The Unordered Access View in slot 0 of the Compute Shader unit has structure stride 16 while the shader expects a structure stride of 4. This mismatch is invalid if the shader actually uses the view (e.g. it is not skipped due to shader code branching). [ EXECUTION ERROR #2097378: DEVICE_UNORDEREDACCESSVIEW_STRUCTURE_STRIDEMISMATCH]

Sometimes before warm up additionally this error can occur:

D3D11 ERROR: ID3D11DeviceContext::CopySubresourceRegion: pSrcBox is not a valid box for the source subresource. *pSrcBox = { left:0, top:0, front:0, right:180912, bottom:1, back:1 }. SrcSubresource = { left:0, top:0, front:0, right:86272, bottom:1, back:1 }. [ RESOURCE_MANIPULATION ERROR #280: COPYSUBRESOURCEREGION_INVALIDSOURCEBOX]

However, that seems only affect soft-bodies, nothing else. Visually I see no error, so maybe it is only missing data through the initialization process, which means nothing. On Cloth objects this does not occur.

UPDATE: solved.

mmacklin commented 7 years ago

We fixed this in the 1.2.0 beta release (available now).

ghost commented 7 years ago

thanks, I upgraded my project, which uses Flex to operate with the new version.

ghost commented 7 years ago

I found out: g_params.numIterations = 3; is tearing the custom cloth. Also g_numSubsteps = 1 can cause this. When changing the "Num Iterations" slider in the original "Tearing" sample down to a value lower than 4 it disturbs the cloth. (In the "Potpourri" Scene a value of 1 works for that, although there's also cloth) So I set these always to 4 or more (mostly 7).

high increasing adhesion in Bath Dam + Paragliding Scene disturbs everything

ghost commented 7 years ago

using the AddTriangleMesh() function to build collision constraints works great with soft bodies, and I got custom cloth and Bouyancy water interaction also working with g_params.numIterations = 7 custom cloth in Bunny Bath Dam Scene with: g_params.relaxationFactor = 1.0f; g_params.relaxationMode = eNvFlexRelaxationLocal;

UPDATE: I found out, that g_buffers->rigidTranslations receives wrong values, cause CalculateRigidCentersOfMass is never called in the case, when soft bodies are active, cause g_buffers->rigidTranslations.size() is non-zeo after soft bodies were done.

So in main.cpp in function void Init(int scene, bool centerCamera = true) I changed;

    if (g_buffers->rigidTranslations.size() == 0)
    {
         g_buffers->rigidTranslations.resize(g_buffers->rigidOffsets.size() - 1, Vec3());
         CalculateRigidCentersOfMass(...
    }

to:

    int rigidTranslations = g_buffers->rigidTranslations.size();
    if (rigidTranslations != numRigids)  // to ensure ANY changes (if soft body already present)
        {
            g_buffers->rigidTranslations.resize(g_buffers->rigidOffsets.size() - 1, Vec3());
            CalculateRigidCentersOfMass(....
    }

So all these combinations work in my tests:

Still issue here:

Additionally I will use NVIDIA Blast to also have the destruction capabilities. All results from that data will then be added as collision constraints in Flex.

UPDATE: The soft body and rigid body interaction issue seems to be solved. And I think the general "custom cloth" and fluid interaction issue is also solved now.

ghost commented 7 years ago

I think most of my issues are solved now. Flex is really great! It would be great to have local settings of adhesion and other fluid related properties on each "group". So different fluids then could be done within one scene. Is it possible to switch adhesion off on solid particles only? This at least would solve some interaction issues.

ghost commented 7 years ago

UPDATED: solved now using DXUT CFirstPersonCamera works for me in both ways for Rendering Fluid:

  1. through building RH Matrices with functions of Flex:

    
    g_camPos.x = camX;
    g_camPos.y = camY;
    g_camPos.z = -camZ;  // D3D LH to RH
    
    g_camAngle.x = -yaw;   // to RH   (yaw in FirstPersonCamera is Y angle)
    g_camAngle.y = -pitch; // to RH   (pitch in FirstPersonCamera is X angle)
    g_camAngle.z = -roll;    // to RH   (roll in FirstPersonCamera is Z angle)

2. through using  directly "LHprojection" and "LHview" matrices from DXUT CFirstPersonCamera:
Vec4 c1, c2, c3, c4;

// apply projection LH MAJOR ROW as MAJOR COLUMN matrix:
c1 = Vec4(LHprojection->_11, LHprojection->_12, LHprojection->_13, LHprojection->_14);
c2 = Vec4(LHprojection->_21, LHprojection->_22, LHprojection->_23, LHprojection->_24);
c3 = Vec4(LHprojection->_31, LHprojection->_32, LHprojection->_33, LHprojection->_34);
c4 = Vec4(LHprojection->_41, LHprojection->_42, LHprojection->_43, LHprojection->_44);
proj = Matrix44(c1, c2, c3, c4);

// apply view LH MAJOR ROW as MAJOR COLUMN matrix:
c1 = Vec4(LHview->_11, LHview->_12, LHview->_13, LHview->_14);
c2 = Vec4(LHview->_21, LHview->_22, LHview->_23, LHview->_24);
c3 = Vec4(LHview->_31, LHview->_32, LHview->_33, LHview->_34);
c4 = Vec4(LHview->_41, LHview->_42, LHview->_43, LHview->_44);
view = Matrix44(c1, c2, c3, c4);

// LH ro RH rotation
view.columns[0][2]=-view.columns[0][2];
view.columns[1][2]=-view.columns[1][2];
view.columns[2][0]=-view.columns[2][0];
view.columns[2][1]=-view.columns[2][1];

// LH to RH translation
view.columns[3][2]=-view.columns[3][2]; 

// LH to RH projection
proj.columns[2][2] = -proj.columns[2][2];
proj.columns[2][3] = -proj.columns[2][3];

and in DemoContextD3D11::setView() I simply removed ConvertToD3DProjection

These Matrix transforms work for me; however I'm always interested if you find any error within it.
ghost commented 7 years ago

All solved so far. Flex is great!