Enable interior nodes for interpolated flex shell mode.
Previously shell mode required cellcount=1 along at least one axis. This CL adds support for cellcount > 1 in all three axes by pinning interior grid nodes to the parent body and reconstructing their positions from boundary nodes via Transfinite Interpolation (TFI). PiperOrigin-RevId: 924314800 Change-Id: I8c2438f4866dd4133feed65f535a1ab69f0c9188
This commit is contained in:
committed by
Copybara-Service
parent
4548e81e4d
commit
91c92279d2
@@ -644,8 +644,26 @@ bool mjCFlexcomp::Make(mjsBody* body, char* error, int error_sz, const mjVFS* vf
|
||||
int nz = flex->spec.cellcount[2] * flex->spec.order + 1;
|
||||
int nnode = nx * ny * nz;
|
||||
|
||||
// mark empty cells and pin nodes exclusively in empty cells
|
||||
MarkEmptyCells(flex, point.data(), npnt, minmax, nx, ny, nz);
|
||||
// mark empty cells and pin nodes exclusively in empty cells (volume mode only)
|
||||
if (!dflex->elastic2d) {
|
||||
MarkEmptyCells(flex, point.data(), npnt, minmax, nx, ny, nz);
|
||||
}
|
||||
|
||||
// shell mode: pin all interior (non-boundary) nodes
|
||||
if (dflex->elastic2d) {
|
||||
for (int gi = 0; gi < nx; gi++) {
|
||||
for (int gj = 0; gj < ny; gj++) {
|
||||
for (int gk = 0; gk < nz; gk++) {
|
||||
bool is_boundary = (gi == 0 || gi == nx-1 ||
|
||||
gj == 0 || gj == ny-1 ||
|
||||
gk == 0 || gk == nz-1);
|
||||
if (!is_boundary) {
|
||||
pinned[gi*ny*nz + gj*nz + gk] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if MarkEmptyCells pinned any nodes, force centered=false
|
||||
// so that pf->node (local positions) is saved to the model
|
||||
|
||||
@@ -4698,11 +4698,7 @@ void mjCFlex::Compile(const mjVFS* vfs) {
|
||||
if (spec.cellcount[0] == 0 || spec.cellcount[1] == 0 || spec.cellcount[2] == 0) {
|
||||
throw mjCError(this, "cellcount cannot be 0 in any dimension when interpolation order > 0");
|
||||
}
|
||||
if (elastic2d && !(spec.cellcount[0] == 1 || spec.cellcount[1] == 1 || spec.cellcount[2] == 1)) {
|
||||
throw mjCError(this,
|
||||
"shell trilinear flex requires at least one dimension "
|
||||
"with cell count equal to one (no interior nodes)");
|
||||
}
|
||||
|
||||
int expected_nodes = (spec.cellcount[0] * spec.order + 1) *
|
||||
(spec.cellcount[1] * spec.order + 1) *
|
||||
(spec.cellcount[2] * spec.order + 1);
|
||||
@@ -4944,9 +4940,9 @@ void mjCFlex::Compile(const mjVFS* vfs) {
|
||||
// create shell fragments and element-vertex collision pairs
|
||||
CreateShellPair();
|
||||
|
||||
// recompute cell_empty from vertex/element geometry
|
||||
// recompute cell_empty from vertex/element geometry (volume mode only)
|
||||
// (survives XML round-trips where flexcomp data is lost)
|
||||
if (interpolated && cell_empty.empty()) {
|
||||
if (interpolated && !elastic2d && cell_empty.empty()) {
|
||||
int cx = spec.cellcount[0], cy = spec.cellcount[1], cz = spec.cellcount[2];
|
||||
if (cx * cy * cz > 1) {
|
||||
ComputeCellEmpty(vertxpos.data(), elem_.data(), nvert, nelem, dim);
|
||||
|
||||
Reference in New Issue
Block a user