Skip to content

Commit

Permalink
[workspace] Use VTK inline namespace
Browse files Browse the repository at this point in the history
TODO(svenevs): computer xfer, create a useful commit message...
  • Loading branch information
svenevs committed Nov 1, 2022
1 parent edb3c0a commit 896847e
Show file tree
Hide file tree
Showing 12 changed files with 240 additions and 238 deletions.
57 changes: 0 additions & 57 deletions geometry/render_gltf_client/internal_render_engine_gltf_client.cc
Original file line number Diff line number Diff line change
Expand Up @@ -169,63 +169,6 @@ std::unique_ptr<RenderEngine> RenderEngineGltfClient::DoClone() const {
new RenderEngineGltfClient(*this));
}

void RenderEngineGltfClient::UpdateViewpoint(
const math::RigidTransformd& X_WC) {
/* The vtkGLTFExporter populates the camera matrix in "nodes" incorrectly in
VTK 9.1.0. It should be providing the inverted modelview transformation
matrix since the "nodes" array is to contain global transformations. See:
https://gitlab.kitware.com/vtk/vtk/-/merge_requests/8883
When VTK is updated, RenderEngineGltfClient::UpdateViewpoint can be deleted
as RenderEngineVtk::UpdateViewpoint will correctly update the transforms on
the cameras. */
#if VTK_VERSION_NUMBER > VTK_VERSION_CHECK(9, 1, 0)
#error "UpdateViewpoint can be removed, modified transform no longer needed."
#endif
/* Build the alternate transform, which consists of both an inversion of the
input transformation as well as a coordinate system inversion. For the
coordinate inversion, we must account for:
1. VTK and drake have inverted Y axis directions.
2. The camera Z axis needs to be pointing in the opposite direction.
RenderEngineVtk::UpdateViewpoint will result in the vtkCamera instance's
SetPosition, SetFocalPoint, and SetViewUp methods being called, followed by
applying the transform from drake. See implementation of vtkCamera in VTK,
the Set{Position,FocalPoint,ViewUp} methods result in the camera internally
recomputing its basis -- users do not have the ability to directly control
the modelview transform. So we engineer a drake transform to pass back to
RenderEngineVtk::UpdateViewpoint that will result in the final vtkCamera
having an inverted modelview transformation than what would be needed to
render so that the vtkGLTFExporter will export the "correct" matrix.
When performing this coordinate-system "hand-change", we seek to invert both
the y and z axes. The way to do this would be to use the identity matrix
with the axes being changed scaled by -1 (the "hand change") and both pre and
post multiply the matrix being changed:
| 1 0 0 0 | | a b c d | | 1 0 0 0 | | a -b -c d |
| 0 -1 0 0 | * | e f g h | * | 0 -1 0 0 | = | -e f g -h |
| 0 0 -1 0 | | i j k l | | 0 0 -1 0 | | -i j k -l |
| 0 0 0 1 | | m n o p | | 0 0 0 1 | | m -n -o p |
which we can build directly, noting that the last row | m -n -o p | will be
| 0 0 0 1 | (homogeneous row) and can therefore be skipped.
NOTE: Use the inverse of RigidTransformd, which will transpose the rotation
and negate the translation rather than doing a full matrix inverse. */
Eigen::Matrix4d hacked_matrix{X_WC.inverse().GetAsMatrix4()};
hacked_matrix(0, 1) *= -1.0; // -b
hacked_matrix(0, 2) *= -1.0; // -c
hacked_matrix(1, 0) *= -1.0; // -e
hacked_matrix(1, 3) *= -1.0; // -h
hacked_matrix(2, 0) *= -1.0; // -i
hacked_matrix(2, 3) *= -1.0; // -l
math::RigidTransformd X_WC_hacked{hacked_matrix};
RenderEngineVtk::UpdateViewpoint(X_WC_hacked);
}

void RenderEngineGltfClient::DoRenderColorImage(
const ColorRenderCamera& camera, ImageRgba8U* color_image_out) const {
const int64_t color_scene_id = GetNextSceneId();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ namespace internal {
/* A RenderEngine that exports
<a href="https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html">glTF
</a> scenes, uploads to a render server, and retrieves the renderings back. */
class RenderEngineGltfClient : public geometry::render::RenderEngineVtk {
class __attribute__((visibility("hidden"))) RenderEngineGltfClient
: public geometry::render::RenderEngineVtk {
public:
/* @name Does not allow copy, move, or assignment */
//@{
Expand All @@ -33,9 +34,6 @@ class RenderEngineGltfClient : public geometry::render::RenderEngineVtk {
RenderEngineGltfClient(const RenderEngineGltfClientParams& parameters =
RenderEngineGltfClientParams());

// TODO(svenevs): Remove when VTK is updated, see implementation for details.
void UpdateViewpoint(const math::RigidTransformd& X_WC) override;

const RenderEngineGltfClientParams& get_params() const {
return render_client_->get_params();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,83 +101,6 @@ TEST_F(RenderEngineGltfClientTest, Clone) {
EXPECT_NE(engine.temp_directory(), clone_engine->temp_directory());
}

// TODO(svenevs): remove when VTK is updated, see implementation for details.
TEST_F(RenderEngineGltfClientTest, UpdateViewpoint) {
RenderEngineGltfClient engine{params_};
const Vector3d translation{0.8, 0.0, 0.5};
const RigidTransformd X_WB(RollPitchYawd{-M_PI * 0.7, 0, M_PI / 2},
translation);

// First, use the RenderEngineVtk::UpdateViewpoint and gather matrices.
engine.RenderEngineVtk::UpdateViewpoint(X_WB);
const Matrix4d vtk_color_mat =
engine.CameraModelViewTransformMatrix(ImageType::kColor);
const Matrix4d vtk_depth_mat =
engine.CameraModelViewTransformMatrix(ImageType::kDepth);
const Matrix4d vtk_label_mat =
engine.CameraModelViewTransformMatrix(ImageType::kLabel);

// Use the RenderEngineGltfClient::UpdateViewpoint and gather new matrices.
engine.UpdateViewpoint(X_WB);
const Matrix4d gltf_color_mat =
engine.CameraModelViewTransformMatrix(ImageType::kColor);
const Matrix4d gltf_depth_mat =
engine.CameraModelViewTransformMatrix(ImageType::kDepth);
const Matrix4d gltf_label_mat =
engine.CameraModelViewTransformMatrix(ImageType::kLabel);

/* A ModelView transform can be inverted directly by inverting the rotation
via transpose, and using this inverted rotation to rotate the negated
translation. We do not need to be concerned about non-uniform scaling on the
diagonal or the bottom row. */
auto transform_inverse = [](const Eigen::Matrix4d& mat) {
Matrix4d inverse{mat};
// Invert the rotation via transpose.
inverse.topLeftCorner<3, 3>().transposeInPlace();
// Rotate the inverted translation.
const Vector3d t = inverse.topRightCorner<3, 1>();
const Vector3d t_inv = inverse.topLeftCorner<3, 3>() * (-t);
inverse.topRightCorner<3, 1>() = t_inv;
return inverse;
};
auto compare = [&](const Matrix4d& vtk, const Matrix4d& gltf) {
constexpr double tolerance = 1e-9;

/* We expect that the MVT from RenderEngineVtk and RenderEngineGltfClient
the inverse of one another. The RenderEngineGltfClient::UpdateViewpoint
method engineers a hacked matrix to result in the effect of
RenderEngineVtk::UpdateViewpoint modifying the underlying vtkCamera to
produce the inverted matrix. This is because the vtkGLTFExporter was
incorrectly exporting the vtkCamera's ModelViewTransformMatrix, which
transforms objects in the world into the view of the camera. The inverse
of this matrix is what was supposed to be exported, since the "nodes" array
in glTF is for world coordinate transforms. */
// Compare the rotations.
const Matrix4d vtk_inv = transform_inverse(vtk);
const Matrix3d R_vtk_inv = vtk_inv.topLeftCorner<3, 3>();
const Matrix3d R_gltf = gltf.topLeftCorner<3, 3>();
EXPECT_TRUE(R_vtk_inv.isApprox(R_gltf, tolerance))
<< "Rotation matrices not similar enough:\nR_vtk_inv:\n"
<< R_vtk_inv << "\nR_gltf:\n"
<< R_gltf << '\n';

// Compare the translations.
const Vector3d t_vtk_inv = vtk_inv.topRightCorner<3, 1>();
const Vector3d t_gltf = gltf.topRightCorner<3, 1>();
EXPECT_TRUE(t_vtk_inv.isApprox(t_gltf, tolerance))
<< "Translation vectors not similar enough:\nt_vtk_inv:\n"
<< t_vtk_inv << "\nt_gltf:\n"
<< t_gltf << '\n';

// For posterity, compare the homogeneous row.
const Vector4d gltf_homogeneous = gltf.bottomRightCorner<1, 4>();
EXPECT_EQ(gltf_homogeneous, Vector4d(0, 0, 0, 1));
};
compare(vtk_color_mat, gltf_color_mat);
compare(vtk_depth_mat, gltf_depth_mat);
compare(vtk_label_mat, gltf_label_mat);
}

class FakeServer : public HttpService {
public:
FakeServer() = default;
Expand Down
7 changes: 4 additions & 3 deletions geometry/render_vtk/internal_render_engine_vtk.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ struct ModuleInitVtkRenderingOpenGL2 {
// See also shaders::kDepthFS, this is where the variables are used.
// For the detail of VTK's callback mechanism, please refer to:
// https://www.vtk.org/doc/nightly/html/classvtkCommand.html#details
class ShaderCallback : public vtkCommand {
class __attribute__((visibility("hidden"))) ShaderCallback
: public vtkCommand {
public:
DRAKE_DEFAULT_COPY_AND_MOVE_AND_ASSIGN(ShaderCallback);

Expand Down Expand Up @@ -89,8 +90,8 @@ enum ImageType {
#endif // !DRAKE_DOXYGEN_CXX

/** See documentation of MakeRenderEngineVtk(). */
class RenderEngineVtk : public RenderEngine,
private internal::ModuleInitVtkRenderingOpenGL2 {
class __attribute__((visibility("hidden"))) RenderEngineVtk
: public RenderEngine, private internal::ModuleInitVtkRenderingOpenGL2 {
public:
/** @name Does not allow copy, move, or assignment */
//@{
Expand Down
4 changes: 2 additions & 2 deletions tools/workspace/vtk/build_binaries_with_docker
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,5 @@ rm -f vtk-*.tar.gz{,.sha256}
build focal --build-arg PLATFORM=ubuntu:20.04
extract focal

build jammy --build-arg PLATFORM=ubuntu:22.04
extract jammy
# build jammy --build-arg PLATFORM=ubuntu:22.04
# extract jammy
85 changes: 85 additions & 0 deletions tools/workspace/vtk/build_mac_binary
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
#!/bin/bash

# This shell script and some files in vtk/image (for docker) are used by
# the project maintainers to create the precompiled vtk binaries that are
# downloaded during the build. They are neither called during the build nor
# expected to be called by most developers or users of the project.

set -euxo pipefail

if ! command -v xcrun >/dev/null 2>&1; then
echo '`xcrun` command not found, is Xcode installed?' >&2
exit 1
fi

macosx_sysroot="$(xcrun -sdk macosx -show-sdk-path)"
# TODO(svenevs): this should fail if it points to "command line tools"
# Must point to Contents/Developer under an Xcode.app like folder.

this_file_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
vtk_args_path="${this_file_dir}/image/vtk-args"

if ! [[ -f "${vtk_args_path}" ]]; then
echo "Could not find 'vtk-args' file ${vtk_args_path}." >&2
exit 1
fi

# See also: image/build-vtk.sh. Extract all CMake / VTK configure arguments
# from image/vtk-args, accumulating with `-D` in front for use on the command
# line removing any comment lines that start with '#'.
index=0
vtk_cmake_args=()
while IFS='' read -r line || [[ -n "${line}" ]]; do
arg="$(sed -e '/^#/d' -e 's/^/-D/' <<< "${line}")"
# If the line was commented out, arg will be the empty string.
if ! [[ -z "${arg}" ]]; then
vtk_cmake_args[index++]="${arg}"
fi
done < "${vtk_args_path}"
vtk_cmake_args+=("-DVTK_USE_COCOA:BOOL=ON")

# TODO(svenevs): unify this with image/build-vtk.sh.
readonly VTK_VERSION="d706250a1422ae1e7ece0fa09a510186769a5fec"

# Directory to contain our source and build trees.
container="${this_file_dir}/mac_binary_build"
build_dir="${container}/build"
install_dir="${container}/install"
rm -rf "${container}"
mkdir -p "${container}"
cd "${container}"

git clone https://gitlab.kitware.com/vtk/vtk.git src
src_dir="${container}/src"
git -C "${src_dir}" checkout "${VTK_VERSION}"

# TODO(svenevs): macOS install rpath concerns.
# -DCMAKE_INSTALL_NAME_DIR:STRING=/opt/homebrew/Cellar/vtk@9.1.0/9.1.0_4/lib
# -DCMAKE_INSTALL_RPATH:STRING=/opt/homebrew/Cellar/vtk@9.1.0/9.1.0_4/lib
cmake \
-G Ninja \
-Wno-dev \
-DCMAKE_INSTALL_PREFIX="${install_dir}" \
-DCMAKE_BUILD_TYPE:STRING=Release \
-DCMAKE_CXX_STANDARD:STRING=20 \
"-DCMAKE_OSX_ARCHITECTURES:STRING='$(arch)'" \
-DCMAKE_INSTALL_LIBDIR=lib \
-DCMAKE_FIND_FRAMEWORK=LAST \
-DCMAKE_OSX_SYSROOT="${macosx_sysroot}" \
-DCMAKE_C_COMPILER="$(xcrun -sdk macosx -find gcc)" \
-DCMAKE_CXX_COMPILER="$(xcrun -sdk macosx -find g++)" \
"${vtk_cmake_args[@]}" \
-B "${build_dir}" \
-S "${src_dir}"

cd "${build_dir}"
ninja install/strip

readonly archive=drake-vtk-mac.tar.gz
cd "${install_dir}"

tar czf "${archive}" -- *
shasum --algorithm 256 "${archive}" | tee "${archive}.sha256"

mv "${archive}" "${this_file_dir}"
mv "${archive}.sha256" "${this_file_dir}"
4 changes: 4 additions & 0 deletions tools/workspace/vtk/find_vtk_headers.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
"vtkRenderingCore",
"vtkRenderingContext2D",
"vtkRenderingFreeType",
"vtkRenderingHyperTreeGrid",
"vtkRenderingOpenGL2",
"vtkRenderingSceneGraph",
"vtkRenderingUI",
Expand Down Expand Up @@ -103,6 +104,7 @@
"vtkRenderingCore": Path("Rendering") / "Core",
"vtkRenderingContext2D": Path("Rendering") / "Context2D",
"vtkRenderingFreeType": Path("Rendering") / "FreeType",
"vtkRenderingHyperTreeGrid": Path("Rendering") / "HyperTreeGrid",
"vtkRenderingOpenGL2": Path("Rendering") / "OpenGL2",
"vtkRenderingSceneGraph": Path("Rendering") / "SceneGraph",
"vtkRenderingUI": Path("Rendering") / "UI",
Expand Down Expand Up @@ -145,6 +147,8 @@ def main():
required=True,
)
parser.add_argument("--debug", action="store_true")
# TODO(svenevs): add ability to dump all headers for all modules to find a
# header when the module name is not known.
parser.add_argument(
"module", type=str, help="VTK module to parse.", choices=VTK_MODULES
)
Expand Down
29 changes: 24 additions & 5 deletions tools/workspace/vtk/image/build-vtk.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,39 @@

set -eu -o pipefail

readonly VTK_VERSION=9.1.0
# Can be a branch, tag, or commit (e.g., 'v9.1.0').
readonly VTK_VERSION="d706250a1422ae1e7ece0fa09a510186769a5fec"

mkdir -p /vtk
cd /vtk

git clone \
--branch v${VTK_VERSION} --depth 1 \
https://gitlab.kitware.com/vtk/vtk.git src
git clone https://gitlab.kitware.com/vtk/vtk.git src
git -C src checkout "${VTK_VERSION}"

mkdir -p /vtk/build
cd /vtk/build

mapfile -t VTK_CMAKE_ARGS < <(sed -e '/^#/d' -e 's/^/-D/' < /vtk/vtk-args)

cmake "${VTK_CMAKE_ARGS[@]}" -GNinja -Wno-dev /vtk/src
codename="$(lsb_release -cs)"
if [[ "${codename}" == "focal" ]]; then
cxx_std="17"
else # "${code_name}" := "jammy"
cxx_std="20"
fi

cmake \
-G Ninja \
-Wno-dev \
-DCMAKE_INSTALL_PREFIX:PATH=/opt/vtk \
-DCMAKE_BUILD_TYPE:STRING=Release \
"-DCMAKE_CXX_STANDARD:STRING=${cxx_std}" \
-DCMAKE_C_FLAGS:STRING='-D_FORTIFY_SOURCE=2 -fstack-protector-strong -Wno-deprecated-declarations' \
-DCMAKE_CXX_FLAGS:STRING='-D_FORTIFY_SOURCE=2 -fstack-protector-strong -Wno-deprecated-declarations' \
-DCMAKE_EXE_LINKER_FLAGS:STRING='-Wl,-Bsymbolic-functions -Wl,-z,now -Wl,-z,relro' \
-DCMAKE_MODULE_LINKER_FLAGS:STRING='-Wl,-Bsymbolic-functions -Wl,-z,now -Wl,-z,relro' \
-DCMAKE_SHARED_LINKER_FLAGS:STRING='-Wl,-Bsymbolic-functions -Wl,-z,now -Wl,-z,relro' \
"${VTK_CMAKE_ARGS[@]}" \
/vtk/src

ninja install/strip
8 changes: 4 additions & 4 deletions tools/workspace/vtk/image/package.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
set -eu -o pipefail

# Get various version numbers.
readonly vtk_tag=vtk-9.1.0
readonly vtk_tag=vtk-9.2.0
# To re-package, increase build_number by 1 and update repository.bzl to avoid
# overwriting artifacts thus breaking historical builds.
readonly build_number=3
readonly build_number=1
readonly platform=$(lsb_release --codename --short)-$(uname --processor)

# Create archive named:
Expand All @@ -17,5 +17,5 @@ readonly platform=$(lsb_release --codename --short)-$(uname --processor)
readonly archive=${vtk_tag}-${build_number}-${platform}.tar.gz
cd /opt/vtk

tar czf $archive -- *
shasum --algorithm 256 $archive | tee $archive.sha256
tar czf "${archive}" -- *
shasum --algorithm 256 "${archive}" | tee "${archive}.sha256"
1 change: 1 addition & 0 deletions tools/workspace/vtk/image/prereqs
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,6 @@ libxt-dev
lsb-release
ninja-build
python-is-python3
sqlite3
wget
zlib1g-dev
Loading

0 comments on commit 896847e

Please sign in to comment.