OpenVDB 中网格的转换和 CSG 操作
Transformation and CSG Operations on grid in OpenVDB
OpenVDB 看起来真的很神奇,节点的寻址真的很聪明。有些操作我不明白,特别是CSG操作。这是一个示例代码。它需要两个参数作为输入:
- 只有一个网格的 vdb 输入文件,表示从三角形网格开始创建的水平集,
- 存储操作结果的 vdb 输出。
算法应该接受输入,
- 在 gridA 中创建一个 deepCopy
- 在 gridB 中创建一个 deepCopy
- 沿 M_PI/4.0f
的 Y 轴旋转 gridB
- 执行 gridA 和 gridB 之间的 csgUnion
- 将所有网格保存在 vdb 输出文件中。
我正在尝试使用 VDB 网格作为数据容器来代替经典树算法,用于需要高度详细的碰撞细节的物理模拟。
我了解世界坐标和网格坐标之间转换的概念,我无法理解如何在树内部进行数据转换,例如平移或旋转水平集,如刚性对象。在这个例子中,我想我只是在改变世界和晶格之间的转换。
这是结果(水平集和音量相同):Initial GridTrasformed grid, it seems that the rotation is performed...没有最终结果?
你有什么建议吗?
附上:一个示例和一个 link 到我正在使用的 LINK REMOVED(抱歉,它是 133MB...)
#include <cmath>
#include "openvdb/openvdb.h"
#include "openvdb/util/Util.h"
#include "openvdb/io/Stream.h"
#include "openvdb/tools/Composite.h"
using namespace openvdb;
int main(int argc, char** argv) {
openvdb::initialize();
openvdb::io::File file(argv[1]);
file.open();
GridBase::Ptr baseGrid;
for (openvdb::io::File::NameIterator nameIter = file.beginName();
nameIter != file.endName(); ++nameIter)
{ baseGrid = file.readGrid(nameIter.gridName()); }
file.close();
FloatGrid::Ptr gridA = gridPtrCast<FloatGrid>(baseGrid);
FloatGrid::Ptr gridB = gridA->deepCopy();
FloatGrid::Ptr result = gridA ->deepCopy();
gridB->transform().postRotate(M_PI/4.0f, math::Y_AXIS);
tools::csgUnion(*result, *gridB);
openvdb::io::File file_out(argv[2]);
GridPtrVec grids;
grids.push_back(gridA);
grids.push_back(gridB);
grids.push_back(result);
file_out.write(grids);
file_out.close();
return 0;
}
感谢 OpenVDB 论坛对 VDB 的支持,我的答案的解决方案是:
- 执行初始网格的简单元数据副本
- 执行转换(就像我代码中的旋转)
- 在新转换的网格中从初始网格重新插值数据,使用
tools::resampleToMatch
,选择可用的插值器之一(在我的例子中为tools::BoxSample
) .
- 继续 csg 操作
仅供参考,执行时间有 极大的差异
使用优化标志 -O3
(减少 400% 的时间)。
#include "openvdb/io/Stream.h"
#include "openvdb/openvdb.h"
#include "openvdb/tools/Composite.h"
#include "openvdb/tools/GridTransformer.h"
#include "openvdb/tools/Interpolation.h"
#include "openvdb/util/Util.h"
#include <cmath>
using namespace openvdb;
int main(int argc, char **argv) {
openvdb::initialize();
openvdb::io::File file(argv[1]);
file.open();
GridBase::Ptr baseGrid;
for (openvdb::io::File::NameIterator nameIter = file.beginName();
nameIter != file.endName(); ++nameIter) {
baseGrid = file.readGrid(nameIter.gridName());
}
file.close();
FloatGrid::Ptr gridA = gridPtrCast<FloatGrid>(baseGrid);
FloatGrid::Ptr gridB = gridA->copy(CP_NEW);
gridB->setTransform(gridA->transform().copy());
gridB->transform().postRotate(M_PI / 4.0f, math::Y_AXIS);
tools::resampleToMatch<tools::BoxSampler>(*gridA, *gridB);
FloatGrid::Ptr result = gridA->deepCopy();
FloatGrid::Ptr gridB2 = gridB->deepCopy();
tools::csgUnion(*result, *gridB);
openvdb::io::File file_out(argv[2]);
GridPtrVec grids;
grids.push_back(gridA);
grids.push_back(gridB2);
grids.push_back(result);
file_out.write(grids);
file_out.close();
return 0;
}
OpenVDB 看起来真的很神奇,节点的寻址真的很聪明。有些操作我不明白,特别是CSG操作。这是一个示例代码。它需要两个参数作为输入:
- 只有一个网格的 vdb 输入文件,表示从三角形网格开始创建的水平集,
- 存储操作结果的 vdb 输出。
算法应该接受输入,
- 在 gridA 中创建一个 deepCopy
- 在 gridB 中创建一个 deepCopy
- 沿 M_PI/4.0f 的 Y 轴旋转 gridB
- 执行 gridA 和 gridB 之间的 csgUnion
- 将所有网格保存在 vdb 输出文件中。
我正在尝试使用 VDB 网格作为数据容器来代替经典树算法,用于需要高度详细的碰撞细节的物理模拟。
我了解世界坐标和网格坐标之间转换的概念,我无法理解如何在树内部进行数据转换,例如平移或旋转水平集,如刚性对象。在这个例子中,我想我只是在改变世界和晶格之间的转换。
这是结果(水平集和音量相同):
你有什么建议吗?
附上:一个示例和一个 link 到我正在使用的 LINK REMOVED(抱歉,它是 133MB...)
#include <cmath>
#include "openvdb/openvdb.h"
#include "openvdb/util/Util.h"
#include "openvdb/io/Stream.h"
#include "openvdb/tools/Composite.h"
using namespace openvdb;
int main(int argc, char** argv) {
openvdb::initialize();
openvdb::io::File file(argv[1]);
file.open();
GridBase::Ptr baseGrid;
for (openvdb::io::File::NameIterator nameIter = file.beginName();
nameIter != file.endName(); ++nameIter)
{ baseGrid = file.readGrid(nameIter.gridName()); }
file.close();
FloatGrid::Ptr gridA = gridPtrCast<FloatGrid>(baseGrid);
FloatGrid::Ptr gridB = gridA->deepCopy();
FloatGrid::Ptr result = gridA ->deepCopy();
gridB->transform().postRotate(M_PI/4.0f, math::Y_AXIS);
tools::csgUnion(*result, *gridB);
openvdb::io::File file_out(argv[2]);
GridPtrVec grids;
grids.push_back(gridA);
grids.push_back(gridB);
grids.push_back(result);
file_out.write(grids);
file_out.close();
return 0;
}
感谢 OpenVDB 论坛对 VDB 的支持,我的答案的解决方案是:
- 执行初始网格的简单元数据副本
- 执行转换(就像我代码中的旋转)
- 在新转换的网格中从初始网格重新插值数据,使用
tools::resampleToMatch
,选择可用的插值器之一(在我的例子中为tools::BoxSample
) . - 继续 csg 操作
仅供参考,执行时间有 极大的差异
使用优化标志 -O3
(减少 400% 的时间)。
#include "openvdb/io/Stream.h"
#include "openvdb/openvdb.h"
#include "openvdb/tools/Composite.h"
#include "openvdb/tools/GridTransformer.h"
#include "openvdb/tools/Interpolation.h"
#include "openvdb/util/Util.h"
#include <cmath>
using namespace openvdb;
int main(int argc, char **argv) {
openvdb::initialize();
openvdb::io::File file(argv[1]);
file.open();
GridBase::Ptr baseGrid;
for (openvdb::io::File::NameIterator nameIter = file.beginName();
nameIter != file.endName(); ++nameIter) {
baseGrid = file.readGrid(nameIter.gridName());
}
file.close();
FloatGrid::Ptr gridA = gridPtrCast<FloatGrid>(baseGrid);
FloatGrid::Ptr gridB = gridA->copy(CP_NEW);
gridB->setTransform(gridA->transform().copy());
gridB->transform().postRotate(M_PI / 4.0f, math::Y_AXIS);
tools::resampleToMatch<tools::BoxSampler>(*gridA, *gridB);
FloatGrid::Ptr result = gridA->deepCopy();
FloatGrid::Ptr gridB2 = gridB->deepCopy();
tools::csgUnion(*result, *gridB);
openvdb::io::File file_out(argv[2]);
GridPtrVec grids;
grids.push_back(gridA);
grids.push_back(gridB2);
grids.push_back(result);
file_out.write(grids);
file_out.close();
return 0;
}