Skip to content

Commit

Permalink
add python tutorials
Browse files Browse the repository at this point in the history
  • Loading branch information
LiangliangNan committed Dec 31, 2024
1 parent d5ef7da commit c573d40
Show file tree
Hide file tree
Showing 10 changed files with 161 additions and 4 deletions.
14 changes: 14 additions & 0 deletions python/bindings/easy3d/core/types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,20 @@

void bind_easy3d_core_types(pybind11::module_& m)
{
// easy3d::geom::bounding_box(const std::vector<easy3d::vec3> &) file:easy3d/core/types.h line:179
m.def("bounding_box", [](const std::vector<easy3d::vec3> &points) {
return easy3d::geom::bounding_box<easy3d::Box3, std::vector<easy3d::vec3> >(points);
}, pybind11::arg("points"),
R"doc(
Compute the bounding box of a set of points.
Parameters:
points (List[vec3]): A list of 3D points.
Returns:
box3: The computed bounding box.
)doc");

// easy3d::geom::orthogonal(const class easy3d::Vec<3, float> &) file:easy3d/core/types.h line:163
m.def("orthogonal", (class easy3d::Vec<3, float> (*)(const class easy3d::Vec<3, float> &)) &easy3d::geom::orthogonal, "Returns a vector orthogonal to v. Its norm() depends on v, but is zero only for a null v.\n\nC++: easy3d::geom::orthogonal(const class easy3d::Vec<3, float> &) --> class easy3d::Vec<3, float>", pybind11::arg("v"));

Expand Down
12 changes: 9 additions & 3 deletions python/bindings/easy3d/renderer/drawables.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,9 @@ void bind_easy3d_renderer_drawables(pybind11::module_& m)

{ // easy3d::LinesDrawable file:easy3d/renderer/drawable_lines.h line:40
pybind11::class_<easy3d::LinesDrawable, std::shared_ptr<easy3d::LinesDrawable>, PyCallBack_easy3d_LinesDrawable, easy3d::Drawable> cl(m, "LinesDrawable", "The drawable for rendering a set of line segments, e.g., edges of a mesh, vector fields\n \n\n\n \n PointsDrawable, TrianglesDrawable");
cl.def( pybind11::init( [](PyCallBack_easy3d_LinesDrawable const &o){ return new PyCallBack_easy3d_LinesDrawable(o); } ) );
cl.def( pybind11::init( [](){ return new easy3d::LinesDrawable(); } ) );
cl.def( pybind11::init( [](const std::string& name){ return new easy3d::LinesDrawable(name); } ) );
cl.def( pybind11::init( [](PyCallBack_easy3d_LinesDrawable const &o){ return new PyCallBack_easy3d_LinesDrawable(o); } ) );
cl.def( pybind11::init( [](easy3d::LinesDrawable const &o){ return new easy3d::LinesDrawable(o); } ) );

pybind11::enum_<easy3d::LinesDrawable::ImposterType>(cl, "ImposterType", pybind11::arithmetic(), "")
Expand All @@ -239,7 +241,9 @@ void bind_easy3d_renderer_drawables(pybind11::module_& m)
}
{ // easy3d::PointsDrawable file:easy3d/renderer/drawable_points.h line:42
pybind11::class_<easy3d::PointsDrawable, std::shared_ptr<easy3d::PointsDrawable>, PyCallBack_easy3d_PointsDrawable, easy3d::Drawable> cl(m, "PointsDrawable", "The drawable for rendering a set of points, e.g., point clouds, vertices of a mesh.\n \n\n\n \n LinesDrawable, TrianglesDrawable");
cl.def( pybind11::init( [](PyCallBack_easy3d_PointsDrawable const &o){ return new PyCallBack_easy3d_PointsDrawable(o); } ) );
cl.def( pybind11::init( [](){ return new easy3d::PointsDrawable(); } ) );
cl.def( pybind11::init( [](const std::string& name){ return new easy3d::PointsDrawable(name); } ) );
cl.def( pybind11::init( [](PyCallBack_easy3d_PointsDrawable const &o){ return new PyCallBack_easy3d_PointsDrawable(o); } ) );
cl.def( pybind11::init( [](easy3d::PointsDrawable const &o){ return new easy3d::PointsDrawable(o); } ) );

pybind11::enum_<easy3d::PointsDrawable::ImposterType>(cl, "ImposterType", pybind11::arithmetic(), "")
Expand All @@ -257,7 +261,9 @@ void bind_easy3d_renderer_drawables(pybind11::module_& m)
}
{ // easy3d::TrianglesDrawable file:easy3d/renderer/drawable_triangles.h line:46
pybind11::class_<easy3d::TrianglesDrawable, std::shared_ptr<easy3d::TrianglesDrawable>, PyCallBack_easy3d_TrianglesDrawable, easy3d::Drawable> cl(m, "TrianglesDrawable", "The drawable for rendering a set of triangles, e.g., the surface of a triangular mesh.\n \n\n\n \n LinesDrawable, PointsDrawable\n\n \n TrianglesDrawable supports triangles only. Visualizing general polygons typically requires tessellating\n the faces into a set of triangles (using Tessellator or any other methods). Vertex coordinates and properties\n (e.g., color, normal) must be provided as consecutive triplets in an array to be transferred to GPU.\n See Drawable::update_vertex_buffer().");
cl.def( pybind11::init( [](PyCallBack_easy3d_TrianglesDrawable const &o){ return new PyCallBack_easy3d_TrianglesDrawable(o); } ) );
cl.def( pybind11::init( [](){ return new easy3d::TrianglesDrawable(); } ) );
cl.def( pybind11::init( [](const std::string& name){ return new easy3d::TrianglesDrawable(name); } ) );
cl.def( pybind11::init( [](PyCallBack_easy3d_TrianglesDrawable const &o){ return new PyCallBack_easy3d_TrianglesDrawable(o); } ) );
cl.def( pybind11::init( [](easy3d::TrianglesDrawable const &o){ return new easy3d::TrianglesDrawable(o); } ) );
cl.def("type", (enum easy3d::Drawable::Type (easy3d::TrianglesDrawable::*)() const) &easy3d::TrianglesDrawable::type, "C++: easy3d::TrianglesDrawable::type() const --> enum easy3d::Drawable::Type");
cl.def("smooth_shading", (bool (easy3d::TrianglesDrawable::*)() const) &easy3d::TrianglesDrawable::smooth_shading, "C++: easy3d::TrianglesDrawable::smooth_shading() const --> bool");
Expand Down
8 changes: 8 additions & 0 deletions python/bindings/easy3d/util/resource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <memory>

#include <pybind11/pybind11.h>
#include <pybind11/stl.h>

#ifndef BINDER_PYBIND11_TYPE_CASTER
#define BINDER_PYBIND11_TYPE_CASTER
Expand All @@ -20,4 +21,11 @@ void bind_easy3d_util_resource(pybind11::module_& m)
// easy3d::resource::directory() file:easy3d/util/resource.h line:48
m.def("directory", (std::string (*)()) &easy3d::resource::directory, "Returns the resource directory (containing color maps, shaders, textures, fonts, etc.)\n\nC++: easy3d::resource::directory() --> std::string");

// The vertices of a bunny model.
// easy3d::resource::bunny_vertices file:easy3d/util/resource.h line:53
m.attr("bunny_vertices") = &easy3d::resource::bunny_vertices;

// The triangle faces of a bunny model. Each consecutive 3 values denote the vertex indices of a triangle.
// easy3d::resource::bunny_indices file:easy3d/util/resource.h line:56
m.attr("bunny_indices") = &easy3d::resource::bunny_indices;
}
13 changes: 13 additions & 0 deletions python/bindings/easy3d/viewer/viewer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -522,6 +522,19 @@ void bind_easy3d_viewer_viewer(pybind11::module_& m)
pybind11::return_value_policy::reference_internal,
"Add an existing polyhedral mesh to the viewer."
);
cl.def("add_drawable", [](easy3d::Viewer &self, std::shared_ptr<easy3d::Drawable> drawable) {
return self.add_drawable(drawable); // Call the C++ function
}, pybind11::arg("drawable"),
pybind11::return_value_policy::reference_internal,
R"doc(
Add a drawable to the viewer to be visualized.
Parameters:
drawable (Drawable): The pointer to the drawable.
Returns:
Drawable: The pointer of the drawable added to the viewer.
)doc");
cl.def("models", (const class std::vector<class easy3d::Model *> & (easy3d::Viewer::*)() const) &easy3d::Viewer::models, "Query the models managed by this viewer.\n \n\n The models managed by this viewer.\n\nC++: easy3d::Viewer::models() const --> const class std::vector<class easy3d::Model *> &", pybind11::return_value_policy::automatic);
cl.def("drawables", (const class std::vector<class easy3d::Drawable *> & (easy3d::Viewer::*)() const) &easy3d::Viewer::drawables, "Query the drawables managed by this viewer.\n \n\n The drawables managed by this viewer.\n\nC++: easy3d::Viewer::drawables() const --> const class std::vector<class easy3d::Drawable *> &", pybind11::return_value_policy::automatic);
cl.def("clear_scene", (void (easy3d::Viewer::*)()) &easy3d::Viewer::clear_scene, "Delete all visual contents of the viewer (all models and drawables).\n\nC++: easy3d::Viewer::clear_scene() --> void");
Expand Down
116 changes: 116 additions & 0 deletions python/tutorials/tutorial_202_drawables.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
# -------------------------------------------------------------------------------
# Tutorial: Using Drawables in Easy3D
# -------------------------------------------------------------------------------
# This tutorial demonstrates how to visualize 3D data using Easy3D's drawables
# without explicitly defining a 3D model. We'll cover:
# 1. Visualizing a surface model using `TrianglesDrawable`.
# 2. Visualizing points with `PointsDrawable`.
# 3. Visualizing bounding boxes using `LinesDrawable`.
# 4. Understanding and configuring drawables for specific rendering purposes.
# 5. Running the Easy3D Viewer to display the visualizations.
# -------------------------------------------------------------------------------

# -------------------------------------------------------------------------------
# Adding Easy3D Python Bindings to the System Path
# -------------------------------------------------------------------------------
# This is required if the bindings are not installed via `pip` but are located in
# a local build directory. For building and installing Python bindings of Easy3D,
# please refer to: https://github.com/LiangliangNan/Easy3D/blob/main/ReadMe.md
# -------------------------------------------------------------------------------
import sys
sys.path.append("../../cmake-build-release/lib/python")

# Importing necessary libraries
import easy3d # Easy3D library for 3D visualization and processing

# -------------------------------------------------------------------------------
# Initializing Easy3D
# -------------------------------------------------------------------------------
# The `easy3d.initialize(False)` function initializes the Easy3D library.
# Use `True` to enable detailed logging, which is useful for debugging.
easy3d.initialize(False)

# Create a Viewer instance
# -------------------------------------------------------------------------------
viewer = easy3d.Viewer("Easy3D Viewer - Drawables")
viewer.set_usage("") # Optionally set usage information for the viewer

# Load 3D data
# -------------------------------------------------------------------------------
# Easy3D provides some predefined models, such as the Stanford Bunny.
# Here, we load the Bunny's vertex positions (`bunny_vertices`) and triangle face
# indices (`bunny_indices`).
points = easy3d.bunny_vertices # Vertex coordinates
indices = easy3d.bunny_indices # Triangle face indices

# Visualize the Bunny surface using `TrianglesDrawable`
# -------------------------------------------------------------------------------
# `TrianglesDrawable` is used to render triangular meshes. We upload the vertex
# positions and indices of the Bunny model for visualization.

# Create a `TrianglesDrawable` named "faces"
surface = easy3d.TrianglesDrawable("faces")
surface.update_vertex_buffer(points) # Upload vertex positions
surface.update_element_buffer(indices) # Upload triangle indices
viewer.add_drawable(surface) # Add the drawable to the viewer

# Visualize the Bunny vertices using `PointsDrawable`
# -------------------------------------------------------------------------------
# `PointsDrawable` is used to render point clouds. We upload the Bunny's vertices
# and configure their appearance (e.g., color, size).

# Create a `PointsDrawable` named "vertices"
vertices = easy3d.PointsDrawable("vertices")
vertices.update_vertex_buffer(points) # Upload vertex positions
vertices.set_uniform_coloring(easy3d.vec4(1.0, 0.0, 0.0, 1.0)) # Set color to red
vertices.set_impostor_type(easy3d.PointsDrawable.SPHERE) # Render points as spheres
vertices.set_point_size(10) # Set point size
viewer.add_drawable(vertices) # Add the drawable to the viewer

# Compute the bounding box of the Bunny model
# -------------------------------------------------------------------------------
# The `bounding_box` function computes the axis-aligned bounding box (AABB) of
# a set of points. We'll use this to render a bounding box around the Bunny.

# Compute the bounding box
bbox = easy3d.bounding_box(points)
# Retrieve the min and max coordinates of the bounding box
min_point = bbox.min_point()
max_point = bbox.max_point()

# Define the 8 corner points of the bounding box
bbox_points = [
easy3d.vec3(min_point.x, min_point.y, max_point.z),
easy3d.vec3(max_point.x, min_point.y, max_point.z),
easy3d.vec3(min_point.x, max_point.y, max_point.z),
easy3d.vec3(max_point.x, max_point.y, max_point.z),
easy3d.vec3(min_point.x, min_point.y, min_point.z),
easy3d.vec3(max_point.x, min_point.y, min_point.z),
easy3d.vec3(min_point.x, max_point.y, min_point.z),
easy3d.vec3(max_point.x, max_point.y, min_point.z),
]

# Define the indices of the lines that connect the bounding box corners
bbox_indices = [
0, 1, 2, 3, 4, 5, 6, 7, # Lines connecting top and bottom
0, 2, 4, 6, 1, 3, 5, 7, # Lines connecting vertical edges
0, 4, 2, 6, 1, 5, 3, 7 # Lines connecting horizontal edges
]

# Visualize the bounding box using `LinesDrawable`
# -------------------------------------------------------------------------------
# `LinesDrawable` is used to render lines. We upload the bounding box corners
# and the indices of the lines connecting them.

# Create a `LinesDrawable` named "bbox"
bbox_drawable = easy3d.LinesDrawable("bbox")
bbox_drawable.update_vertex_buffer(bbox_points) # Upload corner points
bbox_drawable.update_element_buffer(bbox_indices) # Upload line indices
bbox_drawable.set_uniform_coloring(easy3d.vec4(0.0, 0.0, 1.0, 1.0)) # Set color to blue
bbox_drawable.set_line_width(5.0) # Set line width
viewer.add_drawable(bbox_drawable) # Add the drawable to the viewer

# Run the viewer
# -------------------------------------------------------------------------------
# The `viewer.run()` function launches the GUI window for visualization.
viewer.run()
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion python/tutorials/tutorial_401_mesh_sampler.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
# -----------------------------------------------------------------------------
# Setting Up the Multi-View Viewer
# -----------------------------------------------------------------------------
# See detailed explanations in "python/tutorials/tutorial_203_multiview.py"
# See detailed explanations in "python/tutorials/tutorial_204_multiview.py"

# Create a MultiViewer instance with 1 row and 2 columns.
viewer = easy3d.MultiViewer(1, 2, "Easy3D Viewer - Mesh sampling")
Expand Down

0 comments on commit c573d40

Please sign in to comment.