1 /****************************************************************************
2 * MeshLab                                                           o o     *
3 * An extendible mesh processor                                    o     o   *
4 *                                                                _   O  _   *
5 * Copyright(C) 2005, 2006                                          \/)\/    *
6 * Visual Computing Lab                                            /\/|      *
7 * ISTI - Italian National Research Council                           |      *
8 *                                                                    \      *
9 * All rights reserved.                                                      *
10 *                                                                           *
11 * This program is free software; you can redistribute it and/or modify      *
12 * it under the terms of the GNU General Public License as published by      *
13 * the Free Software Foundation; either version 2 of the License, or         *
14 * (at your option) any later version.                                       *
15 *                                                                           *
16 * This program is distributed in the hope that it will be useful,           *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of            *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
19 * GNU General Public License (http://www.gnu.org/licenses/gpl.txt)          *
20 * for more details.                                                         *
21 *                                                                           *
22 ****************************************************************************/
23 #include "io_json.h"
24 
25 #include <string>
26 #include <fstream>
27 
28 #include <vcg/complex/algorithms/attribute_seam.h>
29 
30 #include <QString>
31 #include <QFile>
32 
JSONIOPlugin(void)33 JSONIOPlugin::JSONIOPlugin(void) : MeshIOInterface()
34 {
35 	;
36 }
37 
~JSONIOPlugin(void)38 JSONIOPlugin::~JSONIOPlugin(void)
39 {
40 	;
41 }
42 
open(const QString & formatName,const QString & fileName,MeshModel & m,int & mask,const RichParameterSet & parlst,vcg::CallBackPos * cb,QWidget * parent)43 bool JSONIOPlugin::open(const QString & formatName, const QString & fileName, MeshModel & m, int & mask, const RichParameterSet & parlst, vcg::CallBackPos * cb, QWidget * parent)
44 {
45 	(void)formatName;
46 	(void)fileName;
47 	(void)m;
48 	(void)mask;
49 	(void)parlst;
50 	(void)cb;
51 	(void)parent;
52 
53 	return false;
54 }
55 
save(const QString & formatName,const QString & fileName,MeshModel & m,const int mask,const RichParameterSet & par,vcg::CallBackPos * cb,QWidget * parent)56 bool JSONIOPlugin::save(const QString & formatName,const QString & fileName, MeshModel & m, const int mask, const RichParameterSet & par, vcg::CallBackPos * cb, QWidget * parent)
57 {
58 	(void)par;
59 	(void)cb;
60 	(void)parent;
61   vcg::tri::Allocator<CMeshO>::CompactVertexVector(m.cm);
62   vcg::tri::Allocator<CMeshO>::CompactFaceVector(m.cm);
63 
64   const size_t maxValuesPerLine = 10; // must be > 0
65 
66 	if (formatName.toUpper() != tr("JSON")) return false;
67 
68 	const bool hasPerVertexPosition = true;
69 	const bool hasPerVertexNormal   = ((mask & vcg::tri::io::Mask::IOM_VERTNORMAL)   != 0) && m.hasDataMask(MeshModel::MM_VERTNORMAL);
70 	const bool hasPerVertexColor    = ((mask & vcg::tri::io::Mask::IOM_VERTCOLOR)    != 0) && m.hasDataMask(MeshModel::MM_VERTCOLOR);
71 	const bool hasPerVertexTexCoord = ((mask & vcg::tri::io::Mask::IOM_VERTTEXCOORD) != 0) && m.hasDataMask(MeshModel::MM_VERTTEXCOORD);
72 
73 	const CMeshO & cm = m.cm;
74 
75 	const std::string filename = QFile::encodeName(fileName).constData();
76 
77 	std::ofstream os(filename.c_str());
78 	if (!os.is_open()) return false;
79 
80 	os << "{" << std::endl;
81 
82 	os << "  \"version\" : \"0.1.0\"," << std::endl;
83 	os << std::endl;
84 
85 	os << "  \"comment\" : \"Generated by MeshLab JSON Exporter\"," << std::endl;
86 	os << std::endl;
87 
88 	os << "  \"id\"      : 1," << std::endl;
89 	os << "  \"name\"    : \"mesh\"," << std::endl;
90 	os << std::endl;
91 
92 	os << "  \"vertices\" :" << std::endl;
93 	os << "  [" << std::endl;
94 
95 	bool prevDone = false;
96 
97 	if (hasPerVertexPosition)
98 	{
99 		os << "    {" << std::endl;
100 		os << "      \"name\"       : \"position_buffer\"," << std::endl;
101 		os << "      \"size\"       : 3," << std::endl;
102 		os << "      \"type\"       : \"float32\"," << std::endl;
103 		os << "      \"normalized\" : false," << std::endl;
104 		os << "      \"values\"     :" << std::endl;
105 		os << "      [" << std::endl;
106 
107 		size_t it = 0;
108 		const size_t sz = cm.vert.size();
109 		while (it < sz)
110 		{
111 			const size_t n = std::min(it + maxValuesPerLine, sz);
112 			if (n > 0)
113 			{
114 				os << "        ";
115 				{
116 					const CMeshO::VertexType::CoordType & p = cm.vert[it].cP();
117 					os << p[0] << ", " << p[1] << ", " << p[2];
118 					it++;
119 				}
120 				for (; it<n; ++it)
121 				{
122 					const CMeshO::VertexType::CoordType & p = cm.vert[it].cP();
123 					os << ", " << p[0] << ", " << p[1] << ", " << p[2];
124 				}
125 				if (it <= (sz - 1))
126 				{
127 					os << ",";
128 				}
129 				os << std::endl;
130 			}
131 		}
132 
133 		os << "      ]" << std::endl;
134 		os << "    }";
135 
136 		prevDone = true;
137 	}
138 
139 	if (hasPerVertexNormal)
140 	{
141 		if (prevDone)
142 		{
143 			os << "," << std::endl;
144 			os << std::endl;
145 		}
146 		os << "    {" << std::endl;
147 		os << "      \"name\"       : \"normal_buffer\"," << std::endl;
148 		os << "      \"size\"       : 3," << std::endl;
149 		os << "      \"type\"       : \"float32\"," << std::endl;
150 		os << "      \"normalized\" : false," << std::endl;
151 		os << "      \"values\"     :" << std::endl;
152 		os << "      [" << std::endl;
153 
154 		size_t it = 0;
155 		const size_t sz = cm.vert.size();
156 		while (it < sz)
157 		{
158 			const size_t n = std::min(it + maxValuesPerLine, sz);
159 			if (n > 0)
160 			{
161 				os << "        ";
162 				{
163 					const CMeshO::VertexType::NormalType & n = cm.vert[it].cN();
164 					os << n[0] << ", " << n[1] << ", " << n[2];
165 					it++;
166 				}
167 				for (; it<n; ++it)
168 				{
169 					const CMeshO::VertexType::NormalType & n = cm.vert[it].cN();
170 					os << ", " << n[0] << ", " << n[1] << ", " << n[2];
171 				}
172 				if (it <= (sz - 1))
173 				{
174 					os << ",";
175 				}
176 				os << std::endl;
177 			}
178 		}
179 
180 		os << "      ]" << std::endl;
181 		os << "    }";
182 
183 		prevDone = true;
184 	}
185 
186 	if (hasPerVertexColor)
187 	{
188 		if (prevDone)
189 		{
190 			os << "," << std::endl;
191 			os << std::endl;
192 		}
193 		os << "    {" << std::endl;
194 		os << "      \"name\"       : \"color_buffer\"," << std::endl;
195 		os << "      \"size\"       : 4," << std::endl;
196 		os << "      \"type\"       : \"uint8\"," << std::endl;
197 		os << "      \"normalized\" : true," << std::endl;
198 		os << "      \"values\"     :" << std::endl;
199 		os << "      [" << std::endl;
200 
201 		size_t it = 0;
202 		const size_t sz = cm.vert.size();
203 		while (it < sz)
204 		{
205 			const size_t n = std::min(it + maxValuesPerLine, sz);
206 			if (n > 0)
207 			{
208 				os << "        ";
209 				{
210 					const CMeshO::VertexType::ColorType & c = cm.vert[it].cC();
211 					os << int(c[0]) << ", " << int(c[1]) << ", " << int(c[2]) << ", " << int(c[3]);
212 					it++;
213 				}
214 				for (; it<n; ++it)
215 				{
216 					const CMeshO::VertexType::ColorType & c = cm.vert[it].cC();
217 					os << ", " << int(c[0]) << ", " << int(c[1]) << ", " << int(c[2]) << ", " << int(c[3]);
218 				}
219 				if (it <= (sz - 1))
220 				{
221 					os << ",";
222 				}
223 				os << std::endl;
224 			}
225 		}
226 
227 		os << "      ]" << std::endl;
228 		os << "    }";
229 
230 		prevDone = true;
231 	}
232 
233 	if (hasPerVertexTexCoord)
234 	{
235 		if (prevDone)
236 		{
237 			os << "," << std::endl;
238 			os << std::endl;
239 		}
240 		os << "    {" << std::endl;
241 		os << "      \"name\"       : \"texcoord_buffer\"," << std::endl;
242 		os << "      \"size\"       : 2," << std::endl;
243 		os << "      \"type\"       : \"float32\"," << std::endl;
244 		os << "      \"normalized\" : false," << std::endl;
245 		os << "      \"values\"     :" << std::endl;
246 		os << "      [" << std::endl;
247 
248 		size_t it = 0;
249 		const size_t sz = cm.vert.size();
250 		while (it < sz)
251 		{
252 			const size_t n = std::min(it + maxValuesPerLine, sz);
253 			if (n > 0)
254 			{
255 				os << "        ";
256 				{
257 					const CMeshO::VertexType::TexCoordType & t = cm.vert[it].cT();
258 					os << t.P()[0] << ", " << t.P()[1];
259 					it++;
260 				}
261 				for (; it<n; ++it)
262 				{
263 					const CMeshO::VertexType::TexCoordType & t = cm.vert[it].cT();
264 					os << ", " << t.P()[0] << ", " << t.P()[1];
265 				}
266 				if (it <= (sz - 1))
267 				{
268 					os << ",";
269 				}
270 				os << std::endl;
271 			}
272 		}
273 
274 		os << "      ]" << std::endl;
275 		os << "    }";
276 
277 		prevDone = true;
278 	}
279 
280 	if (prevDone)
281 	{
282 		os << std::endl;
283 	}
284 
285 	os << "  ]," << std::endl;
286 	os << std::endl;
287 
288 	os << "  \"connectivity\" :" << std::endl;
289 	os << "  [" << std::endl;
290 
291 	if ((m.cm.vn > 0) && (m.cm.fn > 0))
292 	{
293 		os << "    {" << std::endl;
294 		os << "      \"name\"      : \"triangles\"," << std::endl;
295 		os << "      \"mode\"      : \"triangles_list\"," << std::endl;
296 		os << "      \"indexed\"   : true," << std::endl;
297 		os << "      \"indexType\" : \"uint32\"," << std::endl;
298 		os << "      \"indices\"   :" << std::endl;
299 		os << "      [" << std::endl;
300 		{
301 			const CMeshO::VertexType * v0 = &(m.cm.vert[0]);
302 
303 			size_t k = 0;
304 			size_t c = 0;
305 			const size_t sz = cm.fn;
306 			while (c < sz)
307 			{
308 				const size_t n = std::min(c + maxValuesPerLine, sz);
309 				if (n > 0)
310 				{
311 					os << "        ";
312 					{
313 						while (cm.face[k].IsD()) k++;
314 						const CMeshO::FaceType & f = cm.face[k];
315 						os << int(f.cV(0) - v0) << ", " << int(f.cV(1) - v0) << ", " << int(f.cV(2) - v0);
316 						c++;
317 						k++;
318 					}
319 					for (; c<n; ++c)
320 					{
321 						while (cm.face[k].IsD()) k++;
322 						const CMeshO::FaceType & f = cm.face[k];
323 						os << ", " << int(f.cV(0) - v0) << ", " << int(f.cV(1) - v0) << ", " << int(f.cV(2) - v0);
324 						k++;
325 					}
326 					if (c <= (sz - 1))
327 					{
328 						os << ",";
329 					}
330 					os << std::endl;
331 				}
332 			}
333 		}
334 		os << "      ]" << std::endl;
335 		os << "    }" << std::endl;
336 	}
337 
338 	os << "  ]," << std::endl;
339 	os << std::endl;
340 
341 	os << "  \"mapping\" :" << std::endl;
342 	os << "  [" << std::endl;
343 	if ((m.cm.vn > 0) && (m.cm.fn > 0))
344 	{
345 		os << "    {" << std::endl;
346 		os << "      \"name\"       : \"standard\"," << std::endl;
347 		os << "      \"primitives\" : \"triangles\"," << std::endl;
348 		os << "      \"attributes\" :" << std::endl;
349 		os << "      [" << std::endl;
350 
351 		prevDone = false;
352 		if (hasPerVertexPosition)
353 		{
354 			os << "        {" << std::endl;
355 			os << "          \"source\"   : \"position_buffer\"," << std::endl;
356 			os << "          \"semantic\" : \"position\"," << std::endl;
357 			os << "          \"set\"      : 0" << std::endl;
358 			os << "        }";
359 			prevDone = true;
360 		}
361 		if (hasPerVertexNormal)
362 		{
363 			if (prevDone)
364 			{
365 				os << "," << std::endl;
366 			}
367 			os << "        {" << std::endl;
368 			os << "          \"source\"   : \"normal_buffer\"," << std::endl;
369 			os << "          \"semantic\" : \"normal\"," << std::endl;
370 			os << "          \"set\"      : 0" << std::endl;
371 			os << "        }";
372 			prevDone = true;
373 		}
374 		if (hasPerVertexColor)
375 		{
376 			if (prevDone)
377 			{
378 				os << "," << std::endl;
379 			}
380 			os << "        {" << std::endl;
381 			os << "          \"source\"   : \"color_buffer\"," << std::endl;
382 			os << "          \"semantic\" : \"color\"," << std::endl;
383 			os << "          \"set\"      : 0" << std::endl;
384 			os << "        }";
385 			prevDone = true;
386 		}
387 		if (hasPerVertexTexCoord)
388 		{
389 			if (prevDone)
390 			{
391 				os << "," << std::endl;
392 			}
393 			os << "        {" << std::endl;
394 			os << "          \"source\"   : \"texcoord_buffer\"," << std::endl;
395 			os << "          \"semantic\" : \"texcoord\"," << std::endl;
396 			os << "          \"set\"      : 0" << std::endl;
397 			os << "        }";
398 			prevDone = true;
399 		}
400 
401 		if (prevDone)
402 		{
403 			os << std::endl;
404 		}
405 
406 		os << "      ]" << std::endl;
407 		os << "    }" << std::endl;
408 	}
409 	os << "  ]," << std::endl;
410 	os << std::endl;
411 
412 	os << "  \"custom\" : null" << std::endl;
413 
414 	os << "}" << std::endl;
415 
416 	os.close();
417 
418 	return true;
419 }
420 
421 /*
422 	returns the list of the file's type which can be imported
423 */
importFormats(void) const424 QList<MeshIOInterface::Format> JSONIOPlugin::importFormats(void) const
425 {
426 	QList<Format> formatList;
427 	//formatList << Format("JavaScript JSON", tr("JSON"));
428 	return formatList;
429 }
430 
431 /*
432 	returns the list of the file's type which can be exported
433 */
exportFormats(void) const434 QList<MeshIOInterface::Format> JSONIOPlugin::exportFormats(void) const
435 {
436 	QList<Format> formatList;
437 	formatList << Format("JavaScript JSON", tr("JSON"));
438 	return formatList;
439 }
440 
441 /*
442 	returns the mask on the basis of the file's type.
443 	otherwise it returns 0 if the file format is unknown
444 */
GetExportMaskCapability(QString & format,int & capability,int & defaultBits) const445 void JSONIOPlugin::GetExportMaskCapability(QString & format, int & capability, int & defaultBits) const
446 {
447 	capability = 0;
448 
449 	if (format.toUpper() == tr("JSON"))
450 	{
451 		// vertex
452 		capability |= vcg::tri::io::Mask::IOM_VERTNORMAL;
453 		capability |= vcg::tri::io::Mask::IOM_VERTCOLOR;
454 		capability |= vcg::tri::io::Mask::IOM_VERTTEXCOORD;
455 
456 		// face
457 		//capability |= vcg::tri::io::Mask::IOM_FACECOLOR;
458 		//capability |= vcg::tri::io::Mask::IOM_FACENORMAL;
459 
460 		// wedge
461 		//capability |= vcg::tri::io::Mask::IOM_WEDGTEXCOORD;
462 		//capability |= vcg::tri::io::Mask::IOM_WEDGNORMAL;
463 		//capability |= vcg::tri::io::Mask::IOM_WEDGCOLOR;
464 
465 		defaultBits = capability;
466 	}
467 }
468 
469 MESHLAB_PLUGIN_NAME_EXPORTER(JSONIOPlugin)
470