Sirikata
libmesh/include/sirikata/mesh/Meshdata.hpp
Go to the documentation of this file.
00001 /*  Sirikata
00002  *  Meshdata.hpp
00003  *
00004  *  Copyright (c) 2010, Daniel B. Miller
00005  *  All rights reserved.
00006  *
00007  *  Redistribution and use in source and binary forms, with or without
00008  *  modification, are permitted provided that the following conditions are
00009  *  met:
00010  *  * Redistributions of source code must retain the above copyright
00011  *    notice, this list of conditions and the following disclaimer.
00012  *  * Redistributions in binary form must reproduce the above copyright
00013  *    notice, this list of conditions and the following disclaimer in
00014  *    the documentation and/or other materials provided with the
00015  *    distribution.
00016  *  * Neither the name of Sirikata nor the names of its contributors may
00017  *    be used to endorse or promote products derived from this software
00018  *    without specific prior written permission.
00019  *
00020  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
00021  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
00022  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00023  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
00024  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00025  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00026  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00027  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00028  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00029  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00030  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00031  */
00032 
00033 #ifndef _SIRIKATA_MESH_MESHDATA_HPP_
00034 #define _SIRIKATA_MESH_MESHDATA_HPP_
00035 
00036 #include <sirikata/mesh/Platform.hpp>
00037 #include <sirikata/mesh/Visual.hpp>
00038 #include <sirikata/core/transfer/RemoteFileMetadata.hpp>
00039 #include "LightInfo.hpp"
00040 #include <stack>
00041 
00042 namespace Sirikata {
00043 namespace Mesh {
00044 
00045 // Typedefs for NodeIndices, which refer to scene graph nodes in the model
00046 typedef int32 NodeIndex;
00047 extern SIRIKATA_MESH_EXPORT NodeIndex NullNodeIndex;
00048 typedef std::vector<NodeIndex> NodeIndexList;
00049 
00050 
00051 typedef std::vector<LightInfo> LightInfoList;
00052 typedef std::vector<std::string> TextureList;
00053 
00054 struct Meshdata;
00055 typedef std::tr1::shared_ptr<Meshdata> MeshdataPtr;
00056 typedef std::tr1::weak_ptr<Meshdata> MeshdataWPtr;
00057 
00061 struct SIRIKATA_MESH_EXPORT SkinController {
00062     // Joints for this controls Indexes into the Meshdata.joints array
00063     // (which indexes into Meshdata.nodes).
00064     std::vector<uint32> joints;
00065 
00066     Matrix4x4f bindShapeMatrix;
00069     std::vector<unsigned int> weightStartIndices;
00070     // weights and jointIndices are the same size and are a sparse
00071     // representation of the (vertex,bone) = weight matrix: the
00072     // weightStartIndices let you figure out the range in these arrays that
00073     // correspond to a single vertex. In that range, each pair represents the
00074     // weight for one joint for the current vertex, with the rest of the joints
00075     // having weight 0.
00076     std::vector<float> weights;
00077     std::vector<unsigned int>jointIndices;
00078     // One inverse bind matrix per joint.
00079     std::vector<Matrix4x4f> inverseBindMatrices;
00080 };
00081 typedef std::vector<SkinController> SkinControllerList;
00082 
00083 struct SIRIKATA_MESH_EXPORT SubMeshGeometry {
00084     std::string name;
00085 
00086     std::vector<Sirikata::Vector3f> positions;
00087     std::vector<Sirikata::Vector3f> normals;
00088     std::vector<Sirikata::Vector3f> tangents;
00089     std::vector<Sirikata::Vector4f> colors;
00090 
00091     struct TextureSet {
00092         unsigned int stride;
00093         std::vector<float> uvs;
00094     };
00095     std::vector<TextureSet>texUVs;
00096     struct Primitive {
00097         std::vector<unsigned short> indices;
00098 
00099         enum PrimitiveType {
00100             TRIANGLES,
00101             LINES,
00102             POINTS,
00103             LINESTRIPS,
00104             TRISTRIPS,
00105             TRIFANS
00106         }primitiveType;
00107         typedef size_t MaterialId;
00108         MaterialId materialId;
00109     };
00110     std::vector<Primitive> primitives;
00111 
00112     BoundingBox3f3f aabb;
00113     double radius;
00114     void recomputeBounds();
00115 
00116     SkinControllerList skinControllers;
00117 
00118 
00123     void append(const SubMeshGeometry& rhs, const Matrix4x4f& xform);
00124 };
00125 typedef std::vector<SubMeshGeometry> SubMeshGeometryList;
00126 
00127 
00128 struct SIRIKATA_MESH_EXPORT GeometryInstance {
00129     typedef std::map<SubMeshGeometry::Primitive::MaterialId,size_t> MaterialBindingMap;
00130     MaterialBindingMap materialBindingMap;//maps materialIndex to offset in Meshdata's materials
00131     unsigned int geometryIndex; // Index in SubMeshGeometryList
00132     NodeIndex parentNode; // Index of node holding this instance
00133 
00138     BoundingBox3f3f computeTransformedBounds(MeshdataPtr parent, const Matrix4x4f& xform) const;
00139     BoundingBox3f3f computeTransformedBounds(const Meshdata& parent, const Matrix4x4f& xform) const;
00140     void computeTransformedBounds(MeshdataPtr parent, const Matrix4x4f& xform, BoundingBox3f3f* bounds_out, double* radius_out) const;
00141     void computeTransformedBounds(const Meshdata& parent, const Matrix4x4f& xform, BoundingBox3f3f* bounds_out, double* radius_out) const;
00142 };
00143 typedef std::vector<GeometryInstance> GeometryInstanceList;
00144 
00145 struct SIRIKATA_MESH_EXPORT LightInstance {
00146     int lightIndex; // Index in LightInfoList
00147     NodeIndex parentNode; // Index of node holding this instance
00148 };
00149 typedef std::vector<LightInstance> LightInstanceList;
00150 
00151 struct SIRIKATA_MESH_EXPORT MaterialEffectInfo {
00152     struct Texture {
00153         std::string uri;
00154         Vector4f color;//color while the texture is pulled in, or if the texture is 404'd
00155         size_t texCoord;
00156         enum Affecting {
00157             DIFFUSE,
00158             SPECULAR,
00159             EMISSION,
00160             AMBIENT,
00161             REFLECTIVE,
00162             OPACITY,
00163 
00164         }affecting;
00165         enum SamplerType
00166         {
00167             SAMPLER_TYPE_UNSPECIFIED,
00168             SAMPLER_TYPE_1D,
00169             SAMPLER_TYPE_2D,
00170             SAMPLER_TYPE_3D,
00171             SAMPLER_TYPE_CUBE,
00172             SAMPLER_TYPE_RECT,
00173             SAMPLER_TYPE_DEPTH,
00174             SAMPLER_TYPE_STATE
00175         } samplerType;
00176         enum SamplerFilter
00177         {
00178             SAMPLER_FILTER_UNSPECIFIED,
00179             SAMPLER_FILTER_NONE,
00180             SAMPLER_FILTER_NEAREST,
00181             SAMPLER_FILTER_LINEAR,
00182             SAMPLER_FILTER_NEAREST_MIPMAP_NEAREST,
00183             SAMPLER_FILTER_LINEAR_MIPMAP_NEAREST,
00184             SAMPLER_FILTER_NEAREST_MIPMAP_LINEAR,
00185             SAMPLER_FILTER_LINEAR_MIPMAP_LINEAR
00186         };
00187         SamplerFilter minFilter;
00188         SamplerFilter magFilter;
00189         enum WrapMode
00190         {
00191             WRAP_MODE_UNSPECIFIED=0,
00192             // NONE == GL_CLAMP_TO BORDER The defined behavior for NONE is
00193             // consistent with decal texturing where the border is black.
00194             // Mapping this calculation to GL_CLAMP_TO_BORDER is the best
00195             // approximation of this.
00196             WRAP_MODE_NONE,
00197             // WRAP == GL_REPEAT Ignores the integer part of texture coordinates,
00198             // using only the fractional part.
00199             WRAP_MODE_WRAP,
00200             // MIRROR == GL_MIRRORED_REPEAT First mirrors the texture coordinate.
00201             // The mirrored coordinate is then clamped as described for CLAMP_TO_EDGE.
00202             WRAP_MODE_MIRROR,
00203             // CLAMP == GL_CLAMP_TO_EDGE Clamps texture coordinates at all
00204             // mipmap levels such that the texture filter never samples a
00205             // border texel. Note: GL_CLAMP takes any texels beyond the
00206             // sampling border and substitutes those texels with the border
00207             // color. So CLAMP_TO_EDGE is more appropriate. This also works
00208             // much better with OpenGL ES where the GL_CLAMP symbol was removed
00209             // from the OpenGL ES specification.
00210             WRAP_MODE_CLAMP,
00211             // BORDER GL_CLAMP_TO_BORDER Clamps texture coordinates at all
00212             // MIPmaps such that the texture filter always samples border
00213             // texels for fragments whose corresponding texture coordinate
00214             // is sufficiently far outside the range [0, 1].
00215             WRAP_MODE_BORDER
00216         };
00217         WrapMode wrapS,wrapT,wrapU;
00218         unsigned int maxMipLevel;
00219         float mipBias;
00220 
00221         bool operator==(const Texture& rhs) const;
00222         bool operator!=(const Texture& rhs) const;
00223     };
00224     typedef std::vector<Texture> TextureList;
00225     TextureList textures;
00226     float shininess;
00227     float reflectivity;
00228 
00229     bool operator==(const MaterialEffectInfo& rhs) const;
00230     bool operator!=(const MaterialEffectInfo& rhs) const;
00231 };
00232 typedef std::vector<MaterialEffectInfo> MaterialEffectInfoList;
00233 
00234 
00235 struct  SIRIKATA_MESH_EXPORT InstanceSkinAnimation {
00236 };
00237 
00239 struct SIRIKATA_MESH_EXPORT TransformationKeyFrames {
00240     typedef std::vector<float> TimeList;
00241     TimeList inputs;
00242     typedef std::vector<Matrix4x4f> TransformationList;
00243     TransformationList outputs;
00244 };
00245 
00246 // A scene graph node. Contains a transformation, set of children nodes,
00247 // camera instances, geometry instances, skin controller instances, light
00248 // instances, and instances of other nodes.
00249 struct SIRIKATA_MESH_EXPORT Node {
00250     Node();
00251     Node(NodeIndex par, const Matrix4x4f& xform);
00252     Node(const Matrix4x4f& xform);
00253 
00254     bool containsInstanceController;
00255 
00256     // Parent node in the actual hierarchy (not instantiated).
00257     NodeIndex parent;
00258     // Transformation to apply when traversing this node.
00259     Matrix4x4f transform;
00260     // Direct children, i.e. they are contained by this node directly and their
00261     // parent NodeIndex will reflect that.
00262     NodeIndexList children;
00263     // Instantiations of other nodes (and their children) into this
00264     // subtree. Because they are instantiations, their
00265     // instanceChildren[i]->parent != this node's index.
00266     NodeIndexList instanceChildren;
00267 
00268     // Map of name -> animation curve.
00269     typedef std::map<String, TransformationKeyFrames> AnimationMap;
00270     AnimationMap animations;
00271 };
00272 typedef std::vector<Node> NodeList;
00273 
00274 //Stores information about a single mipmap level
00275 struct SIRIKATA_MESH_EXPORT ProgressiveMipmapLevel {
00276     //Offset within the tar file of the mipmap
00277     uint32 offset;
00278     //Length of the mipmap file within the tar file
00279     uint32 length;
00280     //Width of the mipmap image
00281     uint32 width;
00282     //Height of the mipmap image
00283     uint32 height;
00284 };
00285 //A map containing mipmap levels in an archive
00286 typedef std::map<uint32, ProgressiveMipmapLevel> ProgressiveMipmaps;
00287 //Information about an archive of mipmaps
00288 struct SIRIKATA_MESH_EXPORT ProgressiveMipmapArchive {
00289     //Contains the list of mipmap levels
00290     ProgressiveMipmaps mipmaps;
00291     //The name of the image in the mesh that references this
00292     std::string name;
00293     //The hash of the mipmap archive
00294     Transfer::Fingerprint archiveHash;
00295 };
00296 //A map containing the names of mipmap archives
00297 typedef std::map<std::string, ProgressiveMipmapArchive> ProgressiveMipmapMap;
00298 //Stores progressive mesh information
00299 struct SIRIKATA_MESH_EXPORT ProgressiveData {
00300     //The hash of the progressive stream
00301     Transfer::Fingerprint progressiveHash;
00302     //The number of triangles in the progressive stream
00303     uint32 numProgressiveTriangles;
00304     //Maps the names of mipmap archives to the mipmap archive data
00305     ProgressiveMipmapMap mipmaps;
00306 };
00307 typedef std::tr1::shared_ptr<ProgressiveData> ProgressiveDataPtr;
00308 
00309 struct SIRIKATA_MESH_EXPORT Meshdata : public Visual {
00310   private:
00311     static String sType;
00312 
00313   public:
00314     Meshdata();
00315 
00316     virtual ~Meshdata();
00317 
00318     virtual const String& type() const;
00319 
00320     SubMeshGeometryList geometry;
00321     TextureList textures;
00322     LightInfoList lights;
00323     MaterialEffectInfoList materials;
00324 
00325     long id;
00326 
00327     bool hasAnimations;
00328 
00329     GeometryInstanceList instances;
00330     LightInstanceList lightInstances;
00331 
00332     // The global transform should be applied to all nodes and instances
00333     Matrix4x4f globalTransform;
00334     // We track two sets of nodes: roots and the full list. (Obviously the roots
00335     // are a subset of the full list). The node list is just the full set,
00336     // usually only used to look up children/parents.  The roots list is just a
00337     // set of indices into the full list.
00338     NodeList nodes;
00339     NodeIndexList rootNodes;
00340 
00341     //Stores a list of transforms on the path from the scene root
00342     //to the instance controller for the skeleton.
00343     std::vector<Matrix4x4f>  mInstanceControllerTransformList;
00344     // Joints are tracked as indices of the nodes they are associated with.
00345     NodeIndexList joints;
00346 
00347     // Be careful using these methods. Since there are no "parent" links for
00348     // instance nodes (and even if there were, there could be more than one),
00349     // these methods cannot correctly compute the transform when instance_nodes
00350     // are involved.
00351     Matrix4x4f getTransform(NodeIndex index) const;
00352 
00353     // If this mesh is in progressive format, stores progressive information
00354     ProgressiveDataPtr progressiveData;
00355 
00356   private:
00357 
00358     // A stack of NodeState is used to track the current traversal state for
00359     // instance iterators
00360     struct SIRIKATA_MESH_EXPORT NodeState {
00361         enum Step {
00362             Init,
00363             Nodes,
00364             InstanceNodes,
00365             InstanceGeometries,
00366             InstanceLights,
00367             Done
00368         };
00369 
00370         NodeIndex index;
00371         Matrix4x4f transform;
00372         Step step;
00373         int32 currentChild;
00374     };
00375     struct SIRIKATA_MESH_EXPORT JointNodeState : public NodeState {
00376         uint32 joint_id;
00377         std::vector<Matrix4x4f> transformList;
00378     };
00379   public:
00380 
00381     // Allows you to generate a list of GeometryInstances with their transformations.
00382     class SIRIKATA_MESH_EXPORT GeometryInstanceIterator {
00383     public:
00384         GeometryInstanceIterator(const Meshdata* const mesh);
00385         // Get the next GeometryInstance and its transform. Returns true if
00386         // values were set, false if there were no more instances. The index
00387         // returned is of the geometry instance.
00388         bool next(uint32* geoinst_idx, Matrix4x4f* xform);
00389     private:
00390         const Meshdata* mMesh;
00391 
00392         int32 mRoot;
00393         std::stack<NodeState> mStack;
00394     };
00395     GeometryInstanceIterator getGeometryInstanceIterator() const;
00399     uint32 getInstancedGeometryCount() const;
00400 
00401 
00402     // Allows you to generate a list of joints with their transformations.
00403     class SIRIKATA_MESH_EXPORT JointIterator {
00404     public:
00405         JointIterator(const Meshdata* const mesh);
00406         // Get the next Joint's unique ID, its index in the list of joints, its
00407         // transform, and parent joint ID. Also gets the list of transforms from the root node
00408         // to the instance controller of the skeleton referencing the joint. Returns true if
00409         // values were set, false if there were no more joints. Joint IDs are
00410         // non-zero, so you can check for, e.g., no parent with parent_id == 0
00411         // or if (parent_id). The joint_idx is an index into Meshdata::joints.
00412         bool next(uint32* joint_id, uint32* joint_idx, Matrix4x4f* xform, uint32* parent_id, std::vector<Matrix4x4f>& transformList);
00413     private:
00414         const Meshdata* mMesh;
00415 
00416         int32 mRoot;
00417         std::stack<JointNodeState> mStack;
00418         uint32 mNextID;
00419     };
00420     JointIterator getJointIterator() const;
00424     uint32 getJointCount() const;
00425 
00426 
00427     // Allows you to generate a list of GeometryInstances with their transformations.
00428     class SIRIKATA_MESH_EXPORT LightInstanceIterator {
00429     public:
00430         LightInstanceIterator(const Meshdata* const mesh);
00431         // Get the next LightInstance and its transform. Returns true if
00432         // values were set, false if there were no more instances. The index
00433         // returned is of the light instance.
00434         bool next(uint32* lightinst_idx, Matrix4x4f* xform);
00435     private:
00436         const Meshdata* mMesh;
00437 
00438         int32 mRoot;
00439         std::stack<NodeState> mStack;
00440     };
00441     LightInstanceIterator getLightInstanceIterator() const;
00446     uint32 getInstancedLightCount() const;
00447 };
00448 
00449 } // namespace Mesh
00450 } // namespace Sirikata
00451 
00452 #endif //_SIRIKATA_MESH_MESHDATA_HPP_