diff options
Diffstat (limited to 'o3d/import/cross/collada.h')
-rw-r--r-- | o3d/import/cross/collada.h | 438 |
1 files changed, 438 insertions, 0 deletions
diff --git a/o3d/import/cross/collada.h b/o3d/import/cross/collada.h new file mode 100644 index 0000000..67538ea --- /dev/null +++ b/o3d/import/cross/collada.h @@ -0,0 +1,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 ¶m_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_ |