I'm in the middle of converting some existing C++ code to Rust (for educational purpose). The crate I'm trying to build is based on the Physically Based Rendering book (PBRT - http://www.pbrt.org).
Let me start with a link to a part of the current documentation for this crate: pbrt - Rust
While a natural representation would be to have a Triangle shape implementation where each triangle stored the positions of its three vertices, a more memory-efficient representation is to separately store entire triangle meshes with an array of vertex positions where each individual triangle just stores three offsets into this array for its three vertices.
And show some of the relevant C++ code:
// Triangle Declarations
struct TriangleMesh {
// TriangleMesh Public Methods
TriangleMesh(const Transform &ObjectToWorld, int nTriangles,
const int *vertexIndices, int nVertices, const Point3f *P,
const Vector3f *S, const Normal3f *N, const Point2f *uv,
const std::shared_ptr<Texture<Float>> &alphaMask,
const std::shared_ptr<Texture<Float>> &shadowAlphaMask);
// TriangleMesh Data
const int nTriangles, nVertices;
std::vector<int> vertexIndices;
std::unique_ptr<Point3f[]> p;
std::unique_ptr<Normal3f[]> n;
std::unique_ptr<Vector3f[]> s;
std::unique_ptr<Point2f[]> uv;
std::shared_ptr<Texture<Float>> alphaMask, shadowAlphaMask;
};
class Triangle : public Shape {
public:
// Triangle Public Methods
Triangle(const Transform *ObjectToWorld, const Transform *WorldToObject,
bool reverseOrientation, const std::shared_ptr<TriangleMesh> &mesh,
int triNumber)
: Shape(ObjectToWorld, WorldToObject, reverseOrientation), mesh(mesh) {
v = &mesh->vertexIndices[3 * triNumber];
triMeshBytes += sizeof(*this);
}
...
private:
...
// Triangle Private Data
std::shared_ptr<TriangleMesh> mesh;
const int *v;
};
If you want to have a peek at the current Rust code, it is here: GitHub - wahn/rs_pbrt: Rust crate to implement a counterpart to the PBRT book's (3rd edition) C++ code. See also https://www.rs-pbrt.org/about ...
Maybe the example code from pbrt_spheres_differentials_texfilt.rs
is most relevant for the questions I have:
...
let triangle_mesh: Arc<TriangleMesh> = Arc::new(TriangleMesh::new(object_to_world,
world_to_object,
false,
false,
n_triangles,
vertex_indices,
n_vertices,
p_ws, // in world space
s, // empty
n, // empty
uv));
let mut tris: Vec<Triangle> = Vec::new();
for i in 0..n_triangles {
tris.push(Triangle::new(object_to_world,
world_to_object,
false,
triangle_mesh.clone(),
i));
}
println!("tris = {:?}", tris);
If you clone the repository and compile the examples and create ...
cargo test --release
... you can run the resulting example:
./target/release/examples/pbrt_spheres_differentials_texfilt
From the output you will see that I try to create 2 triangles:
n_triangles = 2
With 4 vertices:
n_vertices = 4
p_ws = [Point3 { x: -99.75, y: -1, z: -100 }, ... }]
The TriangleMesh is supposed to hold all the relevant data, and the Triangle to keep a thread-safe reference-counting pointer.
So my question are related to the following two C++ lines:
std::shared_ptr<TriangleMesh> mesh;
const int *v;
I decided already about the mesh
pointer:
pub struct Triangle {
mesh: Arc<TriangleMesh>,
}
Question 1: Is this the right decision?
Question 2: What should the v pointer translate to?
I think a slice could be a possible answer. It always would contain three indices into p: Vec<Point3f>
from the (shared) TriangleMesh:
tris = [Triangle { mesh: TriangleMesh { n_triangles: 2, vertex_indices: [0, 2, 1, 0, 3, 2], n_vertices: 4, p: [Point3 {...}, ...] ...]
So that print of a vector of two triangles would somehow look like this:
tris = [Triangle { mesh: ..., v: [0, 2, 1] }, Triangle { mesh: ..., v: [0, 3, 2] }]
Can you help me with this? Am I going down the correct route? How would the definition of v look like? I'm assuming I will run into lifetimes syntax problems, but I rather ask now than investing too much time into a direction I should have avoided ...
Thanks. I would appreciate all comments on the current decisions I made. If you want to look at the C++ counter part, here is the C++ code: