Skip to content

Commit

Permalink
Cleanup to possibly support better point and line intersection (#1257)
Browse files Browse the repository at this point in the history
  • Loading branch information
xelatihy authored Jul 6, 2021
1 parent 07c22ff commit 3bf2506
Show file tree
Hide file tree
Showing 19 changed files with 427 additions and 16 deletions.
117 changes: 114 additions & 3 deletions libs/yocto/yocto_geometry.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,9 @@ inline bbox3f triangle_bounds(
const vec3f& p0, const vec3f& p1, const vec3f& p2);
inline bbox3f quad_bounds(
const vec3f& p0, const vec3f& p1, const vec3f& p2, const vec3f& p3);
inline bbox3f sphere_bounds(const vec3f& p, float r);
inline bbox3f capsule_bounds(
const vec3f& p0, const vec3f& p1, float r0, float r1);

} // namespace yocto

Expand All @@ -176,14 +179,19 @@ inline bbox3f quad_bounds(
namespace yocto {

// Line properties.
inline vec3f line_point(const vec3f& p0, const vec3f& p1, float u);
inline vec3f line_tangent(const vec3f& p0, const vec3f& p1);
inline float line_length(const vec3f& p0, const vec3f& p1);

// Triangle properties.
inline vec3f triangle_point(
const vec3f& p0, const vec3f& p1, const vec3f& p2, const vec2f& uv);
inline vec3f triangle_normal(const vec3f& p0, const vec3f& p1, const vec3f& p2);
inline float triangle_area(const vec3f& p0, const vec3f& p1, const vec3f& p2);

// Quad propeties.
// Quad properties.
inline vec3f quad_point(
const vec3f& p0, const vec3f& p1, const vec3f& p2, const vec2f& uv);
inline vec3f quad_normal(
const vec3f& p0, const vec3f& p1, const vec3f& p2, const vec3f& p3);
inline float quad_area(
Expand Down Expand Up @@ -221,12 +229,28 @@ inline T interpolate_quad(
template <typename T>
inline T interpolate_bezier(
const T& p0, const T& p1, const T& p2, const T& p3, float u);
// Computes the derivative of a cubic Bezier segment parametrized by u.

// Computes the derivative of a cubic Bezier segment parametrized by u.
template <typename T>
inline T interpolate_bezier_derivative(
const T& p0, const T& p1, const T& p2, const T& p3, float u);

// Interpolated line properties.
inline vec3f line_point(const vec3f& p0, const vec3f& p1, float u);
inline vec3f line_tangent(const vec3f& t0, const vec3f& t1, float u);

// Interpolated triangle properties.
inline vec3f triangle_point(
const vec3f& p0, const vec3f& p1, const vec3f& p2, const vec2f& uv);
inline vec3f triangle_normal(
const vec3f& n0, const vec3f& n1, const vec3f& n2, const vec2f& uv);

// Interpolated quad properties.
inline vec3f quad_point(const vec3f& p0, const vec3f& p1, const vec3f& p2,
const vec3f& p3, const vec2f& uv);
inline vec3f quad_normal(const vec3f& n0, const vec3f& n1, const vec3f& n2,
const vec3f& n3, const vec2f& uv);

} // namespace yocto

// -----------------------------------------------------------------------------
Expand Down Expand Up @@ -453,6 +477,11 @@ inline bbox3f quad_bounds(
const vec3f& p0, const vec3f& p1, const vec3f& p2, const vec3f& p3) {
return {min(p0, min(p1, min(p2, p3))), max(p0, max(p1, max(p2, p3)))};
}
inline bbox3f sphere_bounds(const vec3f& p, float r) { return {p - r, p + r}; }
inline bbox3f capsule_bounds(
const vec3f& p0, const vec3f& p1, float r0, float r1) {
return {min(p0 - r0, p1 - r1), max(p0 + r0, p1 + r1)};
}

} // namespace yocto

Expand Down Expand Up @@ -527,6 +556,52 @@ inline T interpolate_bezier_derivative(
(p3 - p2) * 3 * u * u;
}

// Interpolated line properties.
inline vec3f line_point(const vec3f& p0, const vec3f& p1, float u) {
return p0 * (1 - u) + p1 * u;
}
inline vec3f line_tangent(const vec3f& t0, const vec3f& t1, float u) {
return normalize(t0 * (1 - u) + t1 * u);
}

// Interpolated triangle properties.
inline vec3f triangle_point(
const vec3f& p0, const vec3f& p1, const vec3f& p2, const vec2f& uv) {
return p0 * (1 - uv.x - uv.y) + p1 * uv.x + p2 * uv.y;
}
inline vec3f triangle_normal(
const vec3f& n0, const vec3f& n1, const vec3f& n2, const vec2f& uv) {
return normalize(n0 * (1 - uv.x - uv.y) + n1 * uv.x + n2 * uv.y);
}

// Interpolated quad properties.
inline vec3f quad_point(const vec3f& p0, const vec3f& p1, const vec3f& p2,
const vec3f& p3, const vec2f& uv) {
if (uv.x + uv.y <= 1) {
return triangle_point(p0, p1, p3, uv);
} else {
return triangle_point(p2, p3, p1, 1 - uv);
}
}
inline vec3f quad_normal(const vec3f& n0, const vec3f& n1, const vec3f& n2,
const vec3f& n3, const vec2f& uv) {
if (uv.x + uv.y <= 1) {
return triangle_normal(n0, n1, n3, uv);
} else {
return triangle_normal(n2, n3, n1, 1 - uv);
}
}

// Interpolated sphere properties.
inline vec3f sphere_point(const vec3f p, float r, const vec2f& uv) {
return p + r * vec3f{cos(uv.x * 2 * pif) * sin(uv.y * pif),
sin(uv.x * 2 * pif) * sin(uv.y * pif), cos(uv.y * pif)};
}
inline vec3f sphere_normal(const vec3f p, float r, const vec2f& uv) {
return normalize(vec3f{cos(uv.x * 2 * pif) * sin(uv.y * pif),
sin(uv.x * 2 * pif) * sin(uv.y * pif), cos(uv.y * pif)});
}

// Triangle tangent and bitangent from uv
inline pair<vec3f, vec3f> triangle_tangents_fromuv(const vec3f& p0,
const vec3f& p1, const vec3f& p2, const vec2f& uv0, const vec2f& uv1,
Expand Down Expand Up @@ -567,7 +642,7 @@ inline pair<vec3f, vec3f> quad_tangents_fromuv(const vec3f& p0, const vec3f& p1,
} // namespace yocto

// -----------------------------------------------------------------------------
// IMPLEMENRTATION OF USER INTERFACE UTILITIES
// IMPLEMENTATION OF USER INTERFACE UTILITIES
// -----------------------------------------------------------------------------
namespace yocto {

Expand Down Expand Up @@ -671,6 +746,42 @@ inline bool intersect_line(const ray3f& ray, const vec3f& p0, const vec3f& p1,
return true;
}

// Intersect a ray with a sphere
inline bool intersect_sphere(
const ray3f& ray, const vec3f& p, float r, vec2f& uv, float& dist) {
// compute parameters
auto a = dot(ray.d, ray.d);
auto b = 2 * dot(ray.o - p, ray.d);
auto c = dot(ray.o - p, ray.o - p) - r * r;

// check discriminant
auto dis = b * b - 4 * a * c;
if (dis < 0) return false;

// compute ray parameter
auto t = (-b - sqrt(dis)) / (2 * a);

// exit if not within bounds
if (t < ray.tmin || t > ray.tmax) return false;

// try other ray parameter
t = (-b + sqrt(dis)) / (2 * a);

// exit if not within bounds
if (t < ray.tmin || t > ray.tmax) return false;

// compute local point for uvs
auto plocal = ((ray.o + ray.d * t) - p) / r;
auto u = atan2(plocal.y, plocal.x) / (2 * pif);
if (u < 0) u += 1;
auto v = acos(clamp(plocal.z, -1.0f, 1.0f)) / pif;

// intersection occurred: set params and exit
uv = {u, v};
dist = t;
return true;
}

// Intersect a ray with a triangle
inline bool intersect_triangle(const ray3f& ray, const vec3f& p0,
const vec3f& p1, const vec3f& p2, vec2f& uv, float& dist) {
Expand Down
41 changes: 36 additions & 5 deletions libs/yocto/yocto_scene.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ vec3f eval_tangent(const shape_data& shape, int element, const vec2f& uv) {
}

vec2f eval_texcoord(const shape_data& shape, int element, const vec2f& uv) {
if (shape.texcoords.empty()) return {0, 0};
if (shape.texcoords.empty()) return uv;
if (!shape.points.empty()) {
auto& point = shape.points[element];
return shape.texcoords[point];
Expand All @@ -343,7 +343,7 @@ vec2f eval_texcoord(const shape_data& shape, int element, const vec2f& uv) {
return interpolate_quad(shape.texcoords[quad.x], shape.texcoords[quad.y],
shape.texcoords[quad.z], shape.texcoords[quad.w], uv);
} else {
return {0, 0};
return uv;
}
}

Expand Down Expand Up @@ -591,13 +591,13 @@ vec3f eval_normal(const fvshape_data& shape, int element, const vec2f& uv) {
}

vec2f eval_texcoord(const fvshape_data& shape, int element, const vec2f& uv) {
if (shape.texcoords.empty()) return {0, 0};
if (shape.texcoords.empty()) return uv;
if (!shape.quadspos.empty()) {
auto& quad = shape.quadstexcoord[element];
return interpolate_quad(shape.texcoords[quad.x], shape.texcoords[quad.y],
shape.texcoords[quad.z], shape.texcoords[quad.w], uv);
} else {
return {0, 0};
return uv;
}
}

Expand Down Expand Up @@ -929,6 +929,22 @@ vec3f eval_normalmap(const scene_data& scene, const instance_data& instance,
return normal;
}

// Eval shading position
vec3f eval_shading_position(const scene_data& scene,
const instance_data& instance, int element, const vec2f& uv,
const vec3f& outgoing) {
auto& shape = scene.shapes[instance.shape];
if (!shape.triangles.empty() || !shape.quads.empty()) {
return eval_position(scene, instance, element, uv);
} else if (!shape.lines.empty()) {
return eval_position(scene, instance, element, uv);
} else if (!shape.points.empty()) {
return eval_position(shape, element, uv);
} else {
return {0, 0, 0};
}
}

// Eval shading normal
vec3f eval_shading_normal(const scene_data& scene,
const instance_data& instance, int element, const vec2f& uv,
Expand All @@ -946,7 +962,14 @@ vec3f eval_shading_normal(const scene_data& scene,
auto normal = eval_normal(scene, instance, element, uv);
return orthonormalize(outgoing, normal);
} else if (!shape.points.empty()) {
return outgoing;
// HACK: sphere
if (true) {
return transform_direction(instance.frame,
vec3f{cos(2 * pif * uv.x) * sin(pif * uv.y),
sin(2 * pif * uv.x) * sin(pif * uv.y), cos(pif * uv.y)});
} else {
return outgoing;
}
} else {
return {0, 0, 0};
}
Expand Down Expand Up @@ -1585,6 +1608,14 @@ shape_data make_points(int num, float uvscale, float radius) {
return shape;
}

shape_data make_points(const vec2i& steps, const vec2f& size,
const vec2f& uvscale, const vec2f& radius) {
auto shape = shape_data{};
make_points(shape.points, shape.positions, shape.normals, shape.texcoords,
shape.radius, steps, size, uvscale, radius);
return shape;
}

shape_data make_random_points(
int num, const vec3f& size, float uvscale, float radius, uint64_t seed) {
auto shape = shape_data{};
Expand Down
10 changes: 9 additions & 1 deletion libs/yocto/yocto_scene.h
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,9 @@ pair<vec3f, vec3f> eval_element_tangents(
const scene_data& scene, const instance_data& instance, int element);
vec3f eval_normalmap(const scene_data& scene, const instance_data& instance,
int element, const vec2f& uv);
vec3f eval_shading_position(const scene_data& scene,
const instance_data& instance, int element, const vec2f& uv,
const vec3f& outgoing);
vec3f eval_shading_normal(const scene_data& scene,
const instance_data& instance, int element, const vec2f& uv,
const vec3f& outgoing);
Expand Down Expand Up @@ -549,10 +552,15 @@ shape_data make_lines(const vec2i& steps = {4, 65536},
const vec2f& scale = {1, 1}, const vec2f& uvscale = {1, 1},
const vec2f& radius = {0.001f, 0.001f});

// Make point primitives. Returns points, pos, norm, texcoord, radius.
// Make a point primitive. Returns points, pos, norm, texcoord, radius.
shape_data make_point(float radius = 0.001f);
// Make a point set on a grid. Returns points, pos, norm, texcoord, radius.
shape_data make_points(
int num = 65536, float uvscale = 1, float radius = 0.001f);
shape_data make_points(const vec2i& steps = {256, 256},
const vec2f& size = {1, 1}, const vec2f& uvscale = {1, 1},
const vec2f& radius = {0.001f, 0.001f});
// Make random points in a cube. Returns points, pos, norm, texcoord, radius.
shape_data make_random_points(int num = 65536, const vec3f& size = {1, 1, 1},
float uvscale = 1, float radius = 0.001f, uint64_t seed = 17);

Expand Down
20 changes: 20 additions & 0 deletions libs/yocto/yocto_sceneio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1456,6 +1456,26 @@ shape_data make_shape_preset(const string& type) {
auto shape = make_random_points(4096, {0.075f, 0.075f, 0.075f});
for (auto& p : shape.positions) p += {0, 0.075f, 0};
return shape;
} else if (type == "test-points-grid") {
auto shape = make_points({256, 256}, {0.075f, 0.075f});
for (auto& p : shape.positions) p += {0, 0.075f, 0};
for (auto& r : shape.radius) r *= 0.075f;
return shape;
} else if (type == "test-lines-grid") {
auto shape = make_lines({256, 256}, {0.075f, 0.075f});
for (auto& p : shape.positions) p += {0, 0.075f, 0};
for (auto& r : shape.radius) r *= 0.075f;
return shape;
} else if (type == "test-thickpoints-grid") {
auto shape = make_points({16, 16}, {0.075f, 0.075f});
for (auto& p : shape.positions) p += {0, 0.075f, 0};
for (auto& r : shape.radius) r *= 0.075f * 10;
return shape;
} else if (type == "test-thicklines-grid") {
auto shape = make_lines({16, 16}, {0.075f, 0.075f});
for (auto& p : shape.positions) p += {0, 0.075f, 0};
for (auto& r : shape.radius) r *= 0.075f * 10;
return shape;
} else if (type == "test-particles") {
return make_points(4096);
} else if (type == "test-cloth") {
Expand Down
14 changes: 14 additions & 0 deletions libs/yocto/yocto_shape.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2365,6 +2365,20 @@ void make_points(vector<int>& points, vector<vec3f>& positions,
texcoords[i] = {(float)i / (float)num, 0};
}

// Generate a point set along a quad.
void make_points(vector<int>& points, vector<vec3f>& positions,
vector<vec3f>& normals, vector<vec2f>& texcoords, vector<float>& radius,
const vec2i& steps, const vec2f& size, const vec2f& uvscale,
const vec2f& rad) {
auto quads = vector<vec4i>{};
make_rect(quads, positions, normals, texcoords, steps, size, uvscale);
points.resize(positions.size());
for (auto i = 0; i < (int)positions.size(); i++) points[i] = i;
radius.resize(positions.size());
for (auto i = 0; i < (int)texcoords.size(); i++)
radius[i] = lerp(rad.x, rad.y, texcoords[i].y / uvscale.y);
}

// Generate a point set.
void make_random_points(vector<int>& points, vector<vec3f>& positions,
vector<vec3f>& normals, vector<vec2f>& texcoords, vector<float>& radius,
Expand Down
6 changes: 6 additions & 0 deletions libs/yocto/yocto_shape.h
Original file line number Diff line number Diff line change
Expand Up @@ -621,6 +621,12 @@ void make_points(vector<int>& points, vector<vec3f>& positions,
vector<vec3f>& normals, vector<vec2f>& texcoords, vector<float>& radius,
int num, float uvscale, float point_radius);

// Generate a point set along a quad.
void make_points(vector<int>& points, vector<vec3f>& positions,
vector<vec3f>& normals, vector<vec2f>& texcoords, vector<float>& radius,
const vec2i& steps, const vec2f& size, const vec2f& uvscale,
const vec2f& rad);

// Generate a point set.
void make_random_points(vector<int>& points, vector<vec3f>& positions,
vector<vec3f>& normals, vector<vec2f>& texcoords, vector<float>& radius,
Expand Down
Loading

0 comments on commit 3bf2506

Please sign in to comment.