Welcome to mirror list, hosted at ThFree Co, Russian Federation.

3DScene.cpp « GUI « slic3r « src « xs - github.com/supermerill/SuperSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 5f61b37b3c10763db1604abadf58e1601558eaa9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
#include "3DScene.hpp"

namespace Slic3r {

// caller is responsible for supplying NO lines with zero length
void
_3DScene::_extrusionentity_to_verts_do(const Lines &lines, const std::vector<double> &widths,
        const std::vector<double> &heights, bool closed, double top_z, const Point &copy,
        GLVertexArray* qverts, GLVertexArray* tverts)
{
    /* It looks like it's faster without reserving capacity...
    // each segment has 4 quads, thus 16 vertices; + 2 caps
    qverts->reserve_more(3 * 4 * (4 * lines.size() + 2));
    
    // two triangles for each corner
    tverts->reserve_more(3 * 3 * 2 * (lines.size() + 1));
    */
    
    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 (size_t 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();
        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
                    tverts->push_norm(prev_xy_right_normal);
                    tverts->push_vert(prev_b1.x, prev_b1.y, middle_z);
            
                    // use the normal going to the right calculated for this line
                    tverts->push_norm(xy_right_normal);
                    tverts->push_vert(a1.x, a1.y, middle_z);
            
                    // normal going upwards
                    tverts->push_norm(0,0,1);
                    tverts->push_vert(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
                    tverts->push_norm(prev_xy_right_normal);
                    tverts->push_vert(prev_b1.x, prev_b1.y, middle_z);
            
                    // normal going downwards
                    tverts->push_norm(0,0,-1);
                    tverts->push_vert(a.x, a.y, bottom_z);
            
                    // use the normal going to the right calculated for this line
                    tverts->push_norm(xy_right_normal);
                    tverts->push_vert(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
                    tverts->push_norm(prev_xy_left_normal);
                    tverts->push_vert(prev_b2.x, prev_b2.y, middle_z);
            
                    // normal going upwards
                    tverts->push_norm(0,0,1);
                    tverts->push_vert(a.x, a.y, top_z);
            
                    // use the normal going to the right calculated for this line
                    tverts->push_norm(xy_left_normal);
                    tverts->push_vert(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
                    tverts->push_norm(prev_xy_left_normal);
                    tverts->push_vert(prev_b2.x, prev_b2.y, middle_z);
            
                    // use the normal going to the right calculated for this line
                    tverts->push_norm(xy_left_normal);
                    tverts->push_vert(a2.x, a2.y, middle_z);
            
                    // normal going downwards
                    tverts->push_norm(0,0,-1);
                    tverts->push_vert(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
                qverts->push_norm(0,0,-1);
                qverts->push_vert(a.x, a.y, bottom_z);
            
                // normal pointing to the right
                qverts->push_norm(xy_right_normal);
                qverts->push_vert(a1.x, a1.y, middle_z);
            
                // normal pointing upwards
                qverts->push_norm(0,0,1);
                qverts->push_vert(a.x, a.y, top_z);
            
                // normal pointing to the left
                qverts->push_norm(xy_left_normal);
                qverts->push_vert(a2.x, a2.y, middle_z);
            }
            // we don't use 'else' because both cases are true if we have only one line
            if (i == lines.size()-1) {
                // normal pointing downwards
                qverts->push_norm(0,0,-1);
                qverts->push_vert(b.x, b.y, bottom_z);
            
                // normal pointing to the left
                qverts->push_norm(xy_left_normal);
                qverts->push_vert(b2.x, b2.y, middle_z);
            
                // normal pointing upwards
                qverts->push_norm(0,0,1);
                qverts->push_vert(b.x, b.y, top_z);
            
                // normal pointing to the right
                qverts->push_norm(xy_right_normal);
                qverts->push_vert(b1.x, b1.y, middle_z);
            }
        }
        
        // bottom-right face
        {
            // normal going downwards
            qverts->push_norm(0,0,-1);
            qverts->push_norm(0,0,-1);
            qverts->push_vert(a.x, a.y, bottom_z);
            qverts->push_vert(b.x, b.y, bottom_z);
            
            qverts->push_norm(xy_right_normal);
            qverts->push_norm(xy_right_normal);
            qverts->push_vert(b1.x, b1.y, middle_z);
            qverts->push_vert(a1.x, a1.y, middle_z);
        }
        
        // top-right face
        {
            qverts->push_norm(xy_right_normal);
            qverts->push_norm(xy_right_normal);
            qverts->push_vert(a1.x, a1.y, middle_z);
            qverts->push_vert(b1.x, b1.y, middle_z);
            
            // normal going upwards
            qverts->push_norm(0,0,1);
            qverts->push_norm(0,0,1);
            qverts->push_vert(b.x, b.y, top_z);
            qverts->push_vert(a.x, a.y, top_z);
        }
         
        // top-left face
        {
            qverts->push_norm(0,0,1);
            qverts->push_norm(0,0,1);
            qverts->push_vert(a.x, a.y, top_z);
            qverts->push_vert(b.x, b.y, top_z);
            
            qverts->push_norm(xy_left_normal);
            qverts->push_norm(xy_left_normal);
            qverts->push_vert(b2.x, b2.y, middle_z);
            qverts->push_vert(a2.x, a2.y, middle_z);
        }
        
        // bottom-left face
        {
            qverts->push_norm(xy_left_normal);
            qverts->push_norm(xy_left_normal);
            qverts->push_vert(a2.x, a2.y, middle_z);
            qverts->push_vert(b2.x, b2.y, middle_z);
            
            // normal going downwards
            qverts->push_norm(0,0,-1);
            qverts->push_norm(0,0,-1);
            qverts->push_vert(b.x, b.y, bottom_z);
            qverts->push_vert(a.x, a.y, bottom_z);
        }
        
        first_done = true;
    }
}

void
GLVertexArray::load_mesh(const TriangleMesh &mesh)
{
    this->reserve_more(3 * 3 * mesh.facets_count());
    
    for (int i = 0; i < mesh.stl.stats.number_of_facets; ++i) {
        stl_facet &facet = mesh.stl.facet_start[i];
        for (int j = 0; j <= 2; ++j) {
            this->push_norm(facet.normal.x, facet.normal.y, facet.normal.z);
            this->push_vert(facet.vertex[j].x, facet.vertex[j].y, facet.vertex[j].z);
        }
    }
}

#ifdef SLIC3RXS
REGISTER_CLASS(GLVertexArray, "GUI::_3DScene::GLVertexArray");
#endif

}