1 /***************************************************************************
2 * pixel_bit.cpp is part of Math Graphic Library
3 * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin@gmail.ru> *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU Lesser General Public License as *
7 * published by the Free Software Foundation; either version 3 of the *
8 * License, or (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU Lesser General Public *
16 * License along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
20 #include <algorithm>
21 #include "mgl2/canvas.h"
22 #include "mgl2/thread.h"
23 #if MGL_HAVE_OMP
24 #include <omp.h>
25 #endif
26
27 //-----------------------------------------------------------------------------
pxl_primpx(long id,long n,const void *)28 void mglCanvas::pxl_primpx(long id, long n, const void *) // NOTE this variant is too slow ... may be later in CUDA???
29 {
30 mglDrawReg d; d.set(this,1,1,id);
31 #if !MGL_HAVE_PTHREAD
32 #pragma omp parallel for firstprivate(d)
33 #endif
34 for(long ii=0;ii<n;ii+=mglNumThr)
35 {
36 long i=ii%Width, j=ii/Width;
37 for(size_t k=0;k<Prm.size();k++)
38 {
39 if(Stop) break;
40 const mglPrim &p=GetPrm(k);
41 d.PDef = p.n3; d.pPos = p.s;
42 d.ObjId = p.id; d.PenWidth=p.w;
43 d.angle = p.angl;
44 if(p.type==2 || p.type==3) d.PDef = p.m;
45 switch(p.type)
46 {
47 case 0: mark_pix(i,j,Pnt[p.n1],p.n4,p.s,&d); break;
48 case 1: line_pix(i,j,Pnt[p.n1],Pnt[p.n2],&d); break;
49 case 2: trig_pix(i,j,Pnt[p.n1],Pnt[p.n2],Pnt[p.n3],true,&d); break;
50 case 3: quad_pix(i,j,Pnt[p.n1],Pnt[p.n2],Pnt[p.n3],Pnt[p.n4],&d); break;
51 case 4: glyph_pix(i,j,p,&d); break;
52 }
53 }
54 }
55 }
56 //-----------------------------------------------------------------------------
quad_pix(long i,long j,const mglPnt & p1,const mglPnt & p2,const mglPnt & p3,const mglPnt & p4,const mglDrawReg * d)57 void mglCanvas::quad_pix(long i, long j, const mglPnt &p1, const mglPnt &p2, const mglPnt &p3, const mglPnt &p4, const mglDrawReg *d)
58 {
59 if(!visible(i,j,d->m, d->PenWidth,d->angle)) return;
60 mglPnt d1(p2-p1), d2(p3-p1), d3(p4+p1-p2-p3);
61 float dd = d1.x*d2.y-d1.y*d2.x;
62 float dsx =-4*(d2.y*d3.x - d2.x*d3.y)*d1.y;
63 float dsy = 4*(d2.y*d3.x - d2.x*d3.y)*d1.x;
64 float xx = (i-p1.x), yy = (j-p1.y), s;
65 s = dsx*xx + dsy*yy + (dd+d3.y*xx-d3.x*yy)*(dd+d3.y*xx-d3.x*yy);
66 if(s<0) return; // no solution
67 s = sqrt(s);
68 float qu = d3.x*yy - d3.y*xx + dd + s, u=-1;
69 float qv = d3.y*xx - d3.x*yy + dd + s, v=-1;
70 if(qu && qv)
71 {
72 u = 2.f*(d2.y*xx - d2.x*yy)/qu;
73 v = 2.f*(d1.x*yy - d1.y*xx)/qv;
74 }
75 if(u*(1.f-u)<0.f || v*(1.f-v)<0.f) // first root bad
76 {
77 qu = d3.x*yy - d3.y*xx + dd - s;
78 qv = d3.y*xx - d3.x*yy + dd - s;
79 u = v = -1.f;
80 if(qu && qv)
81 {
82 u = 2.f*(d2.y*xx - d2.x*yy)/qu;
83 v = 2.f*(d1.x*yy - d1.y*xx)/qv;
84 }
85 if(u*(1.f-u)<0.f || v*(1.f-v)<0.f) return; // second root bad
86 }
87 mglPnt p(p1+d1*u+d2*v+d3*(u*v));
88 if(mgl_isnan(p.u) && mgl_isnum(p.v))
89 {
90 mglPoint n1(mglPoint(p2.x-p1.x,p2.y-p1.y,p2.z-p1.z)^mglPoint(p3.x-p1.x,p3.y-p1.y,p3.z-p1.z));
91 mglPoint n2(mglPoint(p2.x-p4.x,p2.y-p4.y,p2.z-p4.z)^mglPoint(p3.x-p4.x,p3.y-p4.y,p3.z-p4.z));
92 p.u = (n1.x+n2.x)*0.5;
93 p.v = (n1.y+n2.y)*0.5;
94 p.w = (n1.z+n2.z)*0.5;
95 }
96 unsigned char r[4]; col2int(p,r,d->ObjId);
97 if(r[3]) pnt_plot(i,j,p.z,r,d->ObjId);
98 }
99 //-----------------------------------------------------------------------------
trig_pix(long i,long j,const mglPnt & p1,const mglPnt & p2,const mglPnt & p3,bool anorm,const mglDrawReg * d)100 void mglCanvas::trig_pix(long i, long j, const mglPnt &p1, const mglPnt &p2, const mglPnt &p3, bool anorm, const mglDrawReg *d)
101 {
102 if(!visible(i,j,d->m, d->PenWidth,d->angle)) return;
103 mglPnt d1(p2-p1), d2(p3-p1);
104 float dd = d2.x*d1.y - d1.x*d2.y;
105 if(fabs(dd)<1e-5) return; // points lies on the same line
106 float dyv =-d1.x/dd, dxv = d1.y/dd, dyu = d2.x/dd, dxu =-d2.y/dd;
107 float xx = (i-p1.x), yy = (j-p1.y);
108 float u = dxu*xx+dyu*yy, v = dxv*xx+dyv*yy;
109 if(u<0 || v<0 || u+v>1) return;
110 mglPnt p(p1+d1*u+d2*v);
111 if(mgl_isnan(p.u) && mgl_isnum(p.v) && anorm)
112 { mglPoint nr(mglPoint(p2.x-p1.x,p2.y-p1.y,p2.z-p1.z)^mglPoint(p3.x-p1.x,p3.y-p1.y,p3.z-p1.z));
113 p.u = nr.x; p.v = nr.y; p.w = nr.z; }
114 unsigned char r[4];
115 col2int(p,r,d->ObjId);
116 if(r[3]) pnt_plot(i,j,p.z,r,d->ObjId);
117 }
118 //-----------------------------------------------------------------------------
line_pix(long i,long j,const mglPnt & p1,const mglPnt & p2,const mglDrawReg * dr)119 void mglCanvas::line_pix(long i, long j, const mglPnt &p1, const mglPnt &p2, const mglDrawReg *dr)
120 {
121 float xx = (i-p1.x), yy = (j-p1.y);
122 mglPnt d(p2-p1);
123 float dd = hypot(d.x, d.y);
124 float dxv = d.y/dd, dyv =-d.x/dd, dxu = d.x/dd, dyu = d.y/dd;
125 float u = dxu*xx+dyu*yy, v = dxv*xx+dyv*yy; v = v*v;
126 if(u<0) v += u*u;
127 else if(u>dd) v += (u-dd)*(u-dd);
128 float pw=dr->PenWidth, dpw=3*pen_delta;
129 if(dr->ObjId==HighId) { pw *= 2; dpw=2*pen_delta; }
130 if(v>pw*pw || !(dr->PDef & ( (uint64_t)1<<long(fmod(dr->pPos+u/pw, 16)) ) )) return;
131 mglPnt p(p1+d*(u/dd));
132 unsigned char r[4];
133 col2int(p,r,dr->ObjId);
134 r[3] = v<(pw-1)*(pw-1)/4 ? 255 : mgl_sline(255,dpw*(sqrt(v)+(1-pw)/2));
135 float dz = Width>2 ? 1 : 1e-5*Width; // provide additional height to be well visible on the surfaces
136 if(r[3]) pnt_plot(i,j,p.z+dz,r,dr->ObjId);
137 }
138 //-----------------------------------------------------------------------------
pnt_pix(long i,long j,const mglPnt & p,const mglDrawReg * dr)139 void mglCanvas::pnt_pix(long i, long j, const mglPnt &p, const mglDrawReg *dr)
140 {
141 float pw=3*dr->PenWidth,dpw=3*pen_delta;
142 if(dr->ObjId==HighId) { pw *= 2; dpw=2*pen_delta; }
143 unsigned char cs[4];
144 col2int(p,cs,dr->ObjId);
145 float xx = (i-p.x), yy = (j-p.y), v = xx*xx+yy*yy;
146 if(cs[3]==0 || v>(10/dpw+pw)*(10/dpw+pw)) return;
147 if(v<(pw-1)*(pw-1)/4) cs[3] = mgl_sline(cs[3],dpw*(sqrt(v)+(1-pw)/2));
148 if(cs[3]) pnt_plot(i,j,p.z,cs,dr->ObjId);
149 }
150 //-----------------------------------------------------------------------------
mark_pix(long i,long j,const mglPnt & q,char type,mreal size,mglDrawReg * d)151 void mglCanvas::mark_pix(long i, long j, const mglPnt &q, char type, mreal size, mglDrawReg *d)
152 {
153 unsigned char cs[4]; col2int(q,cs,d->ObjId); cs[3] = size>0 ? 255 : 255*q.t;
154 mglPnt p0=q,p1=q,p2=q,p3=q;
155 mreal ss=fabs(size);
156
157 if(type=='.' || ss==0)
158 {
159 if(d) d->PenWidth = ss?ss:sqrt(font_factor/400);
160 pnt_pix(i,j,q,d);
161 }
162 else
163 {
164 if(d)
165 {
166 d->PDef = MGL_SOLID_MASK; d->angle = 0;
167 d->PenWidth*=fabs(50*size);
168 if(d->PenWidth<1) d->PenWidth=1;
169 }
170 if(!strchr("xsSoO",type)) ss *= 1.1;
171 switch(type)
172 {
173 case 'P':
174 p0.x = q.x-ss; p0.y = q.y-ss; p1.x = q.x+ss; p1.y = q.y-ss;
175 p2.x = q.x+ss; p2.y = q.y+ss; p3.x = q.x-ss; p3.y = q.y+ss;
176 line_pix(i,j,p0,p1,d); line_pix(i,j,p1,p2,d);
177 line_pix(i,j,p2,p3,d); line_pix(i,j,p3,p0,d);
178 case '+':
179 p0.x = q.x-ss; p0.y = q.y; p1.x = q.x+ss; p1.y = q.y; line_pix(i,j,p0,p1,d);
180 p2.x = q.x; p2.y = q.y-ss; p3.x = q.x; p3.y = q.y+ss; line_pix(i,j,p2,p3,d);
181 break;
182 case 'X':
183 p0.x = q.x-ss; p0.y = q.y-ss; p1.x = q.x+ss; p1.y = q.y-ss;
184 p2.x = q.x+ss; p2.y = q.y+ss; p3.x = q.x-ss; p3.y = q.y+ss;
185 line_pix(i,j,p0,p1,d); line_pix(i,j,p1,p2,d);
186 line_pix(i,j,p2,p3,d); line_pix(i,j,p3,p0,d);
187 case 'x':
188 p0.x = q.x-ss; p0.y = q.y-ss; p1.x = q.x+ss; p1.y = q.y+ss; line_pix(i,j,p0,p1,d);
189 p2.x = q.x+ss; p2.y = q.y-ss; p3.x = q.x-ss; p3.y = q.y+ss; line_pix(i,j,p2,p3,d);
190 break;
191 case 'S':
192 p0.x = q.x-ss; p0.y = q.y-ss; p1.x = q.x-ss; p1.y = q.y+ss;
193 p2.x= q.x+ss; p2.y= q.y+ss; p3.x = q.x+ss; p3.y = q.y-ss;
194 quad_pix(i,j,p0,p1,p3,p2,d);
195 case 's':
196 p0.x = q.x-ss; p0.y = q.y-ss; p1.x = q.x+ss; p1.y = q.y-ss;
197 p2.x = q.x+ss; p2.y = q.y+ss; p3.x = q.x-ss; p3.y = q.y+ss;
198 line_pix(i,j,p0,p1,d); line_pix(i,j,p1,p2,d);
199 line_pix(i,j,p2,p3,d); line_pix(i,j,p3,p0,d);
200 break;
201 case 'D':
202 p0.x = q.x; p0.y = q.y-ss; p1.x = q.x+ss; p1.y = q.y;
203 p2.x= q.x; p2.y= q.y+ss; p3.x = q.x-ss; p3.y = q.y;
204 quad_pix(i,j,p0,p1,p3,p2,d);
205 case 'd':
206 p0.x = q.x; p0.y = q.y-ss; p1.x = q.x+ss; p1.y = q.y;
207 p2.x = q.x; p2.y = q.y+ss; p3.x = q.x-ss; p3.y = q.y;
208 line_pix(i,j,p0,p1,d); line_pix(i,j,p1,p2,d);
209 line_pix(i,j,p2,p3,d); line_pix(i,j,p3,p0,d);
210 break;
211 case 'Y':
212 p1.x = q.x; p1.y = q.y-ss; line_pix(i,j,q,p1,d);
213 p2.x = q.x-0.8*ss; p2.y = q.y+0.6*ss; line_pix(i,j,q,p2,d);
214 p3.x = q.x+0.8*ss; p3.y = q.y+0.6*ss; line_pix(i,j,q,p3,d);
215 break;
216 case '*':
217 p0.x = q.x-ss; p0.y = q.y;
218 p1.x = q.x+ss; p1.y = q.y; line_pix(i,j,p0,p1,d);
219 p0.x = q.x-0.6*ss; p0.y = q.y-0.8*ss;
220 p1.x = q.x+0.6*ss; p1.y = q.y+0.8*ss; line_pix(i,j,p0,p1,d);
221 p0.x = q.x-0.6*ss; p0.y = q.y+0.8*ss;
222 p1.x = q.x+0.6*ss; p1.y = q.y-0.8*ss; line_pix(i,j,p0,p1,d);
223 break;
224 case 'T':
225 p0.x = q.x-ss; p0.y = q.y-ss/2;
226 p1.x = q.x+ss; p1.y = q.y-ss/2;
227 p2.x= q.x; p2.y= q.y+ss;
228 trig_pix(i,j,p0,p1,p2,false,d);
229 case '^':
230 p0.x = q.x-ss; p0.y = q.y-ss/2;
231 p1.x = q.x+ss; p1.y = q.y-ss/2;
232 p2.x= q.x; p2.y= q.y+ss;
233 line_pix(i,j,p0,p1,d); line_pix(i,j,p1,p2,d);
234 line_pix(i,j,p2,p0,d); break;
235 case 'V':
236 p0.x = q.x-ss; p0.y = q.y+ss/2;
237 p1.x = q.x+ss; p1.y = q.y+ss/2;
238 p2.x= q.x; p2.y= q.y-ss;
239 trig_pix(i,j,p0,p1,p2,false,d);
240 case 'v':
241 p0.x = q.x-ss; p0.y = q.y+ss/2;
242 p1.x = q.x+ss; p1.y = q.y+ss/2;
243 p2.x= q.x; p2.y= q.y-ss;
244 line_pix(i,j,p0,p1,d); line_pix(i,j,p1,p2,d);
245 line_pix(i,j,p2,p0,d); break;
246 case 'L':
247 p0.x = q.x+ss/2; p0.y = q.y+ss;
248 p1.x = q.x+ss/2; p1.y = q.y-ss;
249 p2.x= q.x-ss; p2.y= q.y;
250 trig_pix(i,j,p0,p1,p2,false,d);
251 case '<':
252 p0.x = q.x+ss/2; p0.y = q.y+ss;
253 p1.x = q.x+ss/2; p1.y = q.y-ss;
254 p2.x= q.x-ss; p2.y= q.y;
255 line_pix(i,j,p0,p1,d); line_pix(i,j,p1,p2,d);
256 line_pix(i,j,p2,p0,d); break;
257 case 'R':
258 p0.x = q.x-ss/2; p0.y = q.y+ss;
259 p1.x = q.x-ss/2; p1.y = q.y-ss;
260 p2.x= q.x+ss; p2.y= q.y;
261 trig_pix(i,j,p0,p1,p2,false,d);
262 case '>':
263 p0.x = q.x-ss/2; p0.y = q.y+ss;
264 p1.x = q.x-ss/2; p1.y = q.y-ss;
265 p2.x= q.x+ss; p2.y= q.y;
266 line_pix(i,j,p0,p1,d); line_pix(i,j,p1,p2,d);
267 line_pix(i,j,p2,p0,d); break;
268 case 'O':
269 {
270 float xx = (i-q.x), yy = (j-q.y);
271 float dz = Width>2 ? 1 : 1e-5*Width; // provide additional height to be well visible on the surfaces
272 if(xx*xx+yy*yy<ss*ss && cs[3]) pnt_plot(i,j,q.z+dz,cs,d->ObjId);
273 }
274 case 'o':
275 {
276 float pw=d->PenWidth;
277 float xx = (i-q.x), yy = (j-q.y), v = hypot(xx,yy);
278 v = (v-ss)*(v-ss);
279 // if(v>pw*pw) return;
280 if(v>(pw-1)*(pw-1)/4) cs[3] = mgl_sline(cs[3],2*(sqrt(v)+(1-pw)/2));
281 float dz = Width>2 ? 1 : 1e-5*Width; // provide additional height to be well visible on the surfaces
282 if(cs[3]) pnt_plot(i,j,q.z+dz,cs,d->ObjId);
283 }
284 break;
285 case 'C':
286 pnt_pix(i,j,q,d);
287 {
288 float pw=d->PenWidth;
289 float xx = (i-q.x), yy = (j-q.y), v = hypot(xx,yy);
290 v = (v-ss)*(v-ss);
291 // if(v>pw*pw) return;
292 if(v>(pw-1)*(pw-1)/4) cs[3] = mgl_sline(cs[3],2*(sqrt(v)+(1-pw)/2));
293 float dz = Width>2 ? 1 : 1e-5*Width; // provide additional height to be well visible on the surfaces
294 if(cs[3]) pnt_plot(i,j,q.z+dz,cs,d->ObjId);
295 }
296 break;
297 }
298 }
299 }
300 //-----------------------------------------------------------------------------
glyph_pix(long i,long j,const mglPrim & P,mglDrawReg * d)301 void mglCanvas::glyph_pix(long i, long j, const mglPrim &P, mglDrawReg *d)
302 {
303 float phi = GetGlyphPhi(Pnt[P.n2],P.w);
304 if(mgl_isnan(phi)) return;
305
306 if(d) { d->PDef = MGL_SOLID_MASK; d->angle = 0; d->PenWidth=1; }
307 mglPnt p=Pnt[P.n1];
308 mreal pf=sqrt((Bp.b[0]*Bp.b[0]+Bp.b[1]*Bp.b[1]+Bp.b[3]*Bp.b[3]+Bp.b[4]*Bp.b[4])/2), f = P.p*pf;
309
310 mglMatrix M;
311 M.b[0] = M.b[4] = M.b[8] = P.s;
312 M.RotateN(phi,0,0,1);
313 M.x=p.x; M.y=p.y; M.z=p.z; M.pf = 1;
314 p.u *= pf; p.v *= pf;
315
316 const mglGlyph &g = Glf[P.n4];
317 if(P.n3&8)
318 {
319 if(!(P.n3&4)) glyph_lpix(i,j,&M,p,f,true, d);
320 glyph_lpix(i,j,&M,p,f,false, d);
321 }
322 else
323 {
324 if(!(P.n3&4)) glyph_fpix(i,j,&M,p,f,g, d);
325 glyph_wpix(i,j,&M,p,f,g, d);
326 }
327 }
328 //-----------------------------------------------------------------------------
glyph_fpix(long i,long j,const mglMatrix * M,const mglPnt & pp,mreal f,const mglGlyph & g,const mglDrawReg * d)329 void mglCanvas::glyph_fpix(long i, long j, const mglMatrix *M, const mglPnt &pp, mreal f, const mglGlyph &g, const mglDrawReg *d)
330 {
331 if(!g.trig || g.nt<=0) return;
332 mglPnt q0=pp, q1=pp, q2=pp;
333 q0.u=q0.v=q1.u=q1.v=q2.u=q2.v=NAN;
334 for(long ik=0;ik<g.nt;ik++)
335 {
336 long ii = 6*ik; mglPoint p;
337 p.Set(f*g.trig[ii]+pp.u,f*g.trig[ii+1]+pp.v,0);
338 PostScale(M,p); q0.x = p.x; q0.y = p.y; q0.z = p.z;
339 ii+=2; p.Set(f*g.trig[ii]+pp.u,f*g.trig[ii+1]+pp.v,0);
340 PostScale(M,p); q1.x = p.x; q1.y = p.y; q1.z = p.z;
341 ii+=2; p.Set(f*g.trig[ii]+pp.u,f*g.trig[ii+1]+pp.v,0);
342 PostScale(M,p); q2.x = p.x; q2.y = p.y; q2.z = p.z;
343 trig_pix(i,j,q0,q1,q2,false,d);
344 }
345 }
346 //-----------------------------------------------------------------------------
glyph_wpix(long i,long j,const mglMatrix * M,const mglPnt & pp,mreal f,const mglGlyph & g,const mglDrawReg * d)347 void mglCanvas::glyph_wpix(long i, long j, const mglMatrix *M, const mglPnt &pp, mreal f, const mglGlyph &g, const mglDrawReg *d)
348 {
349 if(!g.line || g.nl<=0) return;
350 long il=0;
351 mglPnt q0=pp, q1=pp; q0.u=q0.v=q1.u=q1.v=NAN;
352 mglPoint p1,p2;
353 for(long ik=0;ik<g.nl;ik++)
354 {
355 long ii = 2*ik;
356 if(g.line[ii]==0x3fff && g.line[ii+1]==0x3fff) // line breakthrough
357 { il = ik+1; continue; }
358 else if(ik==g.nl-1 || (g.line[ii+2]==0x3fff && g.line[ii+3]==0x3fff))
359 { // enclose the circle. May be in future this block should be commented
360 p1.Set(f*g.line[ii]+pp.u,f*g.line[ii+1]+pp.v,0); ii=2*il;
361 p2.Set(f*g.line[ii]+pp.u,f*g.line[ii+1]+pp.v,0);
362 }
363 else
364 { // normal line
365 p1.Set(f*g.line[ii]+pp.u,f*g.line[ii+1]+pp.v,0); ii+=2;
366 p2.Set(f*g.line[ii]+pp.u,f*g.line[ii+1]+pp.v,0);
367 }
368 PostScale(M,p1); PostScale(M,p2);
369 q0.x = p1.x; q0.y = p1.y; q0.z = p1.z;
370 q1.x = p2.x; q1.y = p2.y; q1.z = p2.z;
371 line_pix(i,j,q0,q1,d);
372 }
373 }
374 //-----------------------------------------------------------------------------
glyph_lpix(long i,long j,const mglMatrix * M,const mglPnt & pp,mreal f,bool solid,const mglDrawReg * d)375 void mglCanvas::glyph_lpix(long i, long j, const mglMatrix *M, const mglPnt &pp, mreal f, bool solid, const mglDrawReg *d)
376 {
377 mglPnt q0=pp,q1=pp,q2=pp,q3=pp;
378 q0.u=q0.v=q1.u=q1.v=q2.u=q2.v=q3.u=q3.v=NAN;
379 mglPoint p1,p2,p3,p4;
380
381 mreal dy = 0.004;
382 p1.Set(pp.u,pp.v-dy,0); PostScale(M,p1);
383 p2.Set(pp.u,pp.v+dy,0); PostScale(M,p2);
384 p3.Set(fabs(f)+pp.u,pp.v+dy,0); PostScale(M,p3);
385 p4.Set(fabs(f)+pp.u,pp.v-dy,0); PostScale(M,p4);
386
387 q0.x = p1.x; q0.y = p1.y; q0.z = p1.z;
388 q1.x = p2.x; q1.y = p2.y; q1.z = p2.z;
389 q2.x = p3.x; q2.y = p3.y; q2.z = p3.z;
390 q3.x = p4.x; q3.y = p4.y; q3.z = p4.z;
391
392 if(solid) quad_pix(i,j,q0,q1,q3,q2,d);
393 else
394 {
395 line_pix(i,j,q0,q1,d); line_pix(i,j,q2,q1,d);
396 line_pix(i,j,q0,q3,d); line_pix(i,j,q2,q3,d);
397 }
398 }
399 //-----------------------------------------------------------------------------
400