1 /***************************************************************************
2 * export_3d.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 <time.h>
21 #include <stdarg.h>
22 #include "mgl2/canvas.h"
23 #include "mgl2/canvas_cf.h"
24 #undef _GR_
25 #define _GR_ ((mglCanvas *)(*gr))
26 #define _Gr_ ((mglCanvas *)(gr))
27 int MGL_NO_EXPORT mgl_tga_save(const char *fname, int w, int h, unsigned char **p);
28 int MGL_NO_EXPORT mgl_pnga_save(const char *fname, int w, int h, unsigned char **p);
29 void MGL_NO_EXPORT mgl_printf(void *fp, bool gz, const char *str, ...);
30 std::string MGL_NO_EXPORT mgl_sprintf(const char *str, ...);
31 //-----------------------------------------------------------------------------
GetRGBA(unsigned char * f) const32 void mglTexture::GetRGBA(unsigned char *f) const
33 {
34 for(long i=255;i>=0;i--)
35 {
36 mglColor c1 = col[2*i], c2 = col[2*i+1];
37 for(long j=0;j<256;j++)
38 {
39 long i0 = 4*(j+256*i);
40 mglColor c = c1 + (c2-c1)*(j/255.);
41 f[i0] = int(255*c.r);
42 f[i0+1] = int(255*c.g);
43 f[i0+2] = int(255*c.b);
44 f[i0+3] = int(255*c.a);
45 }
46 }
47 }
48 //-----------------------------------------------------------------------------
mgl_obj_glyph_old(HMGL gr,const mglPrim & q,const mglPnt & p,FILE * fp)49 void MGL_EXPORT mgl_obj_glyph_old(HMGL gr, const mglPrim &q, const mglPnt &p, FILE *fp)
50 {
51 mreal f = q.p/2, dx=p.u/2, dy=p.v/2, x,y;
52 mreal c=q.s*cos(q.w*M_PI/180), s=-q.s*sin(q.w*M_PI/180);
53 if(mgl_isnan(q.s)) c=s=0;
54 double b[4] = {c,-s, s,c};
55 long i=q.n1+1;
56
57 const mglGlyph &g = gr->GetGlf(q.n4);
58 const mreal dd = 0.004;
59 if(q.n3&8)
60 {
61 fprintf(fp,"v %g %g %g\n",p.x+b[0]*dx+b[1]*(dy-dd),p.y+b[2]*dx+b[3]*(dy-dd),p.z);
62 fprintf(fp,"v %g %g %g\n",p.x+b[0]*dx+b[1]*(dy+dd),p.y+b[2]*dx+b[3]*(dy+dd),p.z);
63 fprintf(fp,"v %g %g %g\n",p.x+b[0]*(dx+f)+b[1]*(dy-dd),p.y+b[2]*dx+b[3]*(dy-dd),p.z);
64 fprintf(fp,"v %g %g %g\n",p.x+b[0]*(dx+f)+b[1]*(dy+dd),p.y+b[2]*dx+b[3]*(dy+dd),p.z);
65 if(!(q.n3&4)) // glyph_line(p,f,true, d);
66 {
67 fprintf(fp,"f -1/%ld -3/%ld -2/%ld\n",i,i,i);
68 fprintf(fp,"f -4/%ld -2/%ld -3/%ld\n",i,i,i);
69 }
70 else // glyph_line(p,f,false, d);
71 {
72 fprintf(fp,"l -1/%ld -2/%ld\n",i,i);
73 fprintf(fp,"l -3/%ld -4/%ld\n",i,i);
74 fprintf(fp,"l -1/%ld -3/%ld\n",i,i);
75 fprintf(fp,"l -2/%ld -4/%ld\n",i,i);
76 }
77 }
78 else
79 {
80 if(!(q.n3&4)) // glyph_fill(p,f,g, d);
81 {
82 for(long ik=0;ik<g.nt;ik++)
83 {
84 x = dx+f*g.trig[6*ik]; y = dy+f*g.trig[6*ik+1];
85 fprintf(fp,"v %g %g %g\n",p.x+b[0]*x+b[1]*y,p.y+b[2]*x+b[3]*y,p.z);
86 x = dx+f*g.trig[6*ik+2]; y = dy+f*g.trig[6*ik+3];
87 fprintf(fp,"v %g %g %g\n",p.x+b[0]*x+b[1]*y,p.y+b[2]*x+b[3]*y,p.z);
88 x = dx+f*g.trig[6*ik+4]; y = dy+f*g.trig[6*ik+5];
89 fprintf(fp,"v %g %g %g\n",p.x+b[0]*x+b[1]*y,p.y+b[2]*x+b[3]*y,p.z);
90 fprintf(fp,"f -1/%ld -3/%ld -2/%ld\n",i,i,i);
91 }
92 }
93 else // glyph_wire(p,f,g, d);
94 {
95 long il=0;
96 for(long ik=0;ik<g.nl;ik++)
97 {
98 x = g.line[2*ik]; y = g.line[2*ik+1];
99 if(x==0x3fff && y==0x3fff) // line breakthrough
100 { il = ik+1; continue; }
101 else if(ik==g.nl-1 || (g.line[2*ik+2]==0x3fff && g.line[2*ik+3]==0x3fff))
102 { // enclose the circle. May be in future this block should be commented
103 x = dx+f*g.line[2*ik]; y = dy+f*g.line[2*ik+1];
104 fprintf(fp,"v %g %g %g\n",p.x+b[0]*x+b[1]*y,p.y+b[2]*x+b[3]*y,p.z);
105 x = dx+f*g.line[2*il]; y = dy+f*g.line[2*il+1];
106 fprintf(fp,"v %g %g %g\n",p.x+b[0]*x+b[1]*y,p.y+b[2]*x+b[3]*y,p.z);
107 }
108 else
109 { // normal line
110 x = dx+f*g.line[2*ik]; y = dy+f*g.line[2*ik+1];
111 fprintf(fp,"v %g %g %g\n",p.x+b[0]*x+b[1]*y,p.y+b[2]*x+b[3]*y,p.z);
112 x = dx+f*g.line[2*ik+2]; y = dy+f*g.line[2*ik+3];
113 fprintf(fp,"v %g %g %g\n",p.x+b[0]*x+b[1]*y,p.y+b[2]*x+b[3]*y,p.z);
114 }
115 fprintf(fp,"l -1/%ld -2/%ld\n",i,i);
116 }
117 }
118 }
119 }
120 //-----------------------------------------------------------------------------
121 /* M.Vidassov take/move it into src/obj.cpp */
mgl_obj_prim_old(HMGL gr,const mglPrim & q,const mglPnt & p,FILE * fp,mreal size)122 void MGL_EXPORT mgl_obj_prim_old(HMGL gr, const mglPrim &q, const mglPnt &p, FILE *fp, mreal size)
123 {
124 char type = q.n4; mreal ss=size;
125 long i=q.n1+1, n1=q.n1+1,n2=q.n2+1,n3=q.n3+1,n4=q.n4+1;
126 switch(q.type)
127 {
128 case 0:
129 if(!strchr("xsSoO",type)) ss *= 1.1;
130 if(type=='.' || ss==0) fprintf(fp,"p %ld\n", i);
131 else switch(type)
132 {
133 case 'P':
134 fprintf(fp,"v %g %g %g\n",p.x-ss,p.y-ss,p.z);
135 fprintf(fp,"v %g %g %g\n",p.x+ss,p.y-ss,p.z);
136 fprintf(fp,"v %g %g %g\n",p.x+ss,p.y+ss,p.z);
137 fprintf(fp,"v %g %g %g\n",p.x-ss,p.y+ss,p.z);
138 fprintf(fp,"l -4/%ld -3/%ld\n", i,i);
139 fprintf(fp,"l -3/%ld -2/%ld\n", i,i);
140 fprintf(fp,"l -2/%ld -1/%ld\n", i,i);
141 fprintf(fp,"l -1/%ld -4/%ld\n", i,i);
142 case '+':
143 fprintf(fp,"v %g %g %g\n",p.x-ss,p.y,p.z);
144 fprintf(fp,"v %g %g %g\n",p.x+ss,p.y,p.z);
145 fprintf(fp,"v %g %g %g\n",p.x,p.y-ss,p.z);
146 fprintf(fp,"v %g %g %g\n",p.x,p.y+ss,p.z);
147 fprintf(fp,"l -4/%ld -3/%ld\n", i,i);
148 fprintf(fp,"l -2/%ld -1/%ld\n", i,i); break;
149 case 'X':
150 fprintf(fp,"v %g %g %g\n",p.x-ss,p.y-ss,p.z);
151 fprintf(fp,"v %g %g %g\n",p.x+ss,p.y-ss,p.z);
152 fprintf(fp,"v %g %g %g\n",p.x+ss,p.y+ss,p.z);
153 fprintf(fp,"v %g %g %g\n",p.x-ss,p.y+ss,p.z);
154 fprintf(fp,"l -4/%ld -3/%ld\n", i,i);
155 fprintf(fp,"l -3/%ld -2/%ld\n", i,i);
156 fprintf(fp,"l -2/%ld -1/%ld\n", i,i);
157 fprintf(fp,"l -1/%ld -4/%ld\n", i,i);
158 fprintf(fp,"l -1/%ld -3/%ld\n", i,i);
159 fprintf(fp,"l -2/%ld -4/%ld\n", i,i); break;
160 case 'x':
161 fprintf(fp,"v %g %g %g\n",p.x-ss,p.y-ss,p.z);
162 fprintf(fp,"v %g %g %g\n",p.x+ss,p.y-ss,p.z);
163 fprintf(fp,"v %g %g %g\n",p.x+ss,p.y+ss,p.z);
164 fprintf(fp,"v %g %g %g\n",p.x-ss,p.y+ss,p.z);
165 fprintf(fp,"l -1/%ld -3/%ld\n", i,i);
166 fprintf(fp,"l -2/%ld -4/%ld\n", i,i); break;
167 case 'S':
168 fprintf(fp,"v %g %g %g\n",p.x-ss,p.y-ss,p.z);
169 fprintf(fp,"v %g %g %g\n",p.x+ss,p.y-ss,p.z);
170 fprintf(fp,"v %g %g %g\n",p.x+ss,p.y+ss,p.z);
171 fprintf(fp,"v %g %g %g\n",p.x-ss,p.y+ss,p.z);
172 fprintf(fp,"f -4/%ld -3/%ld -2/%ld -1/%ld\n",i,i,i,i); break;
173 case 's':
174 fprintf(fp,"v %g %g %g\n",p.x-ss,p.y-ss,p.z);
175 fprintf(fp,"v %g %g %g\n",p.x+ss,p.y-ss,p.z);
176 fprintf(fp,"v %g %g %g\n",p.x+ss,p.y+ss,p.z);
177 fprintf(fp,"v %g %g %g\n",p.x-ss,p.y+ss,p.z);
178 fprintf(fp,"l -4/%ld -3/%ld\n", i,i);
179 fprintf(fp,"l -3/%ld -2/%ld\n", i,i);
180 fprintf(fp,"l -2/%ld -1/%ld\n", i,i);
181 fprintf(fp,"l -1/%ld -4/%ld\n", i,i); break;
182 case 'D':
183 fprintf(fp,"v %g %g %g\n",p.x,p.y-ss,p.z);
184 fprintf(fp,"v %g %g %g\n",p.x+ss,p.y,p.z);
185 fprintf(fp,"v %g %g %g\n",p.x,p.y+ss,p.z);
186 fprintf(fp,"v %g %g %g\n",p.x-ss,p.y,p.z);
187 fprintf(fp,"f -4/%ld -3/%ld -2/%ld -1/%ld\n",i,i,i,i); break;
188 case 'd':
189 fprintf(fp,"v %g %g %g\n",p.x,p.y-ss,p.z);
190 fprintf(fp,"v %g %g %g\n",p.x+ss,p.y,p.z);
191 fprintf(fp,"v %g %g %g\n",p.x,p.y+ss,p.z);
192 fprintf(fp,"v %g %g %g\n",p.x-ss,p.y,p.z);
193 fprintf(fp,"l -4/%ld -3/%ld\n", i,i);
194 fprintf(fp,"l -3/%ld -2/%ld\n", i,i);
195 fprintf(fp,"l -2/%ld -1/%ld\n", i,i);
196 fprintf(fp,"l -1/%ld -4/%ld\n", i,i); break;
197 case 'Y':
198 fprintf(fp,"v %g %g %g\n",p.x,p.y-ss,p.z);
199 fprintf(fp,"v %g %g %g\n",p.x+0.8*ss,p.y+0.6*ss,p.z);
200 fprintf(fp,"v %g %g %g\n",p.x-0.8*ss,p.y+0.6*ss,p.z);
201 fprintf(fp,"l -3/%ld %ld/%ld\n", i,i,i);
202 fprintf(fp,"l -2/%ld %ld/%ld\n", i,i,i);
203 fprintf(fp,"l -1/%ld %ld/%ld\n", i,i,i); break;
204 case '*':
205 fprintf(fp,"v %g %g %g\n",p.x+ss,p.y,p.z);
206 fprintf(fp,"v %g %g %g\n",p.x-ss,p.y,p.z);
207 fprintf(fp,"l -2/%ld -1/%ld\n", i,i);
208 fprintf(fp,"v %g %g %g\n",p.x+0.6*ss,p.y+0.8*ss,p.z);
209 fprintf(fp,"v %g %g %g\n",p.x-0.6*ss,p.y-0.8*ss,p.z);
210 fprintf(fp,"l -2/%ld -1/%ld\n", i,i);
211 fprintf(fp,"v %g %g %g\n",p.x+0.6*ss,p.y-0.8*ss,p.z);
212 fprintf(fp,"v %g %g %g\n",p.x-0.6*ss,p.y+0.8*ss,p.z);
213 fprintf(fp,"l -2/%ld -1/%ld\n", i,i); break;
214 case 'T':
215 fprintf(fp,"v %g %g %g\n",p.x-ss,p.y-ss/2,p.z);
216 fprintf(fp,"v %g %g %g\n",p.x+ss,p.y-ss/2,p.z);
217 fprintf(fp,"v %g %g %g\n",p.x,p.y+ss,p.z);
218 fprintf(fp,"f -3/%ld -2/%ld -1/%ld\n", i,i,i); break;
219 case '^':
220 fprintf(fp,"v %g %g %g\n",p.x-ss,p.y-ss/2,p.z);
221 fprintf(fp,"v %g %g %g\n",p.x+ss,p.y-ss/2,p.z);
222 fprintf(fp,"v %g %g %g\n",p.x,p.y+ss,p.z);
223 fprintf(fp,"l -3/%ld -2/%ld\n", i,i);
224 fprintf(fp,"l -2/%ld -1/%ld\n", i,i);
225 fprintf(fp,"l -1/%ld -3/%ld\n", i,i); break;
226 case 'V':
227 fprintf(fp,"v %g %g %g\n",p.x-ss,p.y+ss/2,p.z);
228 fprintf(fp,"v %g %g %g\n",p.x+ss,p.y+ss/2,p.z);
229 fprintf(fp,"v %g %g %g\n",p.x,p.y-ss,p.z);
230 fprintf(fp,"f -3/%ld -2/%ld -1/%ld\n", i,i,i); break;
231 case 'v':
232 fprintf(fp,"v %g %g %g\n",p.x-ss,p.y+ss/2,p.z);
233 fprintf(fp,"v %g %g %g\n",p.x+ss,p.y+ss/2,p.z);
234 fprintf(fp,"v %g %g %g\n",p.x,p.y-ss,p.z);
235 fprintf(fp,"l -3/%ld -2/%ld\n", i,i);
236 fprintf(fp,"l -2/%ld -1/%ld\n", i,i);
237 fprintf(fp,"l -1/%ld -3/%ld\n", i,i); break;
238 case 'L':
239 fprintf(fp,"v %g %g %g\n",p.x+ss/2,p.y+ss,p.z);
240 fprintf(fp,"v %g %g %g\n",p.x+ss/2,p.y-ss,p.z);
241 fprintf(fp,"v %g %g %g\n",p.x-ss,p.y,p.z);
242 fprintf(fp,"f -3/%ld -2/%ld -1/%ld\n", i,i,i); break;
243 case '<':
244 fprintf(fp,"v %g %g %g\n",p.x+ss/2,p.y+ss,p.z);
245 fprintf(fp,"v %g %g %g\n",p.x+ss/2,p.y-ss,p.z);
246 fprintf(fp,"v %g %g %g\n",p.x-ss,p.y,p.z);
247 fprintf(fp,"l -3/%ld -2/%ld\n", i,i);
248 fprintf(fp,"l -2/%ld -1/%ld\n", i,i);
249 fprintf(fp,"l -1/%ld -3/%ld\n", i,i); break;
250 case 'R':
251 fprintf(fp,"v %g %g %g\n",p.x-ss/2,p.y+ss,p.z);
252 fprintf(fp,"v %g %g %g\n",p.x-ss/2,p.y-ss,p.z);
253 fprintf(fp,"v %g %g %g\n",p.x+ss,p.y,p.z);
254 fprintf(fp,"f -3/%ld -2/%ld -1/%ld\n", i,i,i); break;
255 case '>':
256 fprintf(fp,"v %g %g %g\n",p.x-ss/2,p.y+ss,p.z);
257 fprintf(fp,"v %g %g %g\n",p.x-ss/2,p.y-ss,p.z);
258 fprintf(fp,"v %g %g %g\n",p.x+ss,p.y,p.z);
259 fprintf(fp,"l -3/%ld -2/%ld\n", i,i);
260 fprintf(fp,"l -2/%ld -1/%ld\n", i,i);
261 fprintf(fp,"l -1/%ld -3/%ld\n", i,i); break;
262 case 'O':
263 for(long j=0;j<=20;j++)
264 fprintf(fp,"v %g %g %g\n",p.x+ss*mgl_cos[(j*36)%360],p.y+ss*mgl_cos[(270+j*36)%360],p.z);
265 for(long j=0;j<20;j++)
266 fprintf(fp,"f %ld/%ld %ld/%ld %ld/%ld\n", j-21,i, j-20,i, i,i);
267 break;
268 case 'C': fprintf(fp,"p %ld\n", i);
269 case 'o':
270 for(long j=0;j<=20;j++)
271 fprintf(fp,"v %g %g %g\n",p.x+ss*mgl_cos[(j*36)%360],p.y+ss*mgl_cos[(270+j*36)%360],p.z);
272 for(long j=0;j<20;j++)
273 fprintf(fp,"l %ld/%ld %ld/%ld\n", j-21,i, j-20,i);
274 break;
275 }
276 break;
277 case 1: fprintf(fp,"l %ld/%ld %ld/%ld\n", n1,n1, n2,n2); break;
278 case 2: fprintf(fp,"f %ld/%ld %ld/%ld %ld/%ld\n", n1,n1, n2,n2, n3,n3); break;
279 case 3: fprintf(fp,"f %ld/%ld %ld/%ld %ld/%ld\n", n1,n1, n2,n2, n3,n3);
280 fprintf(fp,"f %ld/%ld %ld/%ld %ld/%ld\n", n2,n2, n4,n4, n3,n3); break;
281 case 4: mgl_obj_glyph_old(gr,q,p,fp); break;
282 }
283 }
284 //-----------------------------------------------------------------------------
mgl_write_obj_old(HMGL gr,const char * fname,const char * descr,int use_png)285 void MGL_EXPORT mgl_write_obj_old(HMGL gr, const char *fname,const char *descr, int use_png)
286 {
287 if(gr->GetPrmNum()==0) return; // nothing to do
288 long m1=0,m2=0;
289 for(size_t i=0;i<gr->Grp.size();i++) // prepare array of indirect indexing
290 { long m = gr->Grp[i].Id; if(m<m1) m1=m; if(m>m2) m2=m; }
291 long *ng = new long[m2-m1+1];
292 for(size_t i=0;i<gr->Grp.size();i++) ng[gr->Grp[i].Id-m1] = i;
293 for(long i=0;i<gr->GetPrmNum();i++) // collect data for groups
294 // it is rather expensive (extra 4b per primitive) but need for export to 3D
295 {
296 long m = gr->GetPrm(i,false).id-m1;
297 if(m>=0 && m<m2-m1+1) gr->Grp[ng[m]].p.push_back(i);
298 }
299 delete []ng;
300
301 size_t len=strlen(fname),ntxt=gr->GetTxtNum();
302 FILE *fp=fopen(fname,"wt");
303 if(!fp) { gr->SetWarn(mglWarnOpen,fname); return; }
304 // vertices definition
305 const std::string loc = setlocale(LC_NUMERIC, "C");
306 fprintf(fp,"# Created by MathGL library\n# Title: %s\n",(descr && *descr) ? descr : fname);
307 for(long i=0;i<gr->GetPntNum();i++)
308 {
309 const mglPnt &pp = gr->GetPnt(i);
310 fprintf(fp,"v %g %g %g\n",pp.x,pp.y,pp.z);
311 fprintf(fp,"vt %g %g\n",1-pp.ta,1-pp.c/ntxt);
312 // if(mgl_isnan(pp.u)) fprintf(fp,"vn 0 0 0\n");
313 // else fprintf(fp,"vn %g %g %g\n",pp.u,pp.v,pp.w);
314 }
315 // primitive definition in groups
316 char *tname = new char[len+15]; strcpy(tname,fname);
317 tname[len-4]=0; fprintf(fp,"# Primitives Definitions\nmtllib %s.mtl\nusemtl %s\n",tname,tname);
318 for(size_t i=0;i<gr->Grp.size();i++)
319 {
320 fprintf(fp,"g %s\n",gr->Grp[i].Lbl.c_str());
321 std::vector<long> &p = gr->Grp[i].p;
322 for(size_t j=0;j<p.size();j++)
323 {
324 const mglPrim &q=gr->GetPrm(p[j],false);
325 mgl_obj_prim_old(gr, q, gr->GetPnt(q.n1), fp, mgl_isnan(q.s)?0:q.s);
326 }
327 gr->Grp[i].p.clear(); // we don't need indexes anymore
328 }
329 // try to save "ungrouped" primitives
330 fclose(fp);
331 // prepare MTL file
332 tname[len-4]='.'; tname[len-3]='m'; tname[len-2]='t'; tname[len-1]='l';
333 fp=fopen(tname,"wt");
334 tname[len-4]=0; fprintf(fp,"newmtl %s\n",tname);
335 fprintf(fp,"Ka 1.000 1.000 1.000\n");
336 fprintf(fp,"Kd 1.000 1.000 1.000\n");
337 fprintf(fp,"Ks 0.000 0.000 0.000\n");
338 fprintf(fp,"d 1.0\nTr 0.0\nillum 2\n");
339 if(use_png) strcat(tname,"_texture.png");
340 // { tname[len-4]='.'; tname[len-3]='p'; tname[len-2]='n'; tname[len-1]='g'; }
341 else strcat(tname,"_texture.tga");
342 // { tname[len-4]='.'; tname[len-3]='t'; tname[len-2]='g'; tname[len-1]='a'; }
343 fprintf(fp,"map_Ka %s\nmap_Kd %s\nmap_Ks %s\n",tname,tname,tname);
344 fclose(fp);
345 // prepare texture file (TGA or PNG)
346 long j=gr->GetTxtNum();
347 unsigned char *buf = new unsigned char[4*256*256*j];
348 unsigned char **pbuf= (unsigned char **)malloc(256*j*sizeof(unsigned char *));
349 for(long i=0;i<256*j;i++) pbuf[i] = buf+4*256*i;
350 for(long i=0;i<j;i++) gr->GetTxt(i).GetRGBA(buf+i*256*256*4);
351 if(use_png) mgl_pnga_save(tname,256,256*j,pbuf);
352 else mgl_tga_save(tname,256,256*j,pbuf);
353 free(pbuf); delete []buf; delete []tname;
354 setlocale(LC_NUMERIC, loc.c_str());
355 }
mgl_write_obj_old_(uintptr_t * gr,const char * fname,const char * descr,int * use_png,int l,int n)356 void MGL_EXPORT mgl_write_obj_old_(uintptr_t *gr, const char *fname,const char *descr, int *use_png,int l,int n)
357 { char *s=new char[l+1]; memcpy(s,fname,l); s[l]=0;
358 char *d=new char[n+1]; memcpy(d,descr,n); d[n]=0;
359 mgl_write_obj_old(_GR_,s,d,*use_png); delete []s; delete []d; }
360 //-----------------------------------------------------------------------------
mgl_write_stl(HMGL gr,const char * fname,const char * descr)361 void MGL_EXPORT mgl_write_stl(HMGL gr, const char *fname,const char *descr)
362 {
363 if(gr->GetPrmNum()==0) return; // nothing to do
364 FILE *fp = fopen(fname,"wt");
365 if(!fp) { gr->SetWarn(mglWarnOpen,fname); return; }
366 const std::string loc = setlocale(LC_NUMERIC, "C");
367 fprintf(fp,"solid %s\n",(descr && *descr)?descr:"mathgl");
368 mglPnt pp;
369 for(long i=0;i<gr->GetPrmNum();i++)
370 {
371 const mglPrim &q=gr->GetPrm(i,false);
372 if(q.type==2) // triangles
373 {
374 pp = gr->GetPnt(q.n1);
375 fprintf(fp,"facet normal %.2g %.2g %.2g\nouter loop\n",pp.u,pp.v,pp.w);
376 fprintf(fp,"vertex %g %g %g\n",pp.x,pp.y,pp.z);
377 pp = gr->GetPnt(q.n2);
378 fprintf(fp,"vertex %g %g %g\n",pp.x,pp.y,pp.z);
379 pp = gr->GetPnt(q.n3);
380 fprintf(fp,"vertex %g %g %g\n",pp.x,pp.y,pp.z);
381 fprintf(fp,"endloop\nendfacet\n");
382 }
383 if(q.type==3) // quadrangles
384 {
385 pp = gr->GetPnt(q.n1);
386 fprintf(fp,"facet normal %.2g %.2g %.2g\nouter loop\n",pp.u,pp.v,pp.w);
387 fprintf(fp,"vertex %g %g %g\n",pp.x,pp.y,pp.z);
388 pp = gr->GetPnt(q.n2);
389 fprintf(fp,"vertex %g %g %g\n",pp.x,pp.y,pp.z);
390 pp = gr->GetPnt(q.n3);
391 fprintf(fp,"vertex %g %g %g\n",pp.x,pp.y,pp.z);
392 fprintf(fp,"endloop\nendfacet\n");
393 pp = gr->GetPnt(q.n1);
394 fprintf(fp,"facet normal %.2g %.2g %.2g\nouter loop\n",pp.u,pp.v,pp.w);
395 pp = gr->GetPnt(q.n4);
396 fprintf(fp,"vertex %g %g %g\n",pp.x,pp.y,pp.z);
397 pp = gr->GetPnt(q.n2);
398 fprintf(fp,"vertex %g %g %g\n",pp.x,pp.y,pp.z);
399 pp = gr->GetPnt(q.n3);
400 fprintf(fp,"vertex %g %g %g\n",pp.x,pp.y,pp.z);
401 fprintf(fp,"endloop\nendfacet\n");
402 }
403 }
404 fprintf(fp,"endsolid %s",(descr && *descr)?descr:"mathgl");
405 fclose(fp);
406 setlocale(LC_NUMERIC, loc.c_str());
407 }
mgl_write_stl_(uintptr_t * gr,const char * fname,const char * descr,int l,int n)408 void MGL_EXPORT mgl_write_stl_(uintptr_t *gr, const char *fname,const char *descr,int l,int n)
409 { char *s=new char[l+1]; memcpy(s,fname,l); s[l]=0;
410 char *d=new char[n+1]; memcpy(d,descr,n); d[n]=0;
411 mgl_write_stl(_GR_,s,d); delete []s; delete []d; }
412 //-----------------------------------------------------------------------------
mgl_write_xyz(HMGL gr,const char * fname,const char * descr)413 void MGL_EXPORT mgl_write_xyz(HMGL gr, const char *fname,const char *descr)
414 {
415 if(gr->GetPrmNum()==0) return; // nothing to do
416
417 FILE *fp=fopen(fname,"wt"), *ff; // vertices definition
418 if(!fp) { gr->SetWarn(mglWarnOpen,fname); return; }
419 const std::string loc = setlocale(LC_NUMERIC, "C");
420 fprintf(fp,"# Created by MathGL library\n# Title: %s\n",(descr && *descr) ? descr : fname);
421 fprintf(fp,"# List of Vertices, with (x,y,z) coordinates.\n");
422 for(long i=0;i<gr->GetPntNum();i++)
423 {
424 const mglPnt &pp = gr->GetPnt(i);
425 fprintf(fp,"%g %g %g\n",pp.x,pp.y,pp.z);
426 }
427 fclose(fp);
428
429 // primitive definition
430 size_t len=strlen(fname);
431 char *tname = new char[len+2]; strcpy(tname,fname); tname[len+1]=tname[len]=0;
432 tname[len]='l'; fp = fopen(tname,"wt");
433 tname[len]='f'; ff = fopen(tname,"wt");
434 fprintf(fp,"# Created by MathGL library\n# Title: %s\n",(descr && *descr) ? descr : fname);
435 fprintf(fp,"# Indices of vertices to connect for lines\n");
436 fprintf(ff,"# Created by MathGL library\n# Title: %s\n",(descr && *descr) ? descr : fname);
437 fprintf(ff,"# Indices of vertices to connect for faces\n");
438 for(long i=0;i<gr->GetPrmNum();i++)
439 {
440 const mglPrim &q=gr->GetPrm(i,false);
441 if(q.type==1) fprintf(fp,"%ld %ld\n",q.n1+1,q.n2+1);
442 if(q.type==2) fprintf(ff,"%ld %ld %ld\n",q.n1+1,q.n2+1,q.n3+1);
443 if(q.type==3) fprintf(ff,"%ld %ld %ld\n%ld %ld %ld\n",q.n1+1,q.n2+1,q.n3+1,q.n4+1,q.n2+1,q.n3+1);
444 }
445 fclose(fp); fclose(ff); delete []tname;
446 setlocale(LC_NUMERIC, loc.c_str());
447 }
mgl_write_xyz_(uintptr_t * gr,const char * fname,const char * descr,int l,int n)448 void MGL_EXPORT mgl_write_xyz_(uintptr_t *gr, const char *fname,const char *descr,int l,int n)
449 { char *s=new char[l+1]; memcpy(s,fname,l); s[l]=0;
450 char *d=new char[n+1]; memcpy(d,descr,n); d[n]=0;
451 mgl_write_xyz(_GR_,s,d); delete []s; delete []d; }
452 //-----------------------------------------------------------------------------
mgl_write_off(HMGL gr,const char * fname,const char * descr,int colored)453 void MGL_EXPORT mgl_write_off(HMGL gr, const char *fname,const char *descr, int colored)
454 {
455 long nf=0;
456 for(long i=0;i<gr->GetPrmNum();i++) // find number of faces
457 {
458 const mglPrim &q=gr->GetPrm(i,false);
459 if(q.type==2 || q.type==3) nf++;
460 }
461 if(nf<=0) return; // nothing to do
462
463 FILE *fp=fopen(fname,"wt");
464 if(!fp) { gr->SetWarn(mglWarnOpen,fname); return; }
465 const std::string loc = setlocale(LC_NUMERIC, "C");
466 // vertices definition
467 if(colored)
468 fprintf(fp,"COFF\n# Created by MathGL library\n# Title: %s\n",(descr && *descr) ? descr : fname);
469 else
470 fprintf(fp,"OFF\n# Created by MathGL library\n# Title: %s\n",(descr && *descr) ? descr : fname);
471 fprintf(fp,"# List of Vertices, with (x,y,z,r,g,b,a) coordinates.\n");
472 fprintf(fp,"%ld %ld 0\n",gr->GetPntNum(), nf);
473 for(long i=0;i<gr->GetPntNum();i++)
474 {
475 const mglPnt &pp = gr->GetPnt(i);
476 if(colored)
477 fprintf(fp,"%g %g %g %g %g %g %g\n", pp.x, pp.y, pp.z, pp.r, pp.g, pp.b, pp.a);
478 else fprintf(fp,"%g %g %g\n", pp.x, pp.y, pp.z);
479 }
480 for(long i=0;i<gr->GetPrmNum();i++)
481 {
482 const mglPrim &q=gr->GetPrm(i,false);
483 const mglPnt &p1=gr->GetPnt(q.n1);
484 if(colored)
485 {
486 if(q.type==2)
487 fprintf(fp,"3 %ld %ld %ld\n",q.n1,q.n2,q.n3);
488 else if(q.type==3)
489 fprintf(fp,"4 %ld %ld %ld %ld\n",q.n1,q.n2,q.n4,q.n3);
490 }
491 else
492 {
493 if(q.type==2)
494 {
495 const mglPnt &p2=gr->GetPnt(q.n2), &p3=gr->GetPnt(q.n3);
496 if(p1.a>mgl_min_a || p2.a>mgl_min_a || p3.a>mgl_min_a)
497 fprintf(fp,"3 %ld %ld %ld %.2g %.2g %.2g %.2g\n",q.n1,q.n2,q.n3,
498 (p1.r+p2.r+p3.r)/3, (p1.g+p2.g+p3.g)/3, (p1.b+p2.b+p3.b)/3, (p1.a+p2.a+p3.a)/3);
499 }
500 else if(q.type==3)
501 {
502 const mglPnt &p2=gr->GetPnt(q.n2), &p3=gr->GetPnt(q.n3), &p4=gr->GetPnt(q.n4);
503 if(p1.a>mgl_min_a || p2.a>mgl_min_a || p3.a>mgl_min_a || p4.a>mgl_min_a)
504 fprintf(fp,"4 %ld %ld %ld %ld %.2g %.2g %.2g %.2g\n",q.n1,q.n2,q.n4,q.n3,
505 (p1.r+p2.r+p3.r+p4.r)/4, (p1.g+p2.g+p3.g+p4.g)/4, (p1.b+p2.b+p3.b+p4.b)/4, (p1.a+p2.a+p3.a+p4.a)/4);
506 }
507 }
508 }
509 fclose(fp);
510 setlocale(LC_NUMERIC, loc.c_str());
511 }
mgl_write_off_(uintptr_t * gr,const char * fname,const char * descr,int * colored,int l,int n)512 void MGL_EXPORT mgl_write_off_(uintptr_t *gr, const char *fname,const char *descr,int *colored,int l,int n)
513 { char *s=new char[l+1]; memcpy(s,fname,l); s[l]=0;
514 char *d=new char[n+1]; memcpy(d,descr,n); d[n]=0;
515 mgl_write_off(_GR_,s,d,*colored); delete []s; delete []d; }
516 //-----------------------------------------------------------------------------
WriteJSON(const char * fname,bool force_zlib)517 bool mglCanvas::WriteJSON(const char *fname, bool force_zlib)
518 {
519 bool fl = strcmp(fname,"-");
520 bool gz = force_zlib || fname[strlen(fname)-1]=='z';
521 void *fp = fl ? (gz ? (void*)gzopen(fname,"wt") : (void*)fopen(fname,"wt")) : stdout;
522 if (!fp) return true;
523 std::string s=GetJSON();
524 if(gz) gzprintf((gzFile)fp, "%s", s.c_str());
525 else fprintf((FILE *)fp, "%s", s.c_str());
526 if(fl) { if(gz) gzclose((gzFile)fp); else fclose((FILE *)fp); }
527 return false;
528 }
529 //-----------------------------------------------------------------------------
mgl_get_json(HMGL gr)530 MGL_EXPORT const char *mgl_get_json(HMGL gr)
531 {
532 static std::string json;
533 mglCanvas *g = dynamic_cast<mglCanvas *>(gr);
534 if(g) json = g->GetJSON();
535 return json.c_str();
536 }
537 //-----------------------------------------------------------------------------
GetJSON()538 std::string mglCanvas::GetJSON()
539 {
540 ClearUnused(); // clear unused points
541 PreparePrim(3);
542 std::string res, buf;
543 long ll=0,l=(long)Pnt.size();
544 long factor = Width>1?10:10000;
545 const std::string loc = setlocale(LC_NUMERIC, "C");
546 res = res + mgl_sprintf("{\n\"width\":%d,\t\"height\":%d,\t\"depth\":%d,\t\"plotid\":\"%s\",\t\"npnts\":%ld,\t\"pnts\":[\n",
547 factor*Width, factor*Height, factor*Depth, PlotId.c_str(), l);
548 for(long i=0;i<l;i++)
549 {
550 const mglPnt &q=Pnt[i];
551 res += mgl_sprintf("[%ld,%ld,%ld,%d]%c\n", long(factor*q.xx), long(factor*(Height-q.yy)), long(factor*q.zz),q.sub, i+1<l?',':' ');
552 }
553
554 l = (long)Prm.size(); ll = 0;
555 for(long i=0;i<l;i++)
556 { mglRGBA c; c.c = GetPrmCol(i,false); if(c.r[3]) ll++; }
557
558 res = res + mgl_sprintf("],\t\"nprim\":%ld,\t\"prim\":[\n",ll+1);
559
560 std::vector<mglPoint> xy; // vector for glyphs coordinates (to be separated from pnts)
561 res.reserve(60*(ll+1));
562 #pragma omp parallel for private(buf)
563 for(long i=0;i<l;i++)
564 {
565 const mglPrim &p=Prm[i]; mglRGBA cp; cp.c = GetPrmCol(i,false);
566 if(p.n1<0 || (p.type==1 && p.n2<0) || (p.type==2 && (p.n2<0 || p.n3<0)) || (p.type==3 && (p.n2<0 || p.n3<0 || p.n4<0)))
567 continue;
568 long n1=p.n1, n2=p.n2, n3=0, n4=(p.type==3||p.type==0)?p.n4:0;
569 if(p.type==2 || p.type==3) n3 = p.n3;
570 if(p.type==4)
571 {
572 const mglPnt &q = Pnt[p.n1];
573 #pragma omp critical
574 {n2 = xy.size(); xy.push_back(mglPoint(q.u,q.v,p.n2));}
575 n3 = p.n3; n4 = p.n4;
576 }
577 if(p.type==1 && n1>n2) { n1=p.n2; n2=p.n1; }
578 long ps=p.s==p.s?long(100*factor*p.s):0, pw=p.w==p.w?long(100*p.w):0, pp=p.p==p.p?mgl_int(1e5*p.p):0;
579 if(cp.r[3]==255 || p.type==0 || p.type==1 || p.type==4 || p.type==6)
580 buf = mgl_sprintf("[%d,%ld,%ld,%ld,%ld,%d,%ld,%ld,%ld,0,\"#%02x%02x%02x\"],\n",
581 p.type, n1, n2, n3, n4, p.id, ps,pw,pp, int(cp.r[0]),int(cp.r[1]),int(cp.r[2]));
582 else if(cp.r[3])
583 buf = mgl_sprintf("[%d,%ld,%ld,%ld,%ld,%d,%ld,%ld,%ld,0,\"rgba(%d,%d,%d,%.2g)\"],\n",
584 p.type, n1, n2, n3, n4, p.id, ps,pw,pp, int(cp.r[0]),int(cp.r[1]),int(cp.r[2]),cp.r[3]/255.);
585 else buf = "";
586 #pragma omp critical
587 res += buf;
588 }
589 res += "[-1,0,0,0,0,0,0,0,0,0,\"#000000\"]\n"; // need to add this empty block
590
591 l = (long)xy.size();
592 res = res + mgl_sprintf("],\t\"ncoor\":%lu,\t\"coor\":[\n",(unsigned long)l);
593 for(long i=0;i<l;i++)
594 {
595 const mglPoint &p=xy[i];
596 const mglPnt &q=Pnt[int(0.5+p.z)];
597 long px=long(100*p.x), py=long(100*p.y);
598 if(q.u==q.u && q.v==q.v && q.w==q.w)
599 res = res + mgl_sprintf("[%ld,%ld,%ld,%ld,%ld]%c\n", px, py, long(100*q.u), long(100*q.v), long(100*q.w), i+1<l?',':' ');
600 else
601 res = res + mgl_sprintf("[%ld,%ld,1e11,1e11,1e11]%c\n", px, py, i+1<l?',':' ');
602 }
603
604 l = (long)Glf.size();
605 res = res + mgl_sprintf("],\t\"nglfs\":%lu,\t\"glfs\":[\n",(unsigned long)l);
606 for(long i=0;i<l;i++)
607 {
608 const mglGlyph &g=Glf[i];
609 res = res + mgl_sprintf("[%ld,\n\t[", g.nl);
610 for(long j=0;j<2*g.nl;j++) res = res + mgl_sprintf("%d%c", g.line[j], j+1<2*g.nl?',':' ');
611 res = res + mgl_sprintf("]\n]%c\n", i+1<l?',':' ');
612 }
613 res = res + mgl_sprintf("]\n}\n");
614 setlocale(LC_NUMERIC, loc.c_str());
615 return res;
616 }
617 //-----------------------------------------------------------------------------
mgl_write_json(HMGL gr,const char * fname,const char *)618 void MGL_EXPORT mgl_write_json(HMGL gr, const char *fname,const char *)
619 { _Gr_->WriteJSON(fname); }
mgl_write_json_(uintptr_t * gr,const char * fname,const char * descr,int l,int n)620 void MGL_EXPORT mgl_write_json_(uintptr_t *gr, const char *fname,const char *descr,int l,int n)
621 { char *s=new char[l+1]; memcpy(s,fname,l); s[l]=0;
622 char *f=new char[n+1]; memcpy(f,descr,n); f[n]=0;
623 mgl_write_json(_GR_,s,f); delete []s; delete []f; }
624 //-----------------------------------------------------------------------------
mgl_write_json_z(HMGL gr,const char * fname,const char *)625 void MGL_EXPORT mgl_write_json_z(HMGL gr, const char *fname,const char *)
626 { _Gr_->WriteJSON(fname,true); }
mgl_write_json_z_(uintptr_t * gr,const char * fname,const char * descr,int l,int n)627 void MGL_EXPORT mgl_write_json_z_(uintptr_t *gr, const char *fname,const char *descr,int l,int n)
628 { char *s=new char[l+1]; memcpy(s,fname,l); s[l]=0;
629 char *f=new char[n+1]; memcpy(f,descr,n); f[n]=0;
630 mgl_write_json_z(_GR_,s,f); delete []s; delete []f; }
631 //-----------------------------------------------------------------------------
ExportMGLD(const char * fname,const char * descr)632 bool mglCanvas::ExportMGLD(const char *fname, const char *descr)
633 {
634 if(Pnt.size()<1 || Prm.size()<1) return true;
635 FILE *fp=fopen(fname,"wt");
636 if(!fp) return true;
637 const std::string loc = setlocale(LC_NUMERIC, "C");
638 // NOTE: I'll save Ptx. So prim type=6 is useless,and no LaTeX
639 fprintf(fp,"MGLD %lu %lu %lu %lu %d %d\n# %s\n", (unsigned long)Pnt.size(), (unsigned long)Prm.size(), (unsigned long)Txt.size(), (unsigned long)Glf.size(), Width, Height, (descr && *descr) ? descr : fname);
640 fprintf(fp,"# Vertexes: x y z c t ta u v w r g b a\n");
641 for(size_t i=0;i<Pnt.size();i++)
642 {
643 const mglPnt &q=Pnt[i];
644 fprintf(fp,"%.4g\t%.4g\t%.4g\t%.4g\t%.4g\t%.4g\t%.4g\t%.4g\t%.4g\t%.4g\t%.4g\t%.4g\t%.4g\n", q.xx, q.yy, q.zz, q.c, q.ta, q.ta, q.u, q.v, q.w, q.r, q.g, q.b, q.a);
645 }
646 fprintf(fp,"# Primitives: type n1 n2 n3 n4 id s w p\n");
647 for(size_t i=0;i<Prm.size();i++)
648 {
649 const mglPrim &p=Prm[i];
650 long long unsigned mask = p.m;
651 fprintf(fp,"%d\t%ld\t%ld\t%ld\t%ld\t%d\t%g\t%g\t%g\t%d\t%llu\n", p.type, p.n1, p.n2, p.n3, p.n4, p.id, p.s==p.s?p.s:0, p.w==p.w?p.w:0, p.p==p.p?p.p:0, p.angl, mask);
652 }
653 fprintf(fp,"# Textures: smooth alpha colors\n");
654 for(size_t i=0;i<Txt.size();i++)
655 {
656 const mglTexture &t=Txt[i];
657 fprintf(fp,"%d\t%.4g\t%s\n",t.Smooth,t.Alpha,t.Sch);
658 }
659 fprintf(fp,"# Glyphs: nt nl [trig] [line]\n");
660 for(size_t i=0;i<Glf.size();i++)
661 {
662 const mglGlyph &g=Glf[i];
663 fprintf(fp,"%ld\t%ld\n", g.nt, g.nl);
664 if(g.trig)
665 {
666 for(long j=0;j<6*g.nt;j++) fprintf(fp,"%d\t",g.trig[j]);
667 fprintf(fp,"\n");
668 }
669 if(g.line)
670 {
671 for(long j=0;j<2*g.nl;j++) fprintf(fp,"%d\t",g.line[j]);
672 fprintf(fp,"\n");
673 }
674 }
675 fclose(fp);
676 setlocale(LC_NUMERIC, loc.c_str());
677 return false;
678 }
679 //-----------------------------------------------------------------------------
mgl_export_mgld(HMGL gr,const char * fname,const char * descr)680 void MGL_EXPORT mgl_export_mgld(HMGL gr, const char *fname,const char *descr)
681 { _Gr_->ExportMGLD(fname, descr); }
mgl_export_mgld_(uintptr_t * gr,const char * fname,const char * descr,int l,int n)682 void MGL_EXPORT mgl_export_mgld_(uintptr_t *gr, const char *fname,const char *descr,int l,int n)
683 { char *s=new char[l+1]; memcpy(s,fname,l); s[l]=0;
684 char *f=new char[n+1]; memcpy(f,descr,n); f[n]=0;
685 mgl_export_mgld(_GR_,s,f); delete []s; delete []f; }
686 //-----------------------------------------------------------------------------
ImportMGLD(const char * fname,bool add)687 bool mglCanvas::ImportMGLD(const char *fname, bool add)
688 {
689 FILE *fp=fopen(fname,"rt");
690 if(!fp) return true;
691 char *buf=new char[512];
692 if(!fgets(buf,512,fp)) *buf=0;
693 if(strncmp(buf,"MGLD",4)) { delete []buf; fclose(fp); return true; }
694 unsigned long n=0,m=0,l=0,k=0, npnt=0, nglf=0;
695 int w=0,h=0,d;
696 sscanf(buf+5,"%lu%lu%lu%lu%d%d",&n,&m,&l,&k,&w,&h);
697 if(w<=0 || h<=0) { w=Width; h=Height; }
698 d = long(sqrt(double(w*h)));
699 if(n==0 || m==0 || l==0) { delete []buf; fclose(fp); return true; }
700 const std::string loc = setlocale(LC_NUMERIC, "C");
701 if(!add) { Clf(); Txt.clear(); }
702 else { ClfZB(); npnt=Pnt.size(); nglf=Glf.size(); }
703 LightScale(&B);
704 #if MGL_HAVE_PTHREAD
705 pthread_mutex_lock(&mutexGlf);
706 pthread_mutex_lock(&mutexPnt);
707 pthread_mutex_lock(&mutexPrm);
708 pthread_mutex_lock(&mutexTxt);
709 #endif
710 #pragma omp critical
711 {
712 Pnt.reserve(n); Prm.reserve(m); Txt.reserve(l); Glf.reserve(k);
713 mglPnt p; float tmp;
714 for(unsigned long i=0;i<n;i++)
715 {
716 do { if(!fgets(buf,512,fp)) *buf=0; mgl_strtrim(buf); } while(*buf=='#');
717 sscanf(buf,"%g%g%g%g%g%g%g%g%g%g%g%g%g", &p.xx, &p.yy, &p.zz, &p.c, &tmp, &p.ta, &p.u, &p.v, &p.w, &p.r, &p.g, &p.b, &p.a);
718 // rescale to current image size
719 p.xx *= Width/double(w); p.yy *= Height/double(h); p.zz *= Depth/double(d);
720 Pnt.push_back(p);
721 }
722 mglPrim q;
723 for(unsigned long i=0;i<m;i++)
724 {
725 do { if(!fgets(buf,512,fp)) *buf=0; mgl_strtrim(buf); } while(*buf=='#');
726 long long unsigned mask=MGL_SOLID_MASK;
727 sscanf(buf,"%hd%ld%ld%ld%ld%d%g%g%g%hd%llu", &q.type, &q.n1, &q.n2, &q.n3, &q.n4, &q.id, &q.s, &q.w, &q.p, &q.angl, &mask);
728 q.n1 = q.n1>=0?q.n1+npnt:-1; q.n2 = q.n2>=0?q.n2+npnt:-1;
729 switch(q.type)
730 {
731 case 3: q.n4 = q.n4>=0?q.n4+npnt:-1;
732 case 2: q.n3 = q.n3>=0?q.n3+npnt:-1; q.m = mask; break;
733 case 4: q.s *= (Width<Height?Width:Height)/double(w<h?w:h);
734 q.n4 = q.n4>=0?q.n4+nglf:-1; break;
735 }
736 Prm.push_back(q);
737 }
738 mglTexture t;
739 for(unsigned long i=0;i<l;i++)
740 {
741 int sm=0; float a;
742 do { if(!fgets(buf,512,fp)) *buf=0; mgl_strtrim(buf); } while(*buf=='#');
743 size_t j,k=0;
744 for(j=0;buf[j];j++)
745 {
746 if(buf[j]<=' ' && k) { sm++; k=0; }
747 if(buf[j]>' ') k=1;
748 if(sm==2 && k) break;
749 }
750 sscanf(buf,"%d%g", &sm, &a);
751 t.Set(buf+j, sm, a);
752 Txt.push_back(t);
753 }
754 mglGlyph g;
755 for(unsigned long i=0;i<k;i++)
756 {
757 do { if(!fgets(buf,512,fp)) *buf=0; mgl_strtrim(buf); } while(*buf=='#' || *buf==0);
758 long nt=0,nl=0;
759 sscanf(buf,"%ld%ld", &nt, &nl); g.Create(nt,nl);
760 for(long j=0;j<6*nt;j++) fscanf(fp,"%hd",g.trig+j);
761 for(long j=0;j<2*nl;j++) fscanf(fp,"%hd",g.line+j);
762 Glf.push_back(g);
763 }
764 }
765 #if MGL_HAVE_PTHREAD
766 pthread_mutex_unlock(&mutexGlf);
767 pthread_mutex_unlock(&mutexPnt);
768 pthread_mutex_unlock(&mutexPrm);
769 pthread_mutex_unlock(&mutexTxt);
770 #endif
771 setlocale(LC_NUMERIC, loc.c_str());
772 delete []buf; fclose(fp); return false;
773 }
774 //-----------------------------------------------------------------------------
mgl_import_mgld(HMGL gr,const char * fname,int add)775 void MGL_EXPORT mgl_import_mgld(HMGL gr, const char *fname, int add)
776 { _Gr_->ImportMGLD(fname, add); }
mgl_import_mgld_(uintptr_t * gr,const char * fname,int * add,int l)777 void MGL_EXPORT mgl_import_mgld_(uintptr_t *gr, const char *fname, int *add, int l)
778 { char *s=new char[l+1]; memcpy(s,fname,l); s[l]=0;
779 mgl_import_mgld(_GR_,s,*add); delete []s; }
780 //-----------------------------------------------------------------------------
781 /*void MGL_EXPORT mgl_xgl_prim(const mglPrim &q, const mglPnt &p, FILE *fp, mreal size)
782 {
783 char type = q.n4; mreal ss=size*0.35;
784 long i=q.n1;
785 switch(q.type)
786 {
787 case 0:
788 if(!strchr("xsSoO",type)) ss *= 1.1;
789 if(type=='.' || ss==0) fprintf(fp,"p %ld\n", i);
790 else switch(type) // TODO: save mark by PATCH
791 {
792 case 'P':
793 fprintf(fp,"v %g %g %g\n",p.x-ss,p.y-ss,p.z);
794 fprintf(fp,"v %g %g %g\n",p.x+ss,p.y-ss,p.z);
795 fprintf(fp,"v %g %g %g\n",p.x+ss,p.y+ss,p.z);
796 fprintf(fp,"v %g %g %g\n",p.x-ss,p.y+ss,p.z);
797 fprintf(fp,"l -4/%ld -3/%ld\n", i,i);
798 fprintf(fp,"l -3/%ld -2/%ld\n", i,i);
799 fprintf(fp,"l -2/%ld -1/%ld\n", i,i);
800 fprintf(fp,"l -1/%ld -4/%ld\n", i,i);
801 case '+':
802 fprintf(fp,"v %g %g %g\n",p.x-ss,p.y,p.z);
803 fprintf(fp,"v %g %g %g\n",p.x+ss,p.y,p.z);
804 fprintf(fp,"v %g %g %g\n",p.x,p.y+ss,p.z);
805 fprintf(fp,"v %g %g %g\n",p.x,p.y+ss,p.z);
806 fprintf(fp,"l -4/%ld -3/%ld\n", i,i);
807 fprintf(fp,"l -2/%ld -1/%ld\n", i,i); break;
808 case 'X':
809 fprintf(fp,"v %g %g %g\n",p.x-ss,p.y-ss,p.z);
810 fprintf(fp,"v %g %g %g\n",p.x+ss,p.y-ss,p.z);
811 fprintf(fp,"v %g %g %g\n",p.x+ss,p.y+ss,p.z);
812 fprintf(fp,"v %g %g %g\n",p.x-ss,p.y+ss,p.z);
813 fprintf(fp,"l -4/%ld -3/%ld\n", i,i);
814 fprintf(fp,"l -3/%ld -2/%ld\n", i,i);
815 fprintf(fp,"l -2/%ld -1/%ld\n", i,i);
816 fprintf(fp,"l -1/%ld -4/%ld\n", i,i);
817 fprintf(fp,"l -1/%ld -3/%ld\n", i,i);
818 fprintf(fp,"l -2/%ld -4/%ld\n", i,i); break;
819 case 'x':
820 fprintf(fp,"v %g %g %g\n",p.x-ss,p.y-ss,p.z);
821 fprintf(fp,"v %g %g %g\n",p.x+ss,p.y-ss,p.z);
822 fprintf(fp,"v %g %g %g\n",p.x+ss,p.y+ss,p.z);
823 fprintf(fp,"v %g %g %g\n",p.x-ss,p.y+ss,p.z);
824 fprintf(fp,"l -1/%ld -3/%ld\n", i,i);
825 fprintf(fp,"l -2/%ld -4/%ld\n", i,i); break;
826 case 'S':
827 fprintf(fp,"v %g %g %g\n",p.x-ss,p.y-ss,p.z);
828 fprintf(fp,"v %g %g %g\n",p.x+ss,p.y-ss,p.z);
829 fprintf(fp,"v %g %g %g\n",p.x+ss,p.y+ss,p.z);
830 fprintf(fp,"v %g %g %g\n",p.x-ss,p.y+ss,p.z);
831 fprintf(fp,"f -4/%ld -3/%ld -2/%ld -1/%ld\n",i,i,i,i); break;
832 case 's':
833 fprintf(fp,"v %g %g %g\n",p.x-ss,p.y-ss,p.z);
834 fprintf(fp,"v %g %g %g\n",p.x+ss,p.y-ss,p.z);
835 fprintf(fp,"v %g %g %g\n",p.x+ss,p.y+ss,p.z);
836 fprintf(fp,"v %g %g %g\n",p.x-ss,p.y+ss,p.z);
837 fprintf(fp,"l -4/%ld -3/%ld\n", i,i);
838 fprintf(fp,"l -3/%ld -2/%ld\n", i,i);
839 fprintf(fp,"l -2/%ld -1/%ld\n", i,i);
840 fprintf(fp,"l -1/%ld -4/%ld\n", i,i); break;
841 case 'D':
842 fprintf(fp,"v %g %g %g\n",p.x,p.y-ss,p.z);
843 fprintf(fp,"v %g %g %g\n",p.x+ss,p.y,p.z);
844 fprintf(fp,"v %g %g %g\n",p.x,p.y+ss,p.z);
845 fprintf(fp,"v %g %g %g\n",p.x-ss,p.y,p.z);
846 fprintf(fp,"f -4/%ld -3/%ld -2/%ld -1/%ld\n",i,i,i,i); break;
847 case 'd':
848 fprintf(fp,"v %g %g %g\n",p.x,p.y-ss,p.z);
849 fprintf(fp,"v %g %g %g\n",p.x+ss,p.y,p.z);
850 fprintf(fp,"v %g %g %g\n",p.x,p.y+ss,p.z);
851 fprintf(fp,"v %g %g %g\n",p.x-ss,p.y,p.z);
852 fprintf(fp,"l -4/%ld -3/%ld\n", i,i);
853 fprintf(fp,"l -3/%ld -2/%ld\n", i,i);
854 fprintf(fp,"l -2/%ld -1/%ld\n", i,i);
855 fprintf(fp,"l -1/%ld -4/%ld\n", i,i); break;
856 case 'Y':
857 fprintf(fp,"v %g %g %g\n",p.x,p.y-ss,p.z);
858 fprintf(fp,"v %g %g %g\n",p.x+0.8*ss,p.y+0.6*ss,p.z);
859 fprintf(fp,"v %g %g %g\n",p.x-0.8*ss,p.y+0.6*ss,p.z);
860 fprintf(fp,"l -3/%ld %ld/%ld\n", i,i,i);
861 fprintf(fp,"l -2/%ld %ld/%ld\n", i,i,i);
862 fprintf(fp,"l -1/%ld %ld/%ld\n", i,i,i); break;
863 case '*':
864 fprintf(fp,"v %g %g %g\n",p.x+ss,p.y,p.z);
865 fprintf(fp,"v %g %g %g\n",p.x-ss,p.y,p.z);
866 fprintf(fp,"l -2/%ld -1/%ld\n", i,i);
867 fprintf(fp,"v %g %g %g\n",p.x+0.6*ss,p.y+0.8*ss,p.z);
868 fprintf(fp,"v %g %g %g\n",p.x-0.6*ss,p.y-0.8*ss,p.z);
869 fprintf(fp,"l -2/%ld -1/%ld\n", i,i);
870 fprintf(fp,"v %g %g %g\n",p.x+0.6*ss,p.y-0.8*ss,p.z);
871 fprintf(fp,"v %g %g %g\n",p.x-0.6*ss,p.y+0.8*ss,p.z);
872 fprintf(fp,"l -2/%ld -1/%ld\n", i,i); break;
873 case 'T':
874 fprintf(fp,"v %g %g %g\n",p.x-ss,p.y-ss/2,p.z);
875 fprintf(fp,"v %g %g %g\n",p.x+ss,p.y-ss/2,p.z);
876 fprintf(fp,"v %g %g %g\n",p.x,p.y+ss,p.z);
877 fprintf(fp,"f -3/%ld -2/%ld -1/%ld\n", i,i,i); break;
878 case '^':
879 fprintf(fp,"v %g %g %g\n",p.x-ss,p.y-ss/2,p.z);
880 fprintf(fp,"v %g %g %g\n",p.x+ss,p.y-ss/2,p.z);
881 fprintf(fp,"v %g %g %g\n",p.x,p.y+ss,p.z);
882 fprintf(fp,"l -3/%ld -2/%ld\n", i,i);
883 fprintf(fp,"l -2/%ld -1/%ld\n", i,i);
884 fprintf(fp,"l -1/%ld -3/%ld\n", i,i); break;
885 case 'V':
886 fprintf(fp,"v %g %g %g\n",p.x-ss,p.y+ss/2,p.z);
887 fprintf(fp,"v %g %g %g\n",p.x+ss,p.y+ss/2,p.z);
888 fprintf(fp,"v %g %g %g\n",p.x,p.y-ss,p.z);
889 fprintf(fp,"f -3/%ld -2/%ld -1/%ld\n", i,i,i); break;
890 case 'v':
891 fprintf(fp,"v %g %g %g\n",p.x-ss,p.y+ss/2,p.z);
892 fprintf(fp,"v %g %g %g\n",p.x+ss,p.y+ss/2,p.z);
893 fprintf(fp,"v %g %g %g\n",p.x,p.y-ss,p.z);
894 fprintf(fp,"l -3/%ld -2/%ld\n", i,i);
895 fprintf(fp,"l -2/%ld -1/%ld\n", i,i);
896 fprintf(fp,"l -1/%ld -3/%ld\n", i,i); break;
897 case 'L':
898 fprintf(fp,"v %g %g %g\n",p.x+ss/2,p.y+ss,p.z);
899 fprintf(fp,"v %g %g %g\n",p.x+ss/2,p.y-ss,p.z);
900 fprintf(fp,"v %g %g %g\n",p.x-ss,p.y,p.z);
901 fprintf(fp,"f -3/%ld -2/%ld -1/%ld\n", i,i,i); break;
902 case '<':
903 fprintf(fp,"v %g %g %g\n",p.x+ss/2,p.y+ss,p.z);
904 fprintf(fp,"v %g %g %g\n",p.x+ss/2,p.y-ss,p.z);
905 fprintf(fp,"v %g %g %g\n",p.x-ss,p.y,p.z);
906 fprintf(fp,"l -3/%ld -2/%ld\n", i,i);
907 fprintf(fp,"l -2/%ld -1/%ld\n", i,i);
908 fprintf(fp,"l -1/%ld -3/%ld\n", i,i); break;
909 case 'R':
910 fprintf(fp,"v %g %g %g\n",p.x-ss/2,p.y+ss,p.z);
911 fprintf(fp,"v %g %g %g\n",p.x-ss/2,p.y-ss,p.z);
912 fprintf(fp,"v %g %g %g\n",p.x+ss,p.y,p.z);
913 fprintf(fp,"f -3/%ld -2/%ld -1/%ld\n", i,i,i); break;
914 case '>':
915 fprintf(fp,"v %g %g %g\n",p.x-ss/2,p.y+ss,p.z);
916 fprintf(fp,"v %g %g %g\n",p.x-ss/2,p.y-ss,p.z);
917 fprintf(fp,"v %g %g %g\n",p.x+ss,p.y,p.z);
918 fprintf(fp,"l -3/%ld -2/%ld\n", i,i);
919 fprintf(fp,"l -2/%ld -1/%ld\n", i,i);
920 fprintf(fp,"l -1/%ld -3/%ld\n", i,i); break;
921 case 'O':
922 for(long j=0;j<=20;j++)
923 fprintf(fp,"v %g %g %g\n",p.x+ss*mgl_cos[(j*36)%360],p.y+ss*mgl_cos[(270+j*36)%360],p.z);
924 for(long j=0;j<20;j++)
925 fprintf(fp,"f %ld/%ld %ld/%ld %ld/%ld\n", j-21,i, j-20,i, i,i);
926 break;
927 case 'C': fprintf(fp,"p %ld\n", i);
928 case 'o':
929 for(long j=0;j<=20;j++)
930 fprintf(fp,"v %g %g %g\n",p.x+ss*mgl_cos[(j*36)%360],p.y+ss*mgl_cos[(270+j*36)%360],p.z);
931 for(long j=0;j<20;j++)
932 fprintf(fp,"l %ld/%ld %ld/%ld\n", j-21,i, j-20,i);
933 break;
934 }
935 break;
936 case 1: fprintf(fp,"l %ld/%ld %ld/%ld\n", q.n1,q.n1, q.n2,q.n2); break;
937 case 2: fprintf(fp,"f %ld/%ld/%ld %ld/%ld/%ld %ld/%ld/%ld\n",
938 q.n1,q.n1,q.n1, q.n2,q.n2,q.n2, q.n3,q.n3,q.n3); break;
939 case 3: fprintf(fp,"f %ld/%ld/%ld %ld/%ld/%ld %ld/%ld/%ld %ld/%ld/%ld\n",
940 q.n1,q.n1,q.n1, q.n2,q.n2,q.n2, q.n3,q.n3,q.n3, q.n4,q.n4,q.n4); break;
941 case 4: break; // TODO: add glyphs export later
942 }
943 }
944 //-----------------------------------------------------------------------------
945 void mglCanvas::WriteXGL(const char *fname,const char *descr)
946 {
947 if(GetPrmNum()==0) return; // nothing to do
948 FILE *fp=fopen(fname,"wt");
949 if(!fp) return true;
950 fprintf(fp,"<WORLD>\n<NAME>%s</NAME>\n", (descr && *descr)?descr:fname);
951 fprintf(fp,"<BACKGROUND><BACKCOLOR>%g, %g, %g</BACKCOLOR></BACKGROUND>\n", BDef[0]/255., BDef[1]/255., BDef[2]/255.);
952 fprintf(fp,"<LIGHTING>\n<AMBIENT>%g, %g, %g</AMBIENT>\n",AmbBr, AmbBr, AmbBr);
953 if(get(MGL_ENABLE_LIGHT)) for(size_t i=0;i<10;i++)
954 if(light[i].n && mgl_isnan(light[i].r.x))
955 {
956 fprintf(fp, "<DIRECTIONALLIGHT>\n<DIRECTION>%g, %g, %g</DIRECTION>\n", light[i].d.x, light[i].d.y, light[i].d.z);
957 fprintf(fp, "<SPECULAR>%g, %g, %g</SPECULAR>\n</DIRECTIONALLIGHT>\n", light[i].c.r, light[i].c.g, light[i].c.b);
958 }
959 fprintf(fp,"</LIGHTING>");
960
961 // TODO: add textures
962
963 long m1=0,m2=0,m;
964 for(size_t i=0;i<Grp.size();i++) // prepare array of indirect indexing
965 { m = Grp[i].Id; if(m<m1) m1=m; if(m>m2) m2=m; }
966 long *ng = new long[m2-m1+1];
967 for(size_t i=0;i<Grp.size();i++) ng[gr->Grp[i].Id-m1] = i;
968 for(size_t i=0;i<GetPrmNum();i++) // collect data for groups
969 // it is rather expensive (extra 4b per primitive) but need for export to 3D
970 {
971 m = GetPrm(i,false).id-m1;
972 if(m>=0 && m<m2-m1+1) Grp[ng[m]].p.push_back(i);
973 }
974 delete []ng;
975
976 std::vector<long> p;
977 mglPrim q;
978 char *pg=new char[GetPntNum()];
979 for(size_t i=0;i<Grp.size();i++) // first write objects
980 {
981 p = Grp[i].p; memset(pg,0,GetPntNum());
982 fprintf(fp,"<OBJECT>\n<NAME>%s</NAME>\n<MESH>\n",Grp[i].Lbl.c_str());
983 for(size_t j=0;j<p.size();j++) // collect Pnt for this object
984 {
985 const mglPrim q=GetPrm(p[j],false); pg[q.n1]=1;
986 if(q.type==3) { pg[q.n2]=1; pg[q.n3]=1; pg[q.n4]=1; }
987 else if(q.type==1) pg[q.n2]=1;
988 else if(q.type==2) { pg[q.n2]=1; pg[q.n3]=1; }
989 }
990 for(size_t j=0;j<GetPntNum();j++) if(pg[j]) // write Pnt for this object
991 {
992 const mglPnt s=Pnt[j];
993 fprintf(fp,"<P ID=\"%u\">%g, %g, %g</P>\n",j, s.x, s.y, s.z);
994 fprintf(fp,"<N ID=\"%u\">%g, %g, %g</N>\n",j, s.x, s.y, s.z);
995 }
996 // TODO: add line styles
997 for(size_t j=0;j<p.size();j++) // now write primitives itself
998 {
999 const mglPrim q=GetPrm(p[j],false);
1000 mgl_xgl_prim(q, GetPnt(q.n1), fp, q.s*FontFactor());
1001 }
1002 fprintf(fp,"</MESH>\n</OBJECT>"); // finish with this object
1003 Grp[i].p.clear(); // we don't need indexes anymore
1004 }
1005 // TODO: try to save "ungrouped" primitives
1006
1007 fprintf(fp,"</WORLD>"); fclose(fp); delete []pg;
1008 }
1009 //-----------------------------------------------------------------------------
1010 void MGL_EXPORT mgl_write_xgl(HMGL gr, const char *fname,const char *descr)
1011 { _Gr_->WriteXGL(fname,descr); }
1012 void MGL_EXPORT mgl_write_xgl_(uintptr_t *gr, const char *fname,const char *descr,int l,int n)
1013 { char *s=new char[l+1]; memcpy(s,fname,l); s[l]=0;
1014 char *d=new char[n+1]; memcpy(d,descr,n); d[n]=0;
1015 mgl_write_xgl(_GR_,s,d); delete []s; delete []d; }*/
1016 //-----------------------------------------------------------------------------
mgl_x3d_mdef(HMGL gr,void * fp,bool gz)1017 void MGL_EXPORT mgl_x3d_mdef(HMGL gr, void *fp, bool gz)
1018 {
1019 /* bool m_p=false,m_x=false,m_d=false,m_v=false,m_t=false,
1020 m_s=false,m_a=false,m_o=false,m_T=false,
1021 m_V=false,m_S=false,m_D=false,m_Y=false,m_l=false,
1022 m_L=false,m_r=false,m_R=false,m_X=false,m_P=false;
1023 for(long i=0;i<gr->GetPrmNum();i++)
1024 {
1025 const mglPrim q = gr->GetPrm(i,false);
1026 if(q.type>0) continue;
1027 if(q.n4=='+') m_p = true;
1028 if(q.n4=='x') m_x = true;
1029 if(q.n4=='s') m_s = true;
1030 if(q.n4=='d') m_d = true;
1031 if(q.n4=='v') m_v = true;
1032 if(q.n4=='^') m_t = true;
1033 if(q.n4=='*') m_a = true;
1034 if(q.n4=='o' || q.n4=='O' || q.n4=='C') m_o = true;
1035 if(q.n4=='S') m_S = true;
1036 if(q.n4=='D') m_D = true;
1037 if(q.n4=='V') m_V = true;
1038 if(q.n4=='T') m_T = true;
1039 if(q.n4=='<') m_l = true;
1040 if(q.n4=='L') m_L = true;
1041 if(q.n4=='>') m_r = true;
1042 if(q.n4=='R') m_R = true;
1043 if(q.n4=='Y') m_Y = true;
1044 if(q.n4=='P') m_P = true;
1045 if(q.n4=='X') m_X = true;
1046 }
1047 if(m_P) { m_p=true; m_s=true; }
1048 if(m_X) { m_x=true; m_s=true; }
1049 if(m_p) mgl_printf(fp, gz, "<ProtoDeclare name='m_p'><ProtoInterface/>\n<ProtoBody>"
1050 "<LineSet vertexCount='0,1,2,3'>\n<Coordinate point='-1 0 0, 1 0 0, 0 -1 0, 0 1 0'/>"
1051 "\n</LineSet></ProtoBody></ProtoDeclare>\n");*/
1052 /*if(m_x) mgl_printf(fp, gz, "/m_x {sm sm rm s2 s2 rl 0 sm 2 mul rm sm 2 mul s2 rl d0} def\n"); // TODO
1053 * if(m_s) mgl_printf(fp, gz, "/m_s {sm sm rm 0 s2 rl s2 0 rl 0 sm 2 mul rl cp d0} def\n");
1054 * if(m_d) mgl_printf(fp, gz, "/m_d {sm 0 rm ss ss rl ss sm rl sm sm rl cp d0} def\n");
1055 * if(m_v) mgl_printf(fp, gz, "/m_v {sm ss 2 div rm s2 0 rl sm sm 1.5 mul rl d0 cp} def\n");
1056 * if(m_t) mgl_printf(fp, gz, "/m_t {sm sm 2 div rm s2 0 rl sm ss 1.5 mul rl d0 cp} def\n");
1057 * if(m_a) mgl_printf(fp, gz, "/m_a {sm 0 rm s2 0 rl sm 1.6 mul sm 0.8 mul rm ss 1.2 mul ss 1.6 mul rl 0 sm 1.6 mul rm sm 1.2 mul ss 1.6 mul rl d0} def\n");
1058 * if(m_o) mgl_printf(fp, gz, "/m_o {ss 0 360 d0 arc} def\n");
1059 * if(m_S) mgl_printf(fp, gz, "/m_S {sm sm rm 0 s2 rl s2 0 rl 0 sm 2 mul rl cp} def\n");
1060 * if(m_D) mgl_printf(fp, gz, "/m_D {sm 0 rm ss ss rl ss sm rl sm sm rl cp} def\n");
1061 * if(m_V) mgl_printf(fp, gz, "/m_V {sm ss 2 div rm s2 0 rl sm sm 1.5 mul rl cp} def\n");
1062 * if(m_T) mgl_printf(fp, gz, "/m_T {sm sm 2 div rm s2 0 rl sm ss 1.5 mul rl cp} def\n");
1063 * if(m_Y) mgl_printf(fp, gz, "/m_Y {0 sm rm 0 ss rl sm ss rl s2 0 rm sm sm rl d0} def\n");
1064 * if(m_r) mgl_printf(fp, gz, "/m_r {sm 2 div sm rm 0 s2 rl ss 1.5 mul sm rl d0 cp} def\n");
1065 * if(m_l) mgl_printf(fp, gz, "/m_l {ss 2 div sm rm 0 s2 rl sm 1.5 mul sm rl d0 cp} def\n");
1066 * if(m_R) mgl_printf(fp, gz, "/m_R {sm 2 div sm rm 0 s2 rl ss 1.5 mul sm rl cp} def\n");
1067 * if(m_L) mgl_printf(fp, gz, "/m_L {ss 2 div sm rm 0 s2 rl sm 1.5 mul sm rl cp} def\n");
1068 * if(m_P) mgl_printf(fp, gz, "/m_P {m_p 0 sm rm m_s} def\n");
1069 * if(m_X) mgl_printf(fp, gz, "/m_X {m_x ss sm rm m_s} def\n");*/
1070 // if(m_C) mgl_printf(fp, gz, "/m_C {m_c m_o} def\n");
1071 // mgl_printf(fp, gz, "\n");
1072 }
1073 //-----------------------------------------------------------------------------
mgl_x3d_prim(const mglPrim & q,const mglPnt & p,const long * pnt,void * fp,bool gz,mreal size)1074 void MGL_EXPORT mgl_x3d_prim(const mglPrim &q, const mglPnt &p, const long *pnt, void *fp,bool gz, mreal size)
1075 {
1076 // <ProtoInstance name='EmissiveMaterial'/>
1077 /* if(q.type==0) // mark
1078 {
1079 mreal x0 = p1.x,y0 = p1.y;
1080 sprintf(str,"1 lw %.2g %.2g %.2g rgb ", cp.r,cp.g,cp.b);
1081 wp=1;
1082 if(q.s!=gr->mark_size()/gr->FontFactor())
1083 {
1084 mgl_printf(fp, gz, "/ss {%g} def\n",q.s*0.4*gr->FontFactor());
1085 mgl_printf(fp, gz, "/s2 {%g} def\n",q.s*0.8*gr->FontFactor());
1086 mgl_printf(fp, gz, "/sm {-%g} def\n",q.s*0.4*gr->FontFactor());
1087 }
1088 switch(q.n4)
1089 {
1090 case '+': mgl_printf(fp, gz, "np %g %g mt m_p %sdr\n",x0,y0,str); break;
1091 case 'x': mgl_printf(fp, gz, "np %g %g mt m_x %sdr\n",x0,y0,str); break;
1092 case 's': mgl_printf(fp, gz, "np %g %g mt m_s %sdr\n",x0,y0,str); break;
1093 case 'd': mgl_printf(fp, gz, "np %g %g mt m_d %sdr\n",x0,y0,str); break;
1094 case '*': mgl_printf(fp, gz, "np %g %g mt m_a %sdr\n",x0,y0,str); break;
1095 case 'v': mgl_printf(fp, gz, "np %g %g mt m_v %sdr\n",x0,y0,str); break;
1096 case '^': mgl_printf(fp, gz, "np %g %g mt m_t %sdr\n",x0,y0,str); break;
1097 case 'S': mgl_printf(fp, gz, "np %g %g mt m_S %sfill\n",x0,y0,str); break;
1098 case 'D': mgl_printf(fp, gz, "np %g %g mt m_D %sfill\n",x0,y0,str); break;
1099 case 'V': mgl_printf(fp, gz, "np %g %g mt m_V %sfill\n",x0,y0,str); break;
1100 case 'T': mgl_printf(fp, gz, "np %g %g mt m_T %sfill\n",x0,y0,str); break;
1101 case 'o': mgl_printf(fp, gz, "%g %g m_o %sdr\n",x0,y0,str);break;
1102 case 'O': mgl_printf(fp, gz, "%g %g m_o %sfill\n",x0,y0,str);break;
1103 case 'Y': mgl_printf(fp, gz, "np %g %g mt m_Y %sdr\n",x0,y0,str); break;
1104 case '<': mgl_printf(fp, gz, "np %g %g mt m_l %sdr\n",x0,y0,str); break;
1105 case '>': mgl_printf(fp, gz, "np %g %g mt m_r %sdr\n",x0,y0,str); break;
1106 case 'L': mgl_printf(fp, gz, "np %g %g mt m_L %sfill\n",x0,y0,str); break;
1107 case 'R': mgl_printf(fp, gz, "np %g %g mt m_R %sfill\n",x0,y0,str); break;
1108 case 'P': mgl_printf(fp, gz, "np %g %g mt m_P %sdr\n",x0,y0,str); break;
1109 case 'X': mgl_printf(fp, gz, "np %g %g mt m_X %sdr\n",x0,y0,str); break;
1110 case 'C': mgl_printf(fp, gz, "%g %g m_o %g %g m_c %sdr\n",x0,y0,x0,y0,str); break;
1111 default: mgl_printf(fp, gz, "%g %g m_c %sfill\n",x0,y0,str);
1112 }
1113 if(q.s!=gr->mark_size()/gr->FontFactor())
1114 {
1115 mgl_printf(fp, gz, "/ss {%g} def\n",0.4*gr->mark_size());
1116 mgl_printf(fp, gz, "/s2 {%g} def\n",0.8*gr->mark_size());
1117 mgl_printf(fp, gz, "/sm {-%g} def\n",0.4*gr->mark_size());
1118 }
1119 }
1120 else if(q.type==3) // quad
1121 {
1122 const mglPnt p2=gr->GetPnt(q.n2), p3=gr->GetPnt(q.n3), p4=gr->GetPnt(q.n4);
1123 mgl_printf(fp, gz, "np %g %g mt %g %g ll %g %g ll %g %g ll cp %sfill\n",
1124 p1.x, p1.y, p2.x, p2.y, p4.x, p4.y, p3.x, p3.y, str);
1125 }
1126 else if(q.type==2) // trig
1127 {
1128 const mglPnt p2=gr->GetPnt(q.n2), p3=gr->GetPnt(q.n3);
1129 mgl_printf(fp, gz, "np %g %g mt %g %g ll %g %g ll cp %sfill\n",
1130 p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, str);
1131 }
1132 else if(q.type==1) // line
1133 {
1134 sprintf(str,"%.2g lw %.2g %.2g %.2g rgb ", q.w>1 ? q.w:1., cp.r,cp.g,cp.b);
1135 wp = q.w>1 ? q.w:1; st = q.n3;
1136 put_line(gr,fp,gz,i,wp,cp,st, "np %g %g mt ", "%g %g ll ", false, 1);
1137 const char *sd = mgl_get_dash(q.n3,q.w);
1138 if(sd && sd[0]) mgl_printf(fp, gz, "%s [%s] %g sd dr\n",str,sd,q.w*q.s);
1139 else mgl_printf(fp, gz, "%s d0 dr\n",str);
1140 }
1141 else if(q.type==4) // glyph
1142 {
1143 mreal ss = q.s/2, xx = p1.u, yy = p1.v, zz = p1.w;
1144 mgl_printf(fp, gz, "gsave\t%g %g translate %g %g scale %g rotate %s\n",
1145 p1.x, p1.y, ss, ss, -q.w, str);
1146 if(q.n3&8) // this is "line"
1147 {
1148 mreal dy = 0.004,f=fabs(zz);
1149 mgl_printf(fp, gz, "np %g %g mt %g %g ll %g %g ll %g %g ll cp ",
1150 xx,yy+dy, xx+f,yy+dy, xx+f,yy-dy, xx,yy-dy);
1151 }
1152 else
1153 mgl_printf(fp, gz, "%.3g %.3g translate %g %g scale %c%c_%04x ",
1154 xx, yy, zz, zz, q.n3&1?'b':'n', q.n3&2?'i':'n', q.n4);
1155 if(q.n3&4) mgl_printf(fp, gz, "dr");
1156 else mgl_printf(fp, gz, "eofill");
1157 mgl_printf(fp, gz, " grestore\n");
1158 }*/
1159 }
1160 //-----------------------------------------------------------------------------
mgl_write_x3d(HMGL gr,const char * fname,const char * descr)1161 void MGL_EXPORT mgl_write_x3d(HMGL gr, const char *fname,const char *descr)
1162 {
1163 if(gr->GetPrmNum()<1) return;
1164 time_t now; time(&now);
1165
1166 bool gz = fname[strlen(fname)-1]=='z';
1167 void *fp = gz ? (void*)gzopen(fname,"wt") : (void*)fopen(fname,"wt");
1168 if(!fp) { gr->SetWarn(mglWarnOpen,fname); return; }
1169 const std::string loc = setlocale(LC_NUMERIC, "C");
1170 mgl_printf(fp, gz, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
1171 mgl_printf(fp, gz, "<!DOCTYPE X3D PUBLIC \"ISO//Web3D//DTD X3D 3.0//EN\" \"http://www.web3d.org/specifications/x3d-3.0.dtd\">\n");
1172 mgl_printf(fp, gz, "<X3D profile='Immersive'>\n<head>\n<meta name='filename' content='%s'/>\n",fname);
1173 mgl_printf(fp, gz, "<meta name='description' content='%s'/>\n",(descr && *descr)?descr:fname);
1174 mgl_printf(fp, gz, "<meta name='created' content='%s'/>\n",ctime(&now));
1175 mgl_printf(fp, gz, "<meta name='generator' content='MathGL, http://mathgl.sourceforge.net/'/>\n");
1176 mgl_printf(fp, gz, "</head>\n<Scene>\n");
1177
1178 // 1. first we have to define proto for marks and glyphs
1179 mgl_x3d_mdef(gr, fp, gz);
1180
1181 // here should be defined textures ... but since X3D support RGBA then omit it in this version
1182
1183 // 2. now find group for primitives
1184 long m1=0,m2=0,m;
1185 for(size_t i=0;i<gr->Grp.size();i++) // prepare array of indirect indexing
1186 { m = gr->Grp[i].Id; if(m<m1) m1=m; if(m>m2) m2=m; }
1187 long *ng = new long[m2-m1+1];
1188 for(size_t i=0;i<gr->Grp.size();i++) ng[gr->Grp[i].Id-m1] = i;
1189 for(long i=0;i<gr->GetPrmNum();i++) // collect data for groups
1190 // it is rather expensive (extra 4b per primitive) but need for export to 3D
1191 {
1192 m = gr->GetPrm(i,false).id-m1;
1193 if(m>=0 && m<m2-m1+1) gr->Grp[ng[m]].p.push_back(i);
1194 }
1195 delete []ng;
1196
1197 // primitive definition in groups
1198 long npnt = gr->GetPntNum();
1199 long *pnt=new long[npnt];
1200 mglPrim q;
1201 for(size_t i=0;i<gr->Grp.size();i++)
1202 {
1203 mgl_printf(fp,gz,"<Group><!--%s-->\n",gr->Grp[i].Lbl.c_str());
1204 std::vector<long> &p = gr->Grp[i].p;
1205
1206 // define coordinates, colors and so on
1207 long line=-1, face=-1, other=-1;
1208 for(size_t j=0;j<p.size();j++) // find points for this group
1209 {
1210 const mglPrim &q=gr->GetPrm(p[j],false);
1211 if(q.type==1) line=q.n1; // find kind of primitives in the group
1212 if(q.type==2 || q.type==3) face =q.n1;
1213 if(q.type>3 || q.type==0) other=q.n1;
1214 }
1215
1216 // now save lines
1217 if(line>=0)
1218 {
1219 mglColor c=gr->GetPntC(line);
1220 bool same=true; // check if there are the same colors for all line segments
1221 for(size_t j=0;j<p.size();j++)
1222 {
1223 const mglPrim &q=gr->GetPrm(p[j],false);
1224 if(q.type==1 && c!=gr->GetPntC(q.n1)) same=false;
1225 }
1226 memset(pnt,-1,npnt*sizeof(long));
1227 for(size_t j=0,k=0;j<p.size();j++) // rearrange points for this group
1228 {
1229 const mglPrim &q=gr->GetPrm(p[j],false);
1230 if(q.type!=1) continue;
1231 if(q.n1>=0 && pnt[q.n1]<0) { pnt[q.n1]=k; k++; }
1232 if(q.n2>=0 && pnt[q.n2]<0) { pnt[q.n2]=k; k++; }
1233 }
1234 mgl_printf(fp, gz, "<Shape><Coordinate DEF='Lpnts_%ld' point='",i);
1235 for(long j=0;j<gr->GetPntNum();j++) if(pnt[j]>=0)
1236 { const mglPnt &p=gr->GetPnt(j); mgl_printf(fp, gz, "%g %g %g, ", p.x,p.y,p.z); }
1237 mgl_printf(fp, gz, "0.0 0.0 0.0'/>");
1238 mgl_printf(fp, gz, "<Color DEF='Lclrs_%ld' color='",i);
1239 for(long j=0;j<gr->GetPntNum();j++) if(pnt[j]>=0)
1240 { const mglPnt &p=gr->GetPnt(j); mgl_printf(fp, gz, "%g %g %g, ", p.r,p.g,p.b); }
1241 mgl_printf(fp, gz, "0.0 0.0 0.0'/>");
1242
1243 // TODO save IndexedLineSet here + manual color is same==true
1244
1245 mgl_printf(fp, gz, "</Shape>");
1246 }
1247
1248 // now save faces
1249 if(face>=0)
1250 {
1251 mglColor c=gr->GetPntC(face);
1252 bool same=true; // check if there are the same colors for all line segments
1253 for(size_t j=0;j<p.size();j++)
1254 {
1255 const mglPrim &q=gr->GetPrm(p[j],false);
1256 if((q.type==2 || q.type==3) && c!=gr->GetPntC(q.n1)) same=false;
1257 }
1258 memset(pnt,-1,npnt*sizeof(long));
1259 for(size_t j=0,k=0;j<p.size();j++) // rearrange points for this group
1260 {
1261 const mglPrim &q=gr->GetPrm(p[j],false);
1262 if(q.type!=2 && q.type!=3) continue;
1263 if(q.n1>=0 && pnt[q.n1]<0) { pnt[q.n1]=k; k++; }
1264 if(q.n2>=0 && pnt[q.n2]<0) { pnt[q.n2]=k; k++; }
1265 if(q.n3>=0 && pnt[q.n3]<0) { pnt[q.n3]=k; k++; }
1266 if(q.type==3 && q.n4>=0 && pnt[q.n4]<0) { pnt[q.n4]=k; k++; }
1267 }
1268 mgl_printf(fp, gz, "<Shape><Coordinate DEF='Fpnts_%ld' point='",i);
1269 for(long j=0;j<gr->GetPntNum();j++) if(pnt[j]>=0)
1270 { const mglPnt &p=gr->GetPnt(j); mgl_printf(fp, gz, "%g %g %g, ", p.x,p.y,p.z); }
1271 mgl_printf(fp, gz, "0.0 0.0 0.0'/>");
1272 mgl_printf(fp, gz, "<Color DEF='Fclrs_%ld' color='",i);
1273 for(long j=0;j<gr->GetPntNum();j++) if(pnt[j]>=0)
1274 { const mglPnt &p=gr->GetPnt(j); mgl_printf(fp, gz, "%g %g %g, ", p.r,p.g,p.b); }
1275 mgl_printf(fp, gz, "0.0 0.0 0.0'/>");
1276
1277 // TODO save IndexedLineSet here + manual color is same==true
1278
1279 mgl_printf(fp, gz, "</Shape>");
1280 }
1281
1282 // now save other primitives
1283 if(other>=0)
1284 {
1285 /* memset(pnt,-1,npnt*sizeof(long));
1286 for(j=0,k=0;j<p.size();j++) // rearrange points for this group
1287 {
1288 const mglPrim &q=gr->GetPrm(p[j],false);
1289 if(q.type!=2 && q.type!=3) continue;
1290 if(q.n1>=0 && pnt[q.n1]<0) { pnt[q.n1]=k; k++; }
1291 if(q.n2>=0 && pnt[q.n2]<0) { pnt[q.n2]=k; k++; }
1292 if(q.n3>=0 && pnt[q.n3]<0) { pnt[q.n3]=k; k++; }
1293 if(q.type==3 && q.n4>=0 && pnt[q.n4]<0) { pnt[q.n4]=k; k++; }
1294 }
1295 mgl_printf(fp, gz, "<Shape><Coordinate DEF='Fpnts_%ld' point='",i);
1296 for(j=0;j<gr->GetPntNum();j++) if(pnt[j]>=0)
1297 { const mglPnt &p=gr->GetPnt(j); mgl_printf(fp, gz, "%g %g %g, ", p.x,p.y,p.z); }
1298 mgl_printf(fp, gz, "0.0 0.0 0.0'/>");
1299 mgl_printf(fp, gz, "<Color DEF='Fclrs_%ld' color='",i);
1300 for(j=0;j<gr->GetPntNum();j++) if(pnt[j]>=0)
1301 { const mglPnt &p=gr->GetPnt(j); mgl_printf(fp, gz, "%g %g %g, ", p.r,p.g,p.b); }
1302 mgl_printf(fp, gz, "0.0 0.0 0.0'/>");
1303
1304 // TODO save IndexedLineSet here + manual color is same==true
1305
1306 mgl_printf(fp, gz, "</Shape>");*/
1307 }
1308 // no normals since mathgl ones are "signless" -- x3d should calculate it by itself
1309
1310 for(size_t j=0;j<p.size();j++)
1311 {
1312 const mglPrim &q=gr->GetPrm(p[j],false); // TODO: collect by type (quads,trig,line) and draw together???
1313 mgl_x3d_prim(q, gr->GetPnt(q.n1), pnt, fp,gz, q.s*gr->FontFactor());
1314 }
1315 mgl_printf(fp,gz,"</Group><!--%s-->\n",gr->Grp[i].Lbl.c_str());
1316 gr->Grp[i].p.clear(); // we don't need indexes anymore
1317 }
1318 mgl_printf(fp, gz, "</Scene>\n");
1319 if(gz) gzclose((gzFile)fp); else fclose((FILE *)fp);
1320 setlocale(LC_NUMERIC, loc.c_str());
1321 delete []pnt;
1322 }
mgl_write_x3d_(uintptr_t * gr,const char * fname,const char * descr,int l,int n)1323 void MGL_EXPORT mgl_write_x3d_(uintptr_t *gr, const char *fname,const char *descr,int l,int n)
1324 { char *s=new char[l+1]; memcpy(s,fname,l); s[l]=0;
1325 char *d=new char[n+1]; memcpy(d,descr,n); d[n]=0;
1326 mgl_write_x3d(_GR_,s,d); delete []s; delete []d; }
1327 //-----------------------------------------------------------------------------
1328