#include "3DScene.hpp" namespace Slic3r { void _3DScene::_extrusionentity_to_verts_do(const Lines &lines, const std::vector &widths, const std::vector &heights, bool closed, double top_z, const Point ©, Pointf3s* qverts, Pointf3s* qnorms, Pointf3s* tverts, Pointf3s* tnorms) { Line prev_line; Pointf prev_b1, prev_b2; Vectorf3 prev_xy_left_normal, prev_xy_right_normal; // loop once more in case of closed loops bool first_done = false; for (int i = 0; i <= lines.size(); ++i) { if (i == lines.size()) i = 0; const Line &line = lines.at(i); if (i == 0 && first_done && !closed) break; double len = line.length(); if (len == 0) continue; double unscaled_len = unscale(len); double bottom_z = top_z - heights.at(i); double middle_z = (top_z + bottom_z) / 2; double dist = widths.at(i)/2; // scaled Vectorf v = Vectorf::new_unscale(line.vector()); v.scale(1/unscaled_len); Pointf a = Pointf::new_unscale(line.a); Pointf b = Pointf::new_unscale(line.b); Pointf a1 = a; Pointf a2 = a; a1.translate(+dist*v.y, -dist*v.x); a2.translate(-dist*v.y, +dist*v.x); Pointf b1 = b; Pointf b2 = b; b1.translate(+dist*v.y, -dist*v.x); b2.translate(-dist*v.y, +dist*v.x); // calculate new XY normals Vector n = line.normal(); Vectorf3 xy_right_normal = Vectorf3::new_unscale(n.x, n.y, 0); xy_right_normal.scale(1/unscaled_len); Vectorf3 xy_left_normal = xy_right_normal; xy_left_normal.scale(-1); if (first_done) { // if we're making a ccw turn, draw the triangles on the right side, otherwise draw them on the left side double ccw = line.b.ccw(prev_line); if (ccw > EPSILON) { // top-right vertex triangle between previous line and this one { // use the normal going to the right calculated for the previous line tnorms->push_back(prev_xy_right_normal); tverts->push_back(Pointf3(prev_b1.x, prev_b1.y, middle_z)); // use the normal going to the right calculated for this line tnorms->push_back(xy_right_normal); tverts->push_back(Pointf3(a1.x, a1.y, middle_z)); // normal going upwards tnorms->push_back(Pointf3(0,0,1)); tverts->push_back(Pointf3(a.x, a.y, top_z)); } // bottom-right vertex triangle between previous line and this one { // use the normal going to the right calculated for the previous line tnorms->push_back(prev_xy_right_normal); tverts->push_back(Pointf3(prev_b1.x, prev_b1.y, middle_z)); // normal going downwards tnorms->push_back(Pointf3(0,0,-1)); tverts->push_back(Pointf3(a.x, a.y, bottom_z)); // use the normal going to the right calculated for this line tnorms->push_back(xy_right_normal); tverts->push_back(Pointf3(a1.x, a1.y, middle_z)); } } else if (ccw < -EPSILON) { // top-left vertex triangle between previous line and this one { // use the normal going to the left calculated for the previous line tnorms->push_back(prev_xy_left_normal); tverts->push_back(Pointf3(prev_b2.x, prev_b2.y, middle_z)); // normal going upwards tnorms->push_back(Pointf3(0,0,1)); tverts->push_back(Pointf3(a.x, a.y, top_z)); // use the normal going to the right calculated for this line tnorms->push_back(xy_left_normal); tverts->push_back(Pointf3(a2.x, a2.y, middle_z)); } // bottom-left vertex triangle between previous line and this one { // use the normal going to the left calculated for the previous line tnorms->push_back(prev_xy_left_normal); tverts->push_back(Pointf3(prev_b2.x, prev_b2.y, middle_z)); // use the normal going to the right calculated for this line tnorms->push_back(xy_left_normal); tverts->push_back(Pointf3(a2.x, a2.y, middle_z)); // normal going downwards tnorms->push_back(Pointf3(0,0,-1)); tverts->push_back(Pointf3(a.x, a.y, bottom_z)); } } } // if this was the extra iteration we were only interested in the triangles if (first_done && i == 0) break; prev_line = line; prev_b1 = b1; prev_b2 = b2; prev_xy_right_normal = xy_right_normal; prev_xy_left_normal = xy_left_normal; if (!closed) { // terminate open paths with caps if (i == 0) { // normal pointing downwards qnorms->push_back(Pointf3(0,0,-1)); qverts->push_back(Pointf3(a.x, a.y, bottom_z)); // normal pointing to the right qnorms->push_back(xy_right_normal); qverts->push_back(Pointf3(a1.x, a1.y, middle_z)); // normal pointing upwards qnorms->push_back(Pointf3(0,0,1)); qverts->push_back(Pointf3(a.x, a.y, top_z)); // normal pointing to the left qnorms->push_back(xy_left_normal); qverts->push_back(Pointf3(a2.x, a2.y, middle_z)); } else if (i == lines.size()-1) { // normal pointing downwards qnorms->push_back(Pointf3(0,0,-1)); qverts->push_back(Pointf3(b.x, b.y, bottom_z)); // normal pointing to the left qnorms->push_back(xy_left_normal); qverts->push_back(Pointf3(b2.x, b2.y, middle_z)); // normal pointing upwards qnorms->push_back(Pointf3(0,0,1)); qverts->push_back(Pointf3(b.x, b.y, top_z)); // normal pointing to the right qnorms->push_back(xy_right_normal); qverts->push_back(Pointf3(b1.x, b1.y, middle_z)); } } // bottom-right face { // normal going downwards qnorms->push_back(Pointf3(0,0,-1)); qnorms->push_back(Pointf3(0,0,-1)); qverts->push_back(Pointf3(a.x, a.y, bottom_z)); qverts->push_back(Pointf3(b.x, b.y, bottom_z)); qnorms->push_back(xy_right_normal); qnorms->push_back(xy_right_normal); qverts->push_back(Pointf3(b1.x, b1.y, middle_z)); qverts->push_back(Pointf3(a1.x, a1.y, middle_z)); } // top-right face { qnorms->push_back(xy_right_normal); qnorms->push_back(xy_right_normal); qverts->push_back(Pointf3(a1.x, a1.y, middle_z)); qverts->push_back(Pointf3(b1.x, b1.y, middle_z)); // normal going upwards qnorms->push_back(Pointf3(0,0,1)); qnorms->push_back(Pointf3(0,0,1)); qverts->push_back(Pointf3(b.x, b.y, top_z)); qverts->push_back(Pointf3(a.x, a.y, top_z)); } // top-left face { qnorms->push_back(Pointf3(0,0,1)); qnorms->push_back(Pointf3(0,0,1)); qverts->push_back(Pointf3(a.x, a.y, top_z)); qverts->push_back(Pointf3(b.x, b.y, top_z)); qnorms->push_back(xy_left_normal); qnorms->push_back(xy_left_normal); qverts->push_back(Pointf3(b2.x, b2.y, middle_z)); qverts->push_back(Pointf3(a2.x, a2.y, middle_z)); } // bottom-left face { qnorms->push_back(xy_left_normal); qnorms->push_back(xy_left_normal); qverts->push_back(Pointf3(a2.x, a2.y, middle_z)); qverts->push_back(Pointf3(b2.x, b2.y, middle_z)); // normal going downwards qnorms->push_back(Pointf3(0,0,-1)); qnorms->push_back(Pointf3(0,0,-1)); qverts->push_back(Pointf3(b.x, b.y, bottom_z)); qverts->push_back(Pointf3(a.x, a.y, bottom_z)); } first_done = true; } } }