RobinTrace
RobinTrace documentation

RobinTrace is a sequential raytracing API for optical design. It is implemented in C++.

Scope

RobinTrace aims at a minimal set of features which make it a usable tool for optical design raytracing. Note this is not a standalone optical design program but rather a toolkit for the raytracing involved in optical design. The scope may be summarized as follows.

  • Minimal: RobinTrace deals with sequential raytracing. Matters of assessing optical performance from ray states are higher level and out of the scope.
  • A toolkit: RobinTrace is an API for raytracing bundles of rays through optical parts sequences and report the ray states along the way. The user is expected to be able to retrieve the data for their own purposes. The user is expected to be familiar with C++ and optical design both.
  • Efficient: The runtime execution should be fast. We aim at an execution speed comparable to the speed of commercial tools (at least the same order of magnitude in execution speed). A set of benchmarking tests is in place to monitor the performance.

API layers

We decomposed the program into three layers of ascending abstraction.

  • Poaky: Poaky is the lowest layer. It defines individual rays and the operations which can be applied on these rays. It contains many mathematical definitions such as algorithms for ray operations and shapes used in raytracing. As such, it comes with a heavy paper documentation.
  • Pinyo: Pinyo is the layer of abstraction on top of Poaky. It defines ray bundles and low-level optical parts (eg a refractive shape, a transfer part) which operate on ray bundles. The operations of parts on bundles of rays are an opportunity to define fine-grained ray error cases management.
  • Pewit: Pewit is the highest layer in the raytracer. It defines sequences of low-level optical parts and a stateful object lseq holding the raytracing. The lseq object holds the sequence of parts, the ray bundles being raytraced through the sequence and a buffer for saving intermediate ray states. It manages the application of parts one by one on the ray bundles.

Example

Here is an example which shows some of the API in bottom-up fashion.

#include <iostream>
#include <vector>
#include <memory>
#include "robintrace.h"
int main(){
std::cout << "# Main #" << std::endl;
std::cout << "## Poaky ##" << std::endl;
ray r (Vec3(0.2, 0.3, 0.0), Vec3(0, 0, 1.0));
std::cout << "ray is valid? " << r.is_valid() << std::endl;
standard sd (1.0/20, -2);
std::cout << sd << std::endl;
std::cout << "ray before intersection: " << r << std::endl;
sd.intersect(r);
std::cout << "ray after intersection: " << r << std::endl;
Vec3 N = sd.normal(r);
std::cout << "normal vector: " << N << std::endl;
transfer tfr;
std::cout << tfr << std::endl;
std::cout << "## Pinyo ##" << std::endl;
// bun
std::vector<ray> rays;
ray r1(Vec3(0.2, 0.3 , 0), Vec3(0, 0, 1));
ray r2(Vec3(0.21, 0.31, 0), Vec3(0, 0, 1));
rays.push_back(r1); rays.push_back(r2);
bun b (rays);
std::cout << "Before transfer: " << b << std::endl;
// transfer_part
transfer_part trfp(transfer(Vec3(0.01, 0, 0)));
std::cout << trfp << std::endl;
trfp.apply(b);
std::cout << "After transfer: " << b << std::endl;
// Standard reflective part
standard sd2 (1.0/20, -2);
std::cout << srp << std::endl;
srp.apply(b);
std::cout << "After standard reflective part: " << b << std::endl;
std::cout << "## Pewit ##" << std::endl;
transfer_part trfp2(transfer(Vec3(0.01, 0, 0)));
shape_reflect_part srp2(standard(1.0/20, -2));
lpart_vec parts;
parts.add_lpart(trfp2);
parts.add_lpart(srp2);
lseq ls(parts);
std::vector<ray> rays_ls;
ray r1_ls(Vec3(0.2, 0.3 , 0), Vec3(0, 0, 1));
ray r2_ls(Vec3(0.21, 0.31, 0), Vec3(0, 0, 1));
rays_ls.push_back(r1_ls); rays_ls.push_back(r2_ls);
bun b_ls(rays_ls);
bun b2_ls(b_ls);
ray_pack ray_buns;
ray_buns.push_back(b_ls);
ray_buns.push_back(b2_ls);
ls.inputs.add(lseq_rays(ray_buns));
ls.parts.at(0).save_rays = true;
ls.parts.at(1).save_rays = true;
ls.trace_remaining();
auto rays_surf0 = ls.parts.at(0).results.get<lseq_part_rays>();
auto rays_surf1 = ls.parts.at(1).results.get<lseq_part_rays>();
std::cout << rays_surf0.ray_buns << std::endl;
std::cout << rays_surf1.ray_buns << std::endl;
// Compute part global position.
ls.compute_parts_global_position();
std::cout << ls.parts.at(1).results.get<lseq_part_global_position>()
<< std::endl;
// Compute part semi-diameter.
ls.parts.at(1).compute_semi_diameter();
auto sdia = ls.parts.at(1).results.get<lseq_part_semi_diameter>();
std::cout << "Semi-diameter: " << sdia.value << std::endl;
// Compute rays in global coordinates
ls.parts.at(1).compute_global_rays();
auto global_rays = ls.parts.at(1).results.get<lseq_part_global_rays>();
std::cout << "Global rays of part 1: " << std::endl
<< global_rays.ray_buns << std::endl;
// Compute the local rays propagation direction.
ls.parts.at(1).compute_propagation_direction();
const auto &propagation_direction =
ls.parts.at(1).results.get<lseq_part_propagation_direction>();
std::cout << "Local rays propagation direction at part 1: "
<< propagation_direction.direction << " "
<< propagation_direction.validity << std::endl;
}
Eigen::Vector3d Vec3
Definition: Vec3.h:11
Class for ray bundles.
Definition: bun.h:13
Vector of lparts.
Definition: lpart_vec.h:12
void add_lpart(T part)
Add a lpart to the vector.
Definition: lpart_vec.h:21
The global coordinates position of a lseq renderable part.
Definition: lseq_part_global_position.h:9
Saved ray states at a lseq part expressed in global coordinates.
Definition: lseq_part_global_rays.h:9
ray_pack ray_buns
Ray states.
Definition: lseq_part_global_rays.h:12
Propagation direction of the lseq_part_rays.
Definition: lseq_part_propagation_direction.h:8
bool direction
The propagation direction of the rays.
Definition: lseq_part_propagation_direction.h:13
Saved ray states at a lseq part.
Definition: lseq_part_rays.h:9
ray_pack ray_buns
Saved ray states.
Definition: lseq_part_rays.h:12
Part semi-diameter from the ray states results.
Definition: lseq_part_semi_diameter.h:8
double value
The semi-diameter value.
Definition: lseq_part_semi_diameter.h:11
Input rays to lseq.
Definition: lseq_rays.h:9
Top-level API for robintrace. Holds parts, rays and manages the computations.
Definition: lseq.h:16
Class for individual rays.
Definition: ray.h:9
Class template implementing the specialized lparts for reflective shape parts.
Definition: shape_part.h:11
Standard shape specialization.
Definition: standard.h:9
Part which applies a transfer operation to rays.
Definition: transfer_part.h:9
Transfer operation over a ray.
Definition: transfer.h:40
std::vector< bun > ray_pack
Vector of ray bundles.
Definition: ray_pack.h:12