HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GA_PrimitiveJSON.h
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * NAME: GA_PrimitiveJSON.h ( GA Library, C++)
7  *
8  * COMMENTS:
9  */
10 
11 #ifndef __GA_PrimitiveJSON__
12 #define __GA_PrimitiveJSON__
13 
14 #include "GA_API.h"
15 #include <UT/UT_JSONValue.h>
16 #include <SYS/SYS_Types.h>
17 
18 class UT_JSONWriter;
19 class UT_JSONParser;
20 class UT_FSA;
21 class GA_Primitive;
22 class GA_SaveMap;
23 class GA_LoadMap;
24 class UT_StringArray;
25 
26 /// Structure to allow GA_JSONUniformBlock to delete whatever data may be
27 /// cached on it using a virtual destructor.
29 {
30  virtual ~GA_JSONUniformData() {}
31 };
32 
33 /// This allows primitives cache parsed uniform data, to avoid having to
34 /// re-parse it for every primitive using the same data. That had been
35 /// a significant bottleneck for curve bases, but it should save time
36 /// for the closed flag on all faces as well.
38 {
40  : myMap(NULL)
41  , myData(NULL)
42  {}
44  {
45  delete myMap;
46  delete myData;
47  }
50 };
51 
52 /// @brief Provide a JSON interface to a primitive
53 ///
54 /// This class is used in saving and loading of geometry.
55 ///
56 /// @see GA_PrimitiveDefinition, UT_JSONWriter, UT_JSONParser
57 ///
58 /// When sequences of primitives appear in order in the geometry, it's possible
59 /// to compact the storage by saving the primitive instance data in a "run".
60 /// This is done by storing the "fields" which appear for each primitive. The
61 /// run data is an array with each item in the array representing the data
62 /// fields for the individual primitive.
63 ///
64 /// This eliminates the repetition of the JSON keys for each primitive.
65 /// For example, the following two objects represent the same data:
66 /// @code
67 /// "primitives" : [
68 /// [ ["type":"polygon"], ["vertices":[0,1,2], "closed":true ] ],
69 /// [ ["type":"polygon"], ["vertices":[3,4,5], "closed":true ] ],
70 /// [ ["type":"polygon"], ["vertices":[6,7,8], "closed":true ] ],
71 /// [ ["type":"polygon"], ["vertices":[9,0,1], "closed":true ] ]
72 /// ]
73 ///
74 /// "primitives" : [
75 /// [ "type" :"run",
76 /// "runtype" :"polygon",
77 /// "varyingfields":["vertices"],
78 /// "uniformfields":{"closed":true},
79 /// ],
80 /// [
81 /// [ [0,1,2] ],
82 /// [ [3,4,5] ],
83 /// [ [6,7,8] ],
84 /// [ [9,0,1] ]
85 /// ]
86 /// ]
87 /// @endcode
88 ///
89 /// @section JSON-GA_Primitive JSON Schema: GA_Primitive
90 /// A primitive is stored as an array with two entries. The first entry stores
91 /// the definition of the primitive. The second entry stores the private data
92 /// for the primitive.
93 ///
94 /// The private data is handled by the GA_PrimitiveJSON associated with the
95 /// primitive type.
96 ///
97 /// @code
98 /// {
99 /// "name" : "GA_Primitive",
100 /// "description" :
101 /// "A primitive is stored in an array of two items. The first
102 /// item stores the definition (or run information). The second
103 /// entry stores the private information for the primitive (or run
104 /// of primitives).",
105 /// "type" : "array",
106 /// "items" : [
107 /// { "$ref" : "GA_Primitive-Definition" }, // Definition of primitive
108 /// {
109 /// "$ref" : "GA_Primitive-Data", // Single primitive data
110 /// "$ref" : "GA_Primitive-RunData", // Data for run of primitives
111 /// },
112 /// ],
113 /// }
114 /// @endcode
115 ///
116 /// @section JSON-GA_Primitive-Definition JSON Schema: GA_Primitive-Definition
117 /// The primitive definition may be the definition for a single primitive, or
118 /// it may store run data. The run fields are optional, but if one is defined,
119 /// all should be defined.
120 /// See also: @ref JSON-GA_Primitive
121 /// @code
122 /// {
123 /// "name" : "GA_Primitive-Definition",
124 /// "description" : "Definition of a primitive (or run of primitives)",
125 /// "type" : "orderedmap",
126 /// "properties":
127 /// {
128 /// "type":
129 /// {
130 /// "type" : "string"
131 /// "description" :
132 /// "Type of primitive. 'run' indicates a run of
133 /// primitives (see runtype, uniformfields and
134 /// varyingfields)",
135 /// }
136 /// "runtype" :
137 /// {
138 /// "type" :"string",
139 /// "description" :"Type of primitive in run",
140 /// "optional" :true,
141 /// },
142 /// "uniformfields" :
143 /// {
144 /// "type" : "object",
145 /// "description" :
146 /// "A map of the fields. The value specified is the same
147 /// for all primitives in a run",
148 /// "optional" :true,
149 /// },
150 /// "varyingfields" :
151 /// {
152 /// "type" : "array",
153 /// "items" : "string",
154 /// "description" :
155 /// "A list of strings which are varying for over the run
156 /// of primitives. The run data will be stored in the
157 /// order of the strings in this list."
158 /// "optional" :true,
159 /// },
160 /// },
161 /// }
162 /// @endcode
163 ///
164 /// @section JSON-GA_Primitive-RunData JSON Schema: GA_Primitive-RunData
165 /// This section stores the private data for a run of primitives. The data is
166 /// processed by the GA_PrimitiveJSON class associated with the primitive.
167 /// The data is stored in an
168 /// @code
169 /// {
170 /// "name" : "GA_Primitive-Data",
171 /// "description" :
172 /// "Private data for a run of primitives. Each entry represents
173 /// a distinct primitive.",
174 /// "type": "array",
175 /// "items": "any",
176 /// }
177 /// @endcode
178 ///
179 /// @section JSON-GA_Primitive-HowTo
180 /// This section describes how to write load/save methods for a primitive.
181 ///
182 /// The high-level interface to primitive save/load is provided by the methods
183 /// - <tt>getEntries()</tt>
184 /// - <tt>getKeyword(int i)</tt>
185 /// - <tt>saveField(const GA_Primitive*, int, UT_JSONWriter&, const GA_SaveMap&)</tt>
186 /// - <tt>saveField(const GA_Primitive*, int, UT_JSONValue&, const GA_SaveMap&)</tt>
187 /// - <tt>load(const GA_Primitive*, int, UT_JSONParser&, const GA_LoadMap&)</tt>
188 /// - <tt>load(const GA_Primitive*, int, UT_JSONParser&, UT_JSONValue&, const GA_LoadMap&)</tt>
189 /// - <tt>isEqual(int i, const GA_Primitive*, const GA_Primitive *)</tt>
190 ///
191 /// The private schema is defined by a number of fields in a dictionary/map.
192 /// For example, a polygon might have two fields in its private schema:
193 /// # Vertex List
194 /// # Open/Closed Flag
195 /// which would have an interface which looked like: @code
196 /// int getEntries() const { return 2; }
197 /// const UT_StringHolder &getKeyword(int i) { return i == 0 ? "vertex"_sh : "closed"_sh; }
198 /// bool saveField(const GA_Primitive *prim, int i, UT_JSONWriter &w,
199 /// const GA_SaveMap &map) const {
200 /// if (i == 0) return myVertexList->save(w, map);
201 /// return w.jsonBool(myClosedFlag);
202 /// }
203 /// bool saveField(const GA_Primitive *prim, int i, UT_JSONValue &v,
204 /// const GA_SaveMap &map) const {
205 /// if (i == 0) return myVertexList->save(v, map);
206 /// v.setBool(myClosedFlag);
207 /// return true;
208 /// }
209 /// bool loadField(GA_Primitive *prim, int i, UT_JSONParser &p,
210 /// const GA_LoadMap &map) const {
211 /// if (i == 0) return myVertexList->load(p, map);
212 /// return p.parseBool(myClosed);
213 /// }
214 /// bool loadField(const GA_Primitive *prim, int i, UT_JSONParser &p,
215 /// const UT_JSONValue &v, const GA_SaveMap &map) const {
216 /// if (i == 0) return false; // Never load from a value
217 /// return v.import(myClosed);
218 /// }
219 /// bool isEqual(int i, const GA_Primitive *p0, const GA_Primitive *p1) {
220 /// if (i == 0) return false; // Never save runs of vertex lists
221 /// return p0->myClosed == p1->myClosed;
222 /// }
223 /// @endcode
224 ///
226 {
227 public:
229  virtual ~GA_PrimitiveJSON();
230 
231  /// Return the number of data fields in the primitive private schema
232  virtual int getEntries() const = 0;
233 
234  /// Return whether the i'th field should be saved to the JSON stream. By
235  /// default, all fields are saved. However, this allows the object to
236  /// "skip" some fields which don't make sense in some circumstances.
237  /// @note At the current time, this method is ignored when saving run data.
238  virtual bool shouldSaveField(const GA_Primitive *prim, int i,
239  const GA_SaveMap &save) const;
240 
241  /// Return the keyword associated with the i'th entry of the schema.
242  /// Keywords are case insensitive, but must be specified as @b lower case
243  /// by this method.
244  virtual const UT_StringHolder &getKeyword(int i) const = 0;
245 
246  /// Save the i'th entry of the primitive's schema to the JSON stream. You
247  /// can assume that the GA_Primitive is the correct type (i.e. a static
248  /// cast is ok).
249  virtual bool saveField(const GA_Primitive *prim, int i,
250  UT_JSONWriter &w,
251  const GA_SaveMap &save) const = 0;
252 
253  /// Save the i'th entry of the primitive's schema to a JSON Value. This
254  /// method should only be called when saving uniform data, which only
255  /// happens if the equality checking returned true for the i'th entry. If
256  /// the comparison fails, then this method will never be called.
257  ///
258  /// The default method just calls: @code
259  /// UT_AutoJSONWriter w(value);
260  /// return saveField(prim, i, *w, save);
261  /// @endcode
262  virtual bool saveField(const GA_Primitive *prim, int i,
264  const GA_SaveMap &save) const;
265 
266  /// Load the i'th entry of the primitive's private schema from a JSON
267  /// stream.
268  virtual bool loadField(GA_Primitive *prim, int i,
269  UT_JSONParser &p,
270  const GA_LoadMap &load) const = 0;
271 
272  /// Load the i'th entry of the primitive's private schema from a JSON value.
273  /// The parser is passed in so that errors/warnings can be added.
274  ///
275  /// The default implementation just calls: @code
276  /// UT_AutoJSONIStream is(p, value);
277  /// return loadField(prim, i, p, load);
278  /// @endcode
279  virtual bool loadField(GA_Primitive *prim, int i,
280  UT_JSONParser &p,
281  const UT_JSONValue &value,
282  const GA_LoadMap &load) const;
283 
284  /// Determine if the i'th entry of a primitive's private schema is equal to
285  /// the value in another primitive. This determines whether the data can
286  /// be created as "uniform" data a run of sequential primitives.
287  virtual bool isEqual(int i,
288  const GA_Primitive *prim1,
289  const GA_Primitive *prim2) const = 0;
290 
291  /// Save a single primitve to the UT_JSONWriter
292  /// By default, this simply saves an ordered dictionary (list) with the
293  /// private schema. That is: @code
294  /// w.beginArray();
295  /// for (int i = 0; i < getEntries(); i++) {
296  /// w.jsonKeyToken(getKeyword(i));
297  /// saveField(prim, i, w, map);
298  /// }
299  /// return json.endArray();
300  /// @endcode
301  virtual bool save(const GA_Primitive *prim,
302  UT_JSONWriter &w,
303  const GA_SaveMap &map) const;
304 
305  /// Save a single primitive to a UT_JSONValue
306  virtual bool save(const GA_Primitive *prim,
307  UT_JSONValue &v,
308  const GA_SaveMap &map) const;
309 
310  /// Load a single primitive from the UT_JSONParser. By default, this
311  /// method loads the primitive from an ordered dictionary (as output by the
312  /// save method).
313  virtual bool load(GA_Primitive *prim,
314  UT_JSONParser &p,
315  const GA_LoadMap &map) const;
316 
317  /// Load a single primitive from a UT_JSONValue
318  virtual bool load(GA_Primitive *prim,
319  UT_JSONParser &p,
320  const UT_JSONValue &value,
321  const GA_LoadMap &map) const;
322 
323 
324 protected:
325  /// The GA library may optimize by saving multiple primitives of the same
326  /// type in a "run". This can be done if the primitive is represented by a
327  /// simple map where all primitives share common fields.
328  /// For example, spheres will all have:
329  /// @li center A vertex reference for the center of the sphere
330  /// @li transform The scale/rotate transform for the primitive
331  ///
332  /// getRunFields() is called only if there is a run of multiple primitives.
333  /// The string array returned should be the list of all fields that the
334  /// primitive needs to save. For the sphere example, it would return:
335  /// [ "center", "transform" ].
336  ///
337  /// @param list @n
338  /// List of primitives to check for uniform values.
339  /// @param list_size @n
340  /// Size of the list of primitives in the run (see GA_SaveMap,
341  /// geo:primrunqueue).
342  /// @param varying @n
343  /// The list of fields which are different for each primitive
344  /// @param uniform @n
345  /// This will be a UT_JSONValue::JSON_MAP value. Values which are
346  /// common to every primitive can be placed in this list (instead of
347  /// the varying list. Only objects which can be easily loaded from
348  /// a UT_JSONValue object should be put into the uniform list, since the
349  /// uniform list is pre-loaded when loading runs of primitives.
350  /// @param user_flags @n
351  /// This is an integer which can be set to any value. It is passed
352  /// verbatim to matchRun() and saveRunFields(). This can be used to pass
353  /// information about the run fields.
354  ///
355  /// The base class returns a NULL pointer (indicating saving runs is
356  /// impossible).
357  ///
358  /// The user_flags is an unsigned integer value which you can modify how
359  /// you wish. It's passed to the matchRun() and saveRunFields() verbatim.
360  ///
361  /// The default method returns @c false (no run is possible)
362  virtual bool getRunFields(const GA_Primitive **list,
363  int list_size,
364  const GA_SaveMap &save,
365  UT_StringArray &varying,
366  UT_JSONValue &uniform,
367  uint &user_flags) const;
368 
369  /// When saving a list of primitives, the library attempts to create "runs"
370  /// of like primitives. The library will create an initial run of
371  /// primitives (the length of which is determined by geo:primrununique in
372  /// the GA_SaveMap). This initial list determines the data elements which
373  /// are uniform and varying in the run of primitives.
374  ///
375  /// After this initial run, additional primitives can be added to the run
376  /// if they match. This method is called to test whether the primitive
377  /// matches the current run (prim0 is the first primitive in the run, prim1
378  /// is the primitive to test).
379  ///
380  /// The @c user_flags are the flags set in @c getRunFields().
381  virtual bool matchRun(const GA_Primitive *prim0,
382  const GA_Primitive *prim1,
383  const UT_StringArray &varying,
384  const UT_JSONValue &uniform,
385  uint user_flags) const;
386 
387  /// saveRunFields() should save a JSON array of values, one for each field
388  /// in the varying list of fields.
389  /// The default method returns @c false.
390  virtual bool saveRunFields(const GA_Primitive *prim,
391  const GA_SaveMap &save,
392  const UT_StringArray &varying,
393  UT_JSONWriter &w,
394  uint user_flags) const;
395 
396  /// Load a single primitive from a run of primitives.
397  /// Returns false if an error occurred, else true.
398  virtual bool load(GA_Primitive *prim,
399  UT_JSONParser &p,
400  const GA_LoadMap &load,
401  const UT_StringArray &varying,
402  const GA_JSONUniformBlock &uniform) const;
403 
404  /// Load, and optionally cache, the uniform data for a run of primitives.
405  /// Returns false if an error occurred, else true.
406  virtual bool loadUniform(GA_Primitive *prim,
407  UT_JSONParser &p,
408  const GA_LoadMap &map,
409  const GA_JSONUniformBlock &uniform) const;
410 
411  /// When the primitive loader hits an unknown map token, it will call this
412  /// method to let the primitive process it. The default behaviour is to
413  /// add a warning to the parser and skip the next object.
414  ///
415  /// If the method returns false, parsing will stop and the load will fail.
416  virtual bool loadUnknownToken(GA_Primitive *prim,
417  const char *token,
418  UT_JSONParser &p,
419  const GA_LoadMap &load) const;
420 
421 protected:
422  void init();
423 
426 
427  friend class GA_PrimitiveList;
428  friend class GA_PrimitiveRun;
429 };
430 
431 #endif
virtual ~GA_JSONUniformData()
Used to pass options and map offset values during saving.
Definition: GA_SaveMap.h:48
UT_JSONValue * myMap
const GLdouble * v
Definition: glcorearb.h:837
JSON reader class which handles parsing of JSON or bJSON files.
Definition: UT_JSONParser.h:87
#define GA_API
Definition: GA_API.h:14
Class which writes ASCII or binary JSON streams.
Definition: UT_JSONWriter.h:37
Definition: UT_FSA.h:54
Provide a JSON interface to a primitive.
Options during loading.
Definition: GA_LoadMap.h:42
A list of primitives.
GA_JSONUniformData * myData
Class to store JSON objects as C++ objects.
Definition: UT_JSONValue.h:99
GLubyte GLubyte GLubyte GLubyte w
Definition: glcorearb.h:857
Definition: core.h:1131
unsigned int uint
Definition: SYS_Types.h:45