diff --git a/scenes/extrudes.fart b/scenes/extrudes.fart index 80106d4..08275c9 100644 --- a/scenes/extrudes.fart +++ b/scenes/extrudes.fart @@ -41,13 +41,13 @@ scene } offset 3 material { color <1, 0.7, 0> } - translate <-2, 0, 0> + translate <-3, 0, 0> } extrude { ngon 5, 2 offset 1 - translate <2, 0, 0> + translate <4, 0, 0> } } diff --git a/shapes/Extrude.cc b/shapes/Extrude.cc index 04d9dde..6bf5ebc 100644 --- a/shapes/Extrude.cc +++ b/shapes/Extrude.cc @@ -35,33 +35,41 @@ Shape::IntersectionList Extrude::intersect(refptr _this, const Ray & ray) { Ray ray_inv = m_inverse.transform_ray(ray); IntersectionList res; + int n_polygons = m_polygons.size(); + int n_offsets = m_offsets.size(); - int n_polygons = m_polygons.size(), n_offsets = m_offsets.size(); + if (n_polygons < 1 || n_offsets < 1) + return res; + + double distance = 0.0; + Vector scale(1.0, 1.0, 1.0); + Vector shift(0.0, 0.0, 0.0); for (int p = 0; p < n_polygons; p++) { refptr polygon = m_polygons[p]; - double distance = 0.0; - Vector scale(1.0, 1.0, 1.0); - Vector shift(0.0, 0.0, 0.0); for (int o = 0; o < n_offsets; o++) { Offset & offset = m_offsets[o]; for (int pt = 0, n_pts = polygon->size(); pt < n_pts; pt++) { - Vector p1 = *(*polygon)[pt] * scale + shift; - Vector p2 = *(*polygon)[(pt+1) % n_pts] * scale + shift; - Vector p3 = *(*polygon)[(pt+1) % n_pts] - * offset.scale + offset.shift; - Vector p4 = *(*polygon)[pt] * offset.scale + offset.shift; - p3[2] += offset.distance; - p4[2] += offset.distance; + Vector p1 = scale.mult(*(*polygon)[pt]) + shift; + Vector p2 = scale.mult(*(*polygon)[(pt+1) % n_pts]) + shift; + Vector p3 = scale.mult(offset.scale) + .mult(*(*polygon)[(pt+1) % n_pts]) + + shift + offset.shift; + Vector p4 = scale.mult(offset.scale).mult(*(*polygon)[pt]) + + shift + offset.shift; + p1[2] += distance; + p2[2] += distance; + p3[2] += distance + offset.distance; + p4[2] += distance + offset.distance; Vector e1 = p2 - p1; Vector e2 = p3 - p2; Vector normal = (e1 * e2).normalize(); - double a = normal[0], b = normal[1], c = normal[2]; - double d = -a * p1[0] - b * p1[1] - c * p1[2]; if (ray_inv.getDirection() % normal < 0) /* skip backfaces */ { + double a = normal[0], b = normal[1], c = normal[2]; + double d = -(a * p1[0] + b * p1[1] + c * p1[2]); LinearSolver solver( a * ray_inv.getDirection()[0] + b * ray_inv.getDirection()[1] + c * ray_inv.getDirection()[2], @@ -85,8 +93,70 @@ Shape::IntersectionList Extrude::intersect(refptr _this, const Ray & ray) } } distance += offset.distance; - scale = offset.scale; - shift = offset.shift; + scale = scale.mult(offset.scale); + shift += offset.shift; + } + } + + double a = 0, b = 0, c = -1.0, d = 0.0; + if (ray_inv.getDirection() % Vector(a, b, c) < 0) + { + LinearSolver solver( a * ray_inv.getDirection()[0] + + b * ray_inv.getDirection()[1] + + c * ray_inv.getDirection()[2], + a * ray_inv.getOrigin()[0] + + b * ray_inv.getOrigin()[1] + + c * ray_inv.getOrigin()[2] + + d); + Solver::Result solutions = solver.solve(); + if (solutions.numResults > 0 && solutions.results[0] > 0.0) + { + Vector ipoint = ray_inv[solutions.results[0]]; + for (int p = 0; p < n_polygons; p++) + { + refptr polygon = m_polygons[p]; + if (polygon->containsPoint(ipoint)) + { + res.add(Intersection(_this, + m_transform.transform_point(ipoint), + m_transform.transform_normal(Vector(a, b, c)))); + } + } + } + } + if (scale[0] > 0.0 && scale[1] > 0.0) + { + a = 0, b = 0, c = 1.0, d = distance; + if (ray_inv.getDirection() % Vector(a, b, c) < 0) + { + LinearSolver solver( a * ray_inv.getDirection()[0] + + b * ray_inv.getDirection()[1] + + c * ray_inv.getDirection()[2], + a * ray_inv.getOrigin()[0] + + b * ray_inv.getOrigin()[1] + + c * ray_inv.getOrigin()[2] + + d); + Solver::Result solutions = solver.solve(); + if (solutions.numResults > 0 && solutions.results[0] > 0.0) + { + Vector ipoint = ray_inv[solutions.results[0]]; + for (int p = 0; p < n_polygons; p++) + { + Polygon tp = *m_polygons[p]; + for (int i = 0, sz = tp.size(); i < sz; i++) + { + tp[i] = new Vector(tp[i]->mult(scale) + shift); + (*tp[i])[2] += distance; + } + if (tp.containsPoint(ipoint)) + { + res.add(Intersection(_this, + m_transform.transform_point(ipoint), + m_transform.transform_normal(Vector(a, b, c)))); + break; + } + } + } } }