summaryrefslogtreecommitdiffstats
path: root/o3d/import/cross/collada.h
blob: 67538ea98f33d0d0b65680036c17183b29381566 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
/*
 * Copyright 2009, Google Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */


// This file declares functions for importing COLLADA files into O3D.

#ifndef O3D_IMPORT_CROSS_COLLADA_H_
#define O3D_IMPORT_CROSS_COLLADA_H_

#include <map>
#include <string>
#include <vector>
#include "base/file_path.h"
#include "core/cross/param.h"
#include "core/cross/types.h"

class FCDocument;
class FCDAnimated;
class FCDCamera;
class FCDSceneNode;
class FCDGeometry;
class FCDGeometryInstance;
class FCDControllerInstance;
class FCDMaterial;
class FCDEffect;
class FCDEffectStandard;
class FCDEffectParameter;
class FCDEffectParameterSampler;
class FCDEffectParameterSurface;
class FCDEffectPassState;
class FCDImage;
class FCDTMatrix;
class FCDTTranslation;
class FCDTRotation;
class FCDTScale;

class FilePath;

namespace o3d {

class ColladaZipArchive;
class Effect;
class IErrorStatus;
class Material;
class Pack;
class ParamObject;
class Sampler;
class ShaderBuilderHelper;
class Shape;
class State;
class Texture;
class Transform;
class TranslationMap;

// This class keeps an association between a Collada node instance and a
// transform.
// This takes ownership of its children NodeInstances.
class NodeInstance {
 public:
  typedef std::vector<NodeInstance *> NodeInstanceList;

  explicit NodeInstance(FCDSceneNode *node) : node_(node), transform_(NULL) {}
  ~NodeInstance() {
    for (unsigned int i = 0; i < children_.size(); ++i) {
      delete children_[i];
    }
  }

  // Gets the Collada node associated with this node instance.
  FCDSceneNode *node() const { return node_; }

  // Gets the Transform associated with this node instance.
  Transform *transform() const { return transform_; }

  // Sets the Transform associated with this node instance.
  void set_transform(Transform *transform) { transform_ = transform; }

  // Gets the list of this node instance's children.
  NodeInstanceList &children() { return children_; }

  // Finds the NodeInstance representing a scene node in the direct children of
  // this NodeInstance.
  NodeInstance *FindNodeShallow(FCDSceneNode *node) {
    for (unsigned int i = 0; i < children_.size(); ++i) {
      NodeInstance *child = children_[i];
      if (child->node() == node) return child;
    }
    return NULL;
  }

  // Finds the NodeInstance representing a scene node in the sub-tree starting
  // at this NodeInstance.
  NodeInstance *FindNodeInTree(FCDSceneNode *node);

 private:
  FCDSceneNode *node_;
  Transform *transform_;
  std::vector<NodeInstance *> children_;
};

class Collada {
 public:
  struct Options {
    Options()
        : generate_mipmaps(true),
          condition_document(false),
          keep_original_data(false),
          up_axis(0.0f, 0.0f, 0.0f),
          base_path(FilePath::kCurrentDirectory) {}
    // Whether or not to generate mip-maps on the textures we load.
    bool generate_mipmaps;

    // Whether or not to retain the original form for textures for later
    // access by filename.
    bool keep_original_data;

    // Whether or not to condition documents for o3d as part of
    // loading them.
    bool condition_document;

    // What the up-axis of the imported geometry should be.
    Vector3 up_axis;

    // The base path to use for determining the relative paths for
    // asset URIs.
    FilePath base_path;
  };

  // Use this if you need access to data after the import (as the
  // converter does).
  Collada(Pack* pack, const Options& options);
  virtual ~Collada();

  // Imports the given COLLADA file or ZIP file into the given scene.
  // This is the external interface to o3d.
  // Parameters:
  //   pack:      The pack into which the scene objects will be placed.
  //   filename:  The COLLADA or ZIPped COLLADA file to import.
  //   parent:    The parent node under which the imported nodes will be placed.
  //              If NULL, nodes will be placed under the client's root.
  //   animation_input: The counter parameter used to control transform
  //              animation in the collada file.
  //   options:   The Options structure (see above) that describes any
  //              desired options.
  // Returns true on success.
  static bool Import(Pack* pack,
                     const FilePath& filename,
                     Transform* parent,
                     ParamFloat* animation_input,
                     const Options& options);

  // Same thing but with String filename.
  static bool Import(Pack* pack,
                     const String& filename,
                     Transform* parent,
                     ParamFloat* animation_input,
                     const Options& options);

  // Imports the given COLLADA file or ZIP file into the pack given to
  // the constructor.
  bool ImportFile(const FilePath& filename, Transform* parent,
                  ParamFloat* animation_input);

  // Access to the filenames of the original data for texture and
  // sound assets imported when ImportFile was called.  These will
  // only return results after an import if the keep_original_data
  // option was set to true when the Collada object was created.
  std::vector<FilePath> GetOriginalDataFilenames() const;
  const std::string& GetOriginalData(const FilePath& filename) const;

 private:
  // Imports the given ZIP file into the given pack.
  bool ImportZIP(const FilePath& filename, Transform* parent,
                 ParamFloat* animation_input);

  // Imports the given COLLADA file (.DAE) into the current pack.
  bool ImportDAE(const FilePath& filename,
                 Transform* parent,
                 ParamFloat* animation_input);

  // Imports the given FCDocument (already loaded) into the current pack.
  bool ImportDAEDocument(FCDocument* doc,
                         bool fc_status,
                         Transform* parent,
                         ParamFloat* animation_input);

  // Creates the instance tree corresponding to the collada scene node DAG.
  // A separate NodeInstance is created every time a particular node is
  // traversed. The caller must destroy the returned NodeInstance.
  static NodeInstance *CreateInstanceTree(FCDSceneNode *node);

  // Recursively imports a tree of nodes from FCollada, rooted at the
  // given node, into the O3D scene.
  void ImportTree(NodeInstance *instance,
                  Transform* parent,
                  ParamFloat* animation_input);

  // Recursively imports a tree of instances (shapes, etc..) from FCollada,
  // rooted at the given node, into the O3D scene. This is a separate step
  // from ImportTree because various kinds of instances can reference other
  // parts of the tree.
  void ImportTreeInstances(FCDocument* doc,
                           NodeInstance* instance);

  bool BuildFloatAnimation(ParamFloat* result,
                           FCDAnimated* animated,
                           const char* qualifier,
                           ParamFloat* animation_input,
                           float output_scale,
                           float default_value);

  bool BuildFloat3Animation(ParamFloat3* result, FCDAnimated* animated,
                            ParamFloat* animation_input,
                            const Float3& default_value);

  ParamMatrix4* BuildComposition(FCDTMatrix* transform,
                                 ParamMatrix4* input_matrix,
                                 ParamFloat* animation_input);

  ParamMatrix4* BuildComposition(const Matrix4& matrix,
                                 ParamMatrix4* input_matrix);

  ParamMatrix4* BuildTranslation(FCDTTranslation* transform,
                                 ParamMatrix4* input_matrix,
                                 ParamFloat* animation_input);

  ParamMatrix4* BuildRotation(FCDTRotation* transform,
                              ParamMatrix4* input_matrix,
                              ParamFloat* animation_input);

  ParamMatrix4* BuildScaling(FCDTScale* transform,
                             ParamMatrix4* input_matrix,
                             ParamFloat* animation_input);

  // Builds a Transform node corresponding to the transform elements of
  // a given node.  All transformations (rotation, translation, scale,
  // etc) are collapsed into a single Transform.
  Transform* BuildTransform(FCDSceneNode* node,
                            Transform* parent_transform,
                            ParamFloat* animation_input);

  // Extracts the various camera parameters from a Collada Camera object and
  // stored them as Params on an O3D Transform.
  void BuildCamera(FCDocument* doc,
                   FCDCamera* camera,
                   Transform* transform,
                   FCDSceneNode* parent_node);

  // Gets an O3D shape corresponding to a given FCollada geometry instance.
  // If the Shape does not exist, Builds one.
  Shape* GetShape(FCDocument* doc,
                  FCDGeometryInstance* geom_instance);

  // Builds O3D shape corresponding to a given FCollada geometry instance.
  Shape* BuildShape(FCDocument* doc,
                    FCDGeometryInstance* geom_instance,
                    FCDGeometry* geom,
                    TranslationMap* translationMap);

  // Gets an O3D skinned shape corresponding to a given FCollada controller
  // instance. If the Shape does not exist, Builds one.
  Shape* GetSkinnedShape(FCDocument* doc,
                         FCDControllerInstance* instance,
                         NodeInstance *parent_node_instance);

  // Builds O3D skinned shape corresponding to a given FCollada controller
  // instance.
  Shape* BuildSkinnedShape(FCDocument* doc,
                           FCDControllerInstance* instance,
                           NodeInstance *parent_node_instance);

  // Builds an O3D texture corresponding to a given FCollada surface
  // parameter.
  Texture* BuildTexture(FCDEffectParameterSurface* surface);

  // Builds an O3D texture corresponding to a given FCDImage.
  Texture* BuildTextureFromImage(FCDImage* image);

  // Builds an O3D material from a COLLADA effect and material.  If a
  // COLLADA-FX (Cg/HLSL) effect is present, it will be used and a programmable
  // Effect generated.  If not, an attempt is made to use one of the fixed-
  // function profiles if present (eg., Constant, Lambert).
  Material* BuildMaterial(FCDocument* doc, FCDMaterial* material);

  // Gets an O3D effect correpsonding to a given FCollada effect. If the
  // effect does not already exist it is created.
  Effect* GetEffect(FCDocument* doc, FCDEffect* effect);

  // Builds an O3D effect from a COLLADA effect and material.  If a
  // COLLADA-FX (Cg/HLSL) effect is present, it will be used and a programmable
  // Effect generated.  If not, an attempt is made to use one of the fixed-
  // function profiles if present (eg., Constant, Lambert).
  Effect* BuildEffect(FCDocument* doc, FCDEffect* effect);

  // Copies the texture sampler states from an FCollada sampler to an O3D
  // sampler.
  void SetSamplerStates(FCDEffectParameterSampler* effect_sampler,
                        Sampler* o3d_sampler);

  // Converts the given COLLADA pass state into one or more state
  // parameters on the given O3D state object.
  void AddRenderState(FCDEffectPassState* pass_state, State* state);

  // Sets the O3D culling state based on the OpenGL-style states that
  // COLLADA-FX uses, cached in cull_enabled_, cull_front_ and front_cw_.
  void UpdateCullingState(State* state);

  // Sets an O3D parameter value from a given FCollada effect parameter.
  bool SetParamFromFCEffectParam(ParamObject *param_object,
                                 const String &param_name,
                                 FCDEffectParameter *fc_param);

  // Sets the value of a Param on the given ParamObject from an FCollada
  // standard-profile effect parameter.  If the FCollada parameter
  // contains a texture, the sampler_param_name and channel is used to set
  // a Sampler Param in o3d from the surface.  If not, the
  // color_param_name is used to create set a vector Param value.
  void SetParamFromStandardEffectParam(FCDEffectStandard* effect_standard,
                                       ParamObject* param_object,
                                       const char* color_param_name,
                                       const char* sampler_param_name,
                                       FCDEffectParameter* color_param,
                                       int channel);

  // Sets the values of shape parameters from a given FCollada material node.
  // If a corresponding shape parameter is not found, the FCollada parameter
  // is ignored.
  void SetParamsFromMaterial(FCDMaterial* material, ParamObject* param_object);

  // Finds a node instance corresponding to a scene node. Since a particular
  // scene node can be instanced multiple times, this will return an arbitrary
  // instance.
  NodeInstance *FindNodeInstance(FCDSceneNode *node);

  // Finds the node instance corresponding to a scene node if it is not
  // instanced, by following the only parent of the nodes until it reaches the
  // root. This will return NULL if the node can't be found, or if the node is
  // instanced more than once.
  NodeInstance *FindNodeInstanceFast(FCDSceneNode *node);

  // Clears out any residual data from the last import.  Doesn't
  // affect the Pack or the options, just intermediate data structures
  // in this object.
  void ClearData();

  // Gets a dummy effect or creates one if none exists.
  Effect* GetDummyEffect();

  // Gets a dummy material or creates one if none exists.
  Material* GetDummyMaterial();

  ServiceLocator* service_locator_;

  // The object from which error status is retreived.
  IErrorStatus* error_status_;

  // The Pack into which newly-created nodes will be placed.
  Pack* pack_;

  // The import options to use;
  Options options_;

  // The effect used if we can't create an effect.
  Effect* dummy_effect_;

  // The material used if we can't create a material.
  Material* dummy_material_;

  // The root of the instance node tree.
  NodeInstance* instance_root_;

  // A map of the Textures created by the importer, indexed by filename.
  std::map<const std::wstring, Texture*> textures_;

  // A map containing the original data (still in original format)
  // used to create the textures, sounds, etc., indexed by filename.
  typedef std::map<FilePath, std::string> OriginalDataMap;
  OriginalDataMap original_data_;

  // A map of the Effects created by the importer, indexed by DAE id.
  std::map<const std::string, Effect*> effects_;

  // A map of the Shapes created by the importer, indexed by DAE id.
  std::map<const std::string, Shape*> shapes_;

  // A map of the Skinned Shapes created by the importer, indexed by DAE id.
  std::map<const std::string, Shape*> skinned_shapes_;

  // A map of the Materials created by the importer, indexed by DAE id.
  std::map<const std::string, Material*> materials_;

  // All the errors accumlated during loading.
  String errors_;

  // The absolute path to the top of the model hierarchy, to use for
  // determining the relative paths to other files.
  FilePath base_path_;

  ColladaZipArchive *collada_zip_archive_;
  // Some temporaries used by the state importer
  bool cull_enabled_;
  bool cull_front_;
  bool front_cw_;

  int unique_filename_counter_;

  DISALLOW_COPY_AND_ASSIGN(Collada);
};
}
#endif  // O3D_IMPORT_CROSS_COLLADA_H_