@@ -1242,3 +1242,214 @@ TEST_F(TestPointConversion, testPrecision)
12421242 EXPECT_EQ (positionAfterNull.z (), positionAfterFixed16.z ());
12431243 }
12441244}
1245+
1246+ TEST_F (TestPointConversion, testExample)
1247+ {
1248+ // this is the example from the documentation using both Vec3R and Vec3f
1249+
1250+ { // Vec3R
1251+ // Create a vector with four point positions.
1252+ std::vector<openvdb::Vec3R> positions;
1253+ positions.push_back (openvdb::Vec3R (0 , 1 , 0 ));
1254+ positions.push_back (openvdb::Vec3R (1.5 , 3.5 , 1 ));
1255+ positions.push_back (openvdb::Vec3R (-1 , 6 , -2 ));
1256+ positions.push_back (openvdb::Vec3R (1.1 , 1.25 , 0.06 ));
1257+
1258+ // The VDB Point-Partioner is used when bucketing points and requires a
1259+ // specific interface. For convenience, we use the PointAttributeVector
1260+ // wrapper around an stl vector wrapper here, however it is also possible to
1261+ // write one for a custom data structure in order to match the interface
1262+ // required.
1263+ openvdb::points::PointAttributeVector<openvdb::Vec3R> positionsWrapper (positions);
1264+
1265+ // This method computes a voxel-size to match the number of
1266+ // points / voxel requested. Although it won't be exact, it typically offers
1267+ // a good balance of memory against performance.
1268+ int pointsPerVoxel = 8 ;
1269+ float voxelSize =
1270+ openvdb::points::computeVoxelSize (positionsWrapper, pointsPerVoxel);
1271+
1272+ // Create a transform using this voxel-size.
1273+ openvdb::math::Transform::Ptr transform =
1274+ openvdb::math::Transform::createLinearTransform (voxelSize);
1275+
1276+ // Create a PointDataGrid containing these four points and using the
1277+ // transform given. This function has two template parameters, (1) the codec
1278+ // to use for storing the position, (2) the grid we want to create
1279+ // (ie a PointDataGrid).
1280+ // We use no compression here for the positions.
1281+ openvdb::points::PointDataGrid::Ptr grid =
1282+ openvdb::points::createPointDataGrid<openvdb::points::NullCodec,
1283+ openvdb::points::PointDataGrid>(positions, *transform);
1284+
1285+ // Set the name of the grid
1286+ grid->setName (" Points" );
1287+
1288+ // Create a VDB file object and write out the grid.
1289+ openvdb::io::File (" mypoints.vdb" ).write ({grid});
1290+
1291+ // Create a new VDB file object for reading.
1292+ openvdb::io::File newFile (" mypoints.vdb" );
1293+
1294+ // Open the file. This reads the file header, but not any grids.
1295+ newFile.open ();
1296+
1297+ // Read the grid by name.
1298+ openvdb::GridBase::Ptr baseGrid = newFile.readGrid (" Points" );
1299+ newFile.close ();
1300+
1301+ // From the example above, "Points" is known to be a PointDataGrid,
1302+ // so cast the generic grid pointer to a PointDataGrid pointer.
1303+ grid = openvdb::gridPtrCast<openvdb::points::PointDataGrid>(baseGrid);
1304+
1305+ std::vector<Vec3R> resultingPositions;
1306+
1307+ // Iterate over all the leaf nodes in the grid.
1308+ for (auto leafIter = grid->tree ().cbeginLeaf (); leafIter; ++leafIter) {
1309+
1310+ // Extract the position attribute from the leaf by name (P is position).
1311+ const openvdb::points::AttributeArray& array =
1312+ leafIter->constAttributeArray (" P" );
1313+
1314+ // Create a read-only AttributeHandle. Position always uses Vec3f.
1315+ openvdb::points::AttributeHandle<openvdb::Vec3f> positionHandle (array);
1316+
1317+ // Iterate over the point indices in the leaf.
1318+ for (auto indexIter = leafIter->beginIndexOn (); indexIter; ++indexIter) {
1319+
1320+ // Extract the voxel-space position of the point.
1321+ openvdb::Vec3f voxelPosition = positionHandle.get (*indexIter);
1322+
1323+ // Extract the index-space position of the voxel.
1324+ const openvdb::Vec3d xyz = indexIter.getCoord ().asVec3d ();
1325+
1326+ // Compute the world-space position of the point.
1327+ openvdb::Vec3f worldPosition =
1328+ grid->transform ().indexToWorld (voxelPosition + xyz);
1329+
1330+ resultingPositions.push_back (worldPosition);
1331+ }
1332+ }
1333+
1334+ EXPECT_EQ (size_t (4 ), resultingPositions.size ());
1335+
1336+ // remap the position order
1337+
1338+ std::vector<size_t > remap;
1339+ remap.push_back (1 );
1340+ remap.push_back (3 );
1341+ remap.push_back (0 );
1342+ remap.push_back (2 );
1343+
1344+ for (int i = 0 ; i < 4 ; i++) {
1345+ EXPECT_NEAR (positions[i].x (), resultingPositions[remap[i]].x (), /* tolerance=*/ 1e-6 );
1346+ EXPECT_NEAR (positions[i].y (), resultingPositions[remap[i]].y (), /* tolerance=*/ 1e-6 );
1347+ EXPECT_NEAR (positions[i].z (), resultingPositions[remap[i]].z (), /* tolerance=*/ 1e-6 );
1348+ }
1349+
1350+ remove (" mypoints.vdb" );
1351+ }
1352+
1353+ { // Vec3f
1354+ // Create a vector with four point positions.
1355+ std::vector<openvdb::Vec3f> positions;
1356+ positions.push_back (openvdb::Vec3f (0 .0f , 1 .0f , 0 .0f ));
1357+ positions.push_back (openvdb::Vec3f (1 .5f , 3 .5f , 1 .0f ));
1358+ positions.push_back (openvdb::Vec3f (-1 .0f , 6 .0f , -2 .0f ));
1359+ positions.push_back (openvdb::Vec3f (1 .1f , 1 .25f , 0 .06f ));
1360+
1361+ // The VDB Point-Partioner is used when bucketing points and requires a
1362+ // specific interface. For convenience, we use the PointAttributeVector
1363+ // wrapper around an stl vector wrapper here, however it is also possible to
1364+ // write one for a custom data structure in order to match the interface
1365+ // required.
1366+ openvdb::points::PointAttributeVector<openvdb::Vec3f> positionsWrapper (positions);
1367+
1368+ // This method computes a voxel-size to match the number of
1369+ // points / voxel requested. Although it won't be exact, it typically offers
1370+ // a good balance of memory against performance.
1371+ int pointsPerVoxel = 8 ;
1372+ float voxelSize =
1373+ openvdb::points::computeVoxelSize (positionsWrapper, pointsPerVoxel);
1374+
1375+ // Create a transform using this voxel-size.
1376+ openvdb::math::Transform::Ptr transform =
1377+ openvdb::math::Transform::createLinearTransform (voxelSize);
1378+
1379+ // Create a PointDataGrid containing these four points and using the
1380+ // transform given. This function has two template parameters, (1) the codec
1381+ // to use for storing the position, (2) the grid we want to create
1382+ // (ie a PointDataGrid).
1383+ // We use no compression here for the positions.
1384+ openvdb::points::PointDataGrid::Ptr grid =
1385+ openvdb::points::createPointDataGrid<openvdb::points::NullCodec,
1386+ openvdb::points::PointDataGrid>(positions, *transform);
1387+
1388+ // Set the name of the grid
1389+ grid->setName (" Points" );
1390+
1391+ // Create a VDB file object and write out the grid.
1392+ openvdb::io::File (" mypoints.vdb" ).write ({grid});
1393+
1394+ // Create a new VDB file object for reading.
1395+ openvdb::io::File newFile (" mypoints.vdb" );
1396+
1397+ // Open the file. This reads the file header, but not any grids.
1398+ newFile.open ();
1399+
1400+ // Read the grid by name.
1401+ openvdb::GridBase::Ptr baseGrid = newFile.readGrid (" Points" );
1402+ newFile.close ();
1403+
1404+ // From the example above, "Points" is known to be a PointDataGrid,
1405+ // so cast the generic grid pointer to a PointDataGrid pointer.
1406+ grid = openvdb::gridPtrCast<openvdb::points::PointDataGrid>(baseGrid);
1407+
1408+ std::vector<Vec3f> resultingPositions;
1409+
1410+ // Iterate over all the leaf nodes in the grid.
1411+ for (auto leafIter = grid->tree ().cbeginLeaf (); leafIter; ++leafIter) {
1412+
1413+ // Extract the position attribute from the leaf by name (P is position).
1414+ const openvdb::points::AttributeArray& array =
1415+ leafIter->constAttributeArray (" P" );
1416+
1417+ // Create a read-only AttributeHandle. Position always uses Vec3f.
1418+ openvdb::points::AttributeHandle<openvdb::Vec3f> positionHandle (array);
1419+
1420+ // Iterate over the point indices in the leaf.
1421+ for (auto indexIter = leafIter->beginIndexOn (); indexIter; ++indexIter) {
1422+
1423+ // Extract the voxel-space position of the point.
1424+ openvdb::Vec3f voxelPosition = positionHandle.get (*indexIter);
1425+
1426+ // Extract the index-space position of the voxel.
1427+ const openvdb::Vec3d xyz = indexIter.getCoord ().asVec3d ();
1428+
1429+ // Compute the world-space position of the point.
1430+ openvdb::Vec3f worldPosition =
1431+ grid->transform ().indexToWorld (voxelPosition + xyz);
1432+
1433+ resultingPositions.push_back (worldPosition);
1434+ }
1435+ }
1436+
1437+ EXPECT_EQ (size_t (4 ), resultingPositions.size ());
1438+
1439+ // remap the position order
1440+
1441+ std::vector<size_t > remap;
1442+ remap.push_back (1 );
1443+ remap.push_back (3 );
1444+ remap.push_back (0 );
1445+ remap.push_back (2 );
1446+
1447+ for (int i = 0 ; i < 4 ; i++) {
1448+ EXPECT_NEAR (positions[i].x (), resultingPositions[remap[i]].x (), /* tolerance=*/ 1e-6f );
1449+ EXPECT_NEAR (positions[i].y (), resultingPositions[remap[i]].y (), /* tolerance=*/ 1e-6f );
1450+ EXPECT_NEAR (positions[i].z (), resultingPositions[remap[i]].z (), /* tolerance=*/ 1e-6f );
1451+ }
1452+
1453+ remove (" mypoints.vdb" );
1454+ }
1455+ }
0 commit comments