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  /// Note uniform data appears BEFORE varying data. So if you require a
288  /// ordering on your keys, you need to make all keys that require to
289  /// be loaded after another key never equal to each other.
290  virtual bool isEqual(int i,
291  const GA_Primitive *prim1,
292  const GA_Primitive *prim2) const = 0;
293 
294  /// Save a single primitve to the UT_JSONWriter
295  /// By default, this simply saves an ordered dictionary (list) with the
296  /// private schema. That is: @code
297  /// w.beginArray();
298  /// for (int i = 0; i < getEntries(); i++) {
299  /// w.jsonKeyToken(getKeyword(i));
300  /// saveField(prim, i, w, map);
301  /// }
302  /// return json.endArray();
303  /// @endcode
304  virtual bool save(const GA_Primitive *prim,
305  UT_JSONWriter &w,
306  const GA_SaveMap &map) const;
307 
308  /// Save a single primitive to a UT_JSONValue
309  virtual bool save(const GA_Primitive *prim,
310  UT_JSONValue &v,
311  const GA_SaveMap &map) const;
312 
313  /// Load a single primitive from the UT_JSONParser. By default, this
314  /// method loads the primitive from an ordered dictionary (as output by the
315  /// save method).
316  virtual bool load(GA_Primitive *prim,
317  UT_JSONParser &p,
318  const GA_LoadMap &map) const;
319 
320  /// Load a single primitive from a UT_JSONValue
321  virtual bool load(GA_Primitive *prim,
322  UT_JSONParser &p,
323  const UT_JSONValue &value,
324  const GA_LoadMap &map) const;
325 
326 
327 protected:
328  /// The GA library may optimize by saving multiple primitives of the same
329  /// type in a "run". This can be done if the primitive is represented by a
330  /// simple map where all primitives share common fields.
331  /// For example, spheres will all have:
332  /// @li center A vertex reference for the center of the sphere
333  /// @li transform The scale/rotate transform for the primitive
334  ///
335  /// getRunFields() is called only if there is a run of multiple primitives.
336  /// The string array returned should be the list of all fields that the
337  /// primitive needs to save. For the sphere example, it would return:
338  /// [ "center", "transform" ].
339  ///
340  /// @param list @n
341  /// List of primitives to check for uniform values.
342  /// @param list_size @n
343  /// Size of the list of primitives in the run (see GA_SaveMap,
344  /// geo:primrunqueue).
345  /// @param varying @n
346  /// The list of fields which are different for each primitive
347  /// @param uniform @n
348  /// This will be a UT_JSONValue::JSON_MAP value. Values which are
349  /// common to every primitive can be placed in this list (instead of
350  /// the varying list. Only objects which can be easily loaded from
351  /// a UT_JSONValue object should be put into the uniform list, since the
352  /// uniform list is pre-loaded when loading runs of primitives.
353  /// @param user_flags @n
354  /// This is an integer which can be set to any value. It is passed
355  /// verbatim to matchRun() and saveRunFields(). This can be used to pass
356  /// information about the run fields.
357  ///
358  /// The base class returns a NULL pointer (indicating saving runs is
359  /// impossible).
360  ///
361  /// The user_flags is an unsigned integer value which you can modify how
362  /// you wish. It's passed to the matchRun() and saveRunFields() verbatim.
363  ///
364  /// The default method returns @c false (no run is possible)
365  virtual bool getRunFields(const GA_Primitive **list,
366  int list_size,
367  const GA_SaveMap &save,
368  UT_StringArray &varying,
369  UT_JSONValue &uniform,
370  uint &user_flags) const;
371 
372  /// When saving a list of primitives, the library attempts to create "runs"
373  /// of like primitives. The library will create an initial run of
374  /// primitives (the length of which is determined by geo:primrununique in
375  /// the GA_SaveMap). This initial list determines the data elements which
376  /// are uniform and varying in the run of primitives.
377  ///
378  /// After this initial run, additional primitives can be added to the run
379  /// if they match. This method is called to test whether the primitive
380  /// matches the current run (prim0 is the first primitive in the run, prim1
381  /// is the primitive to test).
382  ///
383  /// The @c user_flags are the flags set in @c getRunFields().
384  virtual bool matchRun(const GA_Primitive *prim0,
385  const GA_Primitive *prim1,
386  const UT_StringArray &varying,
387  const UT_JSONValue &uniform,
388  uint user_flags) const;
389 
390  /// saveRunFields() should save a JSON array of values, one for each field
391  /// in the varying list of fields.
392  /// The default method returns @c false.
393  virtual bool saveRunFields(const GA_Primitive *prim,
394  const GA_SaveMap &save,
395  const UT_StringArray &varying,
396  UT_JSONWriter &w,
397  uint user_flags) const;
398 
399  /// Load a single primitive from a run of primitives.
400  /// Returns false if an error occurred, else true.
401  virtual bool load(GA_Primitive *prim,
402  UT_JSONParser &p,
403  const GA_LoadMap &load,
404  const UT_StringArray &varying,
405  const GA_JSONUniformBlock &uniform) const;
406 
407  /// Load, and optionally cache, the uniform data for a run of primitives.
408  /// Returns false if an error occurred, else true.
409  virtual bool loadUniform(GA_Primitive *prim,
410  UT_JSONParser &p,
411  const GA_LoadMap &map,
412  const GA_JSONUniformBlock &uniform) const;
413 
414  /// When the primitive loader hits an unknown map token, it will call this
415  /// method to let the primitive process it. The default behaviour is to
416  /// add a warning to the parser and skip the next object.
417  ///
418  /// If the method returns false, parsing will stop and the load will fail.
419  virtual bool loadUnknownToken(GA_Primitive *prim,
420  const char *token,
421  UT_JSONParser &p,
422  const GA_LoadMap &load) const;
423 
424 protected:
425  void init();
426 
429 
430  friend class GA_PrimitiveList;
431  friend class GA_PrimitiveRun;
432 };
433 
434 #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