@@ -1522,246 +1522,6 @@ TEST_F(TestFile, testReadClippedGrid)
15221522// //////////////////////////////////////
15231523
15241524
1525- namespace {
1526-
1527- template <typename T, openvdb::Index Log2Dim> struct MultiPassLeafNode ; // forward declaration
1528-
1529- // Dummy value type
1530- using MultiPassValue = openvdb::PointIndex<openvdb::Index32, 1000 >;
1531-
1532- // Tree configured to match the default OpenVDB configuration
1533- using MultiPassTree = openvdb::tree::Tree<
1534- openvdb::tree::RootNode<
1535- openvdb::tree::InternalNode<
1536- openvdb::tree::InternalNode<
1537- MultiPassLeafNode<MultiPassValue, 3 >, 4 >, 5 >>>;
1538-
1539- using MultiPassGrid = openvdb::Grid<MultiPassTree>;
1540-
1541-
1542- template <typename T, openvdb::Index Log2Dim>
1543- struct MultiPassLeafNode : public openvdb ::tree::LeafNode<T, Log2Dim>, openvdb::io::MultiPass
1544- {
1545- // The following had to be copied from the LeafNode class
1546- // to make the derived class compatible with the tree structure.
1547-
1548- using LeafNodeType = MultiPassLeafNode;
1549- using Ptr = openvdb::SharedPtr<MultiPassLeafNode>;
1550- using BaseLeaf = openvdb::tree::LeafNode<T, Log2Dim>;
1551- using NodeMaskType = openvdb::util::NodeMask<Log2Dim>;
1552- using ValueType = T;
1553- using ValueOnCIter = typename BaseLeaf::template ValueIter<typename NodeMaskType::OnIterator,
1554- const MultiPassLeafNode, const ValueType, typename BaseLeaf::ValueOn>;
1555- using ChildOnIter = typename BaseLeaf::template ChildIter<typename NodeMaskType::OnIterator,
1556- MultiPassLeafNode, typename BaseLeaf::ChildOn>;
1557- using ChildOnCIter = typename BaseLeaf::template ChildIter<
1558- typename NodeMaskType::OnIterator, const MultiPassLeafNode, typename BaseLeaf::ChildOn>;
1559-
1560- MultiPassLeafNode (const openvdb::Coord& coords, const T& value, bool active = false )
1561- : BaseLeaf(coords, value, active) {}
1562- MultiPassLeafNode (openvdb::PartialCreate, const openvdb::Coord& coords, const T& value,
1563- bool active = false ): BaseLeaf(openvdb::PartialCreate(), coords, value, active) {}
1564- MultiPassLeafNode (const MultiPassLeafNode& rhs): BaseLeaf(rhs) {}
1565-
1566- ValueOnCIter cbeginValueOn () const { return ValueOnCIter (this ->getValueMask ().beginOn (),this ); }
1567- ChildOnCIter cbeginChildOn () const { return ChildOnCIter (this ->getValueMask ().endOn (), this ); }
1568- ChildOnIter beginChildOn () { return ChildOnIter (this ->getValueMask ().endOn (), this ); }
1569-
1570- // Methods in use for reading and writing multiple buffers
1571-
1572- void readBuffers (std::istream& is, const openvdb::CoordBBox&, bool fromHalf = false )
1573- {
1574- this ->readBuffers (is, fromHalf);
1575- }
1576-
1577- void readBuffers (std::istream& is, bool /* fromHalf*/ = false )
1578- {
1579- const openvdb::io::StreamMetadata::Ptr meta = openvdb::io::getStreamMetadataPtr (is);
1580- if (!meta) {
1581- OPENVDB_THROW (openvdb::IoError,
1582- " Cannot write out a MultiBufferLeaf without StreamMetadata." );
1583- }
1584-
1585- // clamp pass to 16-bit integer
1586- const uint32_t pass (static_cast <uint16_t >(meta->pass ()));
1587-
1588- // Read in the stored pass number.
1589- uint32_t readPass;
1590- is.read (reinterpret_cast <char *>(&readPass), sizeof (uint32_t ));
1591- EXPECT_EQ (pass, readPass);
1592- // Record the pass number.
1593- mReadPasses .push_back (readPass);
1594-
1595- if (pass == 0 ) {
1596- // Read in the node's origin.
1597- openvdb::Coord origin;
1598- is.read (reinterpret_cast <char *>(&origin), sizeof (openvdb::Coord));
1599- EXPECT_EQ (origin, this ->origin ());
1600- }
1601- }
1602-
1603- void writeBuffers (std::ostream& os, bool /* toHalf*/ = false ) const
1604- {
1605- const openvdb::io::StreamMetadata::Ptr meta = openvdb::io::getStreamMetadataPtr (os);
1606- if (!meta) {
1607- OPENVDB_THROW (openvdb::IoError,
1608- " Cannot read in a MultiBufferLeaf without StreamMetadata." );
1609- }
1610-
1611- // clamp pass to 16-bit integer
1612- const uint32_t pass (static_cast <uint16_t >(meta->pass ()));
1613-
1614- // Leaf traversal analysis deduces the number of passes to perform for this leaf
1615- // then updates the leaf traversal value to ensure all passes will be written.
1616- if (meta->countingPasses ()) {
1617- if (mNumPasses > pass) meta->setPass (mNumPasses );
1618- return ;
1619- }
1620-
1621- // Record the pass number.
1622- EXPECT_TRUE (mWritePassesPtr );
1623- const_cast <std::vector<int >&>(*mWritePassesPtr ).push_back (pass);
1624-
1625- // Write out the pass number.
1626- os.write (reinterpret_cast <const char *>(&pass), sizeof (uint32_t ));
1627- if (pass == 0 ) {
1628- // Write out the node's origin and the pass number.
1629- const auto origin = this ->origin ();
1630- os.write (reinterpret_cast <const char *>(&origin), sizeof (openvdb::Coord));
1631- }
1632- }
1633-
1634-
1635- uint32_t mNumPasses = 0 ;
1636- // Pointer to external vector in which to record passes as they are written
1637- std::vector<int >* mWritePassesPtr = nullptr ;
1638- // Vector in which to record passes as they are read
1639- // (this needs to be internal, because leaf nodes are constructed as a grid is read)
1640- std::vector<int > mReadPasses ;
1641- }; // struct MultiPassLeafNode
1642-
1643- } // anonymous namespace
1644-
1645-
1646- TEST_F (TestFile, testMultiPassIO)
1647- {
1648- using namespace openvdb ;
1649-
1650- openvdb::initialize ();
1651- MultiPassGrid::registerGrid ();
1652-
1653- // Create a multi-buffer grid.
1654- const MultiPassGrid::Ptr grid = openvdb::createGrid<MultiPassGrid>();
1655- grid->setName (" test" );
1656- grid->setTransform (math::Transform::createLinearTransform (1.0 ));
1657- MultiPassGrid::TreeType& tree = grid->tree ();
1658- tree.setValue (Coord (0 , 0 , 0 ), 5 );
1659- tree.setValue (Coord (0 , 10 , 0 ), 5 );
1660- EXPECT_EQ (2 , int (tree.leafCount ()));
1661-
1662- const GridPtrVec grids{grid};
1663-
1664- // Vector in which to record pass numbers (to ensure blocked ordering)
1665- std::vector<int > writePasses;
1666- {
1667- // Specify the required number of I/O passes for each leaf node.
1668- MultiPassGrid::TreeType::LeafIter leafIter = tree.beginLeaf ();
1669- leafIter->mNumPasses = 3 ;
1670- leafIter->mWritePassesPtr = &writePasses;
1671- ++leafIter;
1672- leafIter->mNumPasses = 2 ;
1673- leafIter->mWritePassesPtr = &writePasses;
1674- }
1675-
1676- const char * filename = " testMultiPassIO.vdb" ;
1677- SharedPtr<const char > scopedFile (filename, ::remove);
1678- {
1679- // Verify that passes are written to a file in the correct order.
1680- io::File (filename).write (grids);
1681- EXPECT_EQ (6 , int (writePasses.size ()));
1682- EXPECT_EQ (0 , writePasses[0 ]); // leaf 0
1683- EXPECT_EQ (0 , writePasses[1 ]); // leaf 1
1684- EXPECT_EQ (1 , writePasses[2 ]); // leaf 0
1685- EXPECT_EQ (1 , writePasses[3 ]); // leaf 1
1686- EXPECT_EQ (2 , writePasses[4 ]); // leaf 0
1687- EXPECT_EQ (2 , writePasses[5 ]); // leaf 1
1688- }
1689- {
1690- // Verify that passes are read in the correct order.
1691- io::File file (filename);
1692- file.open ();
1693- const auto newGrid = GridBase::grid<MultiPassGrid>(file.readGrid (" test" ));
1694-
1695- auto leafIter = newGrid->tree ().beginLeaf ();
1696- EXPECT_EQ (3 , int (leafIter->mReadPasses .size ()));
1697- EXPECT_EQ (0 , leafIter->mReadPasses [0 ]);
1698- EXPECT_EQ (1 , leafIter->mReadPasses [1 ]);
1699- EXPECT_EQ (2 , leafIter->mReadPasses [2 ]);
1700- ++leafIter;
1701- EXPECT_EQ (3 , int (leafIter->mReadPasses .size ()));
1702- EXPECT_EQ (0 , leafIter->mReadPasses [0 ]);
1703- EXPECT_EQ (1 , leafIter->mReadPasses [1 ]);
1704- EXPECT_EQ (2 , leafIter->mReadPasses [2 ]);
1705- }
1706- {
1707- // Verify that when using multi-pass and bbox clipping that each leaf node
1708- // is still being read before being clipped
1709- io::File file (filename);
1710- file.open ();
1711- const auto newGrid = GridBase::grid<MultiPassGrid>(
1712- file.readGrid (" test" , BBoxd (Vec3d (0 ), Vec3d (1 ))));
1713- EXPECT_EQ (Index64 (1 ), newGrid->tree ().leafCount ());
1714-
1715- auto leafIter = newGrid->tree ().beginLeaf ();
1716- EXPECT_EQ (3 , int (leafIter->mReadPasses .size ()));
1717- EXPECT_EQ (0 , leafIter->mReadPasses [0 ]);
1718- EXPECT_EQ (1 , leafIter->mReadPasses [1 ]);
1719- EXPECT_EQ (2 , leafIter->mReadPasses [2 ]);
1720- ++leafIter;
1721- EXPECT_TRUE (!leafIter); // second leaf node has now been clipped
1722- }
1723-
1724- // Clear the pass data.
1725- writePasses.clear ();
1726-
1727- {
1728- // Verify that passes are written to and read from a non-seekable stream
1729- // in the correct order.
1730- std::ostringstream ostr (std::ios_base::binary);
1731- io::Stream (ostr).write (grids);
1732-
1733- EXPECT_EQ (6 , int (writePasses.size ()));
1734- EXPECT_EQ (0 , writePasses[0 ]); // leaf 0
1735- EXPECT_EQ (0 , writePasses[1 ]); // leaf 1
1736- EXPECT_EQ (1 , writePasses[2 ]); // leaf 0
1737- EXPECT_EQ (1 , writePasses[3 ]); // leaf 1
1738- EXPECT_EQ (2 , writePasses[4 ]); // leaf 0
1739- EXPECT_EQ (2 , writePasses[5 ]); // leaf 1
1740-
1741- std::istringstream is (ostr.str (), std::ios_base::binary);
1742- io::Stream strm (is);
1743- const auto streamedGrids = strm.getGrids ();
1744- EXPECT_EQ (1 , int (streamedGrids->size ()));
1745-
1746- const auto newGrid = gridPtrCast<MultiPassGrid>(*streamedGrids->begin ());
1747- EXPECT_TRUE (bool (newGrid));
1748- auto leafIter = newGrid->tree ().beginLeaf ();
1749- EXPECT_EQ (3 , int (leafIter->mReadPasses .size ()));
1750- EXPECT_EQ (0 , leafIter->mReadPasses [0 ]);
1751- EXPECT_EQ (1 , leafIter->mReadPasses [1 ]);
1752- EXPECT_EQ (2 , leafIter->mReadPasses [2 ]);
1753- ++leafIter;
1754- EXPECT_EQ (3 , int (leafIter->mReadPasses .size ()));
1755- EXPECT_EQ (0 , leafIter->mReadPasses [0 ]);
1756- EXPECT_EQ (1 , leafIter->mReadPasses [1 ]);
1757- EXPECT_EQ (2 , leafIter->mReadPasses [2 ]);
1758- }
1759- }
1760-
1761-
1762- // //////////////////////////////////////
1763-
1764-
17651525TEST_F (TestFile, testHasGrid)
17661526{
17671527 using namespace openvdb ;
0 commit comments