00001 /* 00002 ----------------------------------------------------------------------------- 00003 This source file is part of OGRE 00004 (Object-oriented Graphics Rendering Engine) 00005 For the latest info, see http://www.ogre3d.org 00006 00007 Copyright (c) 2000-2012 Torus Knot Software Ltd 00008 00009 Permission is hereby granted, free of charge, to any person obtaining a copy 00010 of this software and associated documentation files (the "Software"), to deal 00011 in the Software without restriction, including without limitation the rights 00012 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00013 copies of the Software, and to permit persons to whom the Software is 00014 furnished to do so, subject to the following conditions: 00015 00016 The above copyright notice and this permission notice shall be included in 00017 all copies or substantial portions of the Software. 00018 00019 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00020 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00021 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00022 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00023 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00024 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00025 THE SOFTWARE. 00026 ----------------------------------------------------------------------------- 00027 */ 00028 #ifndef __Pass_H__ 00029 #define __Pass_H__ 00030 00031 #include "OgrePrerequisites.h" 00032 #include "OgreGpuProgram.h" 00033 #include "OgreColourValue.h" 00034 #include "OgreBlendMode.h" 00035 #include "OgreCommon.h" 00036 #include "OgreLight.h" 00037 #include "OgreTextureUnitState.h" 00038 #include "OgreUserObjectBindings.h" 00039 00040 namespace Ogre { 00041 00048 00049 enum IlluminationStage 00050 { 00052 IS_AMBIENT, 00054 IS_PER_LIGHT, 00056 IS_DECAL, 00058 IS_UNKNOWN 00059 }; 00060 00080 class _OgreExport Pass : public PassAlloc 00081 { 00082 public: 00093 struct HashFunc 00094 { 00095 virtual uint32 operator()(const Pass* p) const = 0; 00097 virtual ~HashFunc() {} 00098 }; 00099 protected: 00100 Technique* mParent; 00101 unsigned short mIndex; // pass index 00102 String mName; // optional name for the pass 00103 uint32 mHash; // pass hash 00104 bool mHashDirtyQueued; // needs to be dirtied when next loaded 00105 //------------------------------------------------------------------------- 00106 // Colour properties, only applicable in fixed-function passes 00107 ColourValue mAmbient; 00108 ColourValue mDiffuse; 00109 ColourValue mSpecular; 00110 ColourValue mEmissive; 00111 Real mShininess; 00112 TrackVertexColourType mTracking; 00113 //------------------------------------------------------------------------- 00114 00115 //------------------------------------------------------------------------- 00116 // Blending factors 00117 SceneBlendFactor mSourceBlendFactor; 00118 SceneBlendFactor mDestBlendFactor; 00119 SceneBlendFactor mSourceBlendFactorAlpha; 00120 SceneBlendFactor mDestBlendFactorAlpha; 00121 00122 // Used to determine if separate alpha blending should be used for color and alpha channels 00123 bool mSeparateBlend; 00124 00125 //------------------------------------------------------------------------- 00126 // Blending operations 00127 SceneBlendOperation mBlendOperation; 00128 SceneBlendOperation mAlphaBlendOperation; 00129 00130 // Determines if we should use separate blending operations for color and alpha channels 00131 bool mSeparateBlendOperation; 00132 00133 //------------------------------------------------------------------------- 00134 00135 //------------------------------------------------------------------------- 00136 // Depth buffer settings 00137 bool mDepthCheck; 00138 bool mDepthWrite; 00139 CompareFunction mDepthFunc; 00140 float mDepthBiasConstant; 00141 float mDepthBiasSlopeScale; 00142 float mDepthBiasPerIteration; 00143 00144 // Colour buffer settings 00145 bool mColourWrite; 00146 00147 // Alpha reject settings 00148 CompareFunction mAlphaRejectFunc; 00149 unsigned char mAlphaRejectVal; 00150 bool mAlphaToCoverageEnabled; 00151 00152 // Transparent depth sorting 00153 bool mTransparentSorting; 00154 // Transparent depth sorting forced 00155 bool mTransparentSortingForced; 00156 //------------------------------------------------------------------------- 00157 00158 //------------------------------------------------------------------------- 00159 // Culling mode 00160 CullingMode mCullMode; 00161 ManualCullingMode mManualCullMode; 00162 //------------------------------------------------------------------------- 00163 00165 bool mLightingEnabled; 00167 unsigned short mMaxSimultaneousLights; 00169 unsigned short mStartLight; 00171 bool mIteratePerLight; 00173 unsigned short mLightsPerIteration; 00174 // Should it only be run for a certain light type? 00175 bool mRunOnlyForOneLightType; 00176 Light::LightTypes mOnlyLightType; 00177 // With a specific light mask? 00178 uint32 mLightMask; 00179 00181 ShadeOptions mShadeOptions; 00183 PolygonMode mPolygonMode; 00185 bool mNormaliseNormals; 00186 bool mPolygonModeOverrideable; 00187 //------------------------------------------------------------------------- 00188 // Fog 00189 bool mFogOverride; 00190 FogMode mFogMode; 00191 ColourValue mFogColour; 00192 Real mFogStart; 00193 Real mFogEnd; 00194 Real mFogDensity; 00195 //------------------------------------------------------------------------- 00196 00198 typedef vector<TextureUnitState*>::type TextureUnitStates; 00199 TextureUnitStates mTextureUnitStates; 00200 00201 // Vertex program details 00202 GpuProgramUsage *mVertexProgramUsage; 00203 // Vertex program details 00204 GpuProgramUsage *mShadowCasterVertexProgramUsage; 00205 // Fragment program details 00206 GpuProgramUsage *mShadowCasterFragmentProgramUsage; 00207 // Vertex program details 00208 GpuProgramUsage *mShadowReceiverVertexProgramUsage; 00209 // Fragment program details 00210 GpuProgramUsage *mFragmentProgramUsage; 00211 // Fragment program details 00212 GpuProgramUsage *mShadowReceiverFragmentProgramUsage; 00213 // Geometry program details 00214 GpuProgramUsage *mGeometryProgramUsage; 00215 // Is this pass queued for deletion? 00216 bool mQueuedForDeletion; 00217 // number of pass iterations to perform 00218 size_t mPassIterationCount; 00219 // point size, applies when not using per-vertex point size 00220 Real mPointSize; 00221 Real mPointMinSize; 00222 Real mPointMaxSize; 00223 bool mPointSpritesEnabled; 00224 bool mPointAttenuationEnabled; 00225 // constant, linear, quadratic coeffs 00226 Real mPointAttenuationCoeffs[3]; 00227 // TU Content type lookups 00228 typedef vector<unsigned short>::type ContentTypeLookup; 00229 mutable ContentTypeLookup mShadowContentTypeLookup; 00230 mutable bool mContentTypeLookupBuilt; 00232 bool mLightScissoring; 00234 bool mLightClipPlanes; 00236 IlluminationStage mIlluminationStage; 00237 // User objects binding. 00238 UserObjectBindings mUserObjectBindings; 00239 00240 00241 // Used to get scene blending flags from a blending type 00242 void _getBlendFlags(SceneBlendType type, SceneBlendFactor& source, SceneBlendFactor& dest); 00243 00244 public: 00245 typedef set<Pass*>::type PassSet; 00246 protected: 00248 static PassSet msDirtyHashList; 00250 static PassSet msPassGraveyard; 00252 static HashFunc* msHashFunc; 00253 public: 00254 OGRE_STATIC_MUTEX(msDirtyHashListMutex) 00255 OGRE_STATIC_MUTEX(msPassGraveyardMutex) 00256 OGRE_MUTEX(mTexUnitChangeMutex) 00257 OGRE_MUTEX(mGpuProgramChangeMutex) 00259 Pass(Technique* parent, unsigned short index); 00261 Pass(Technique* parent, unsigned short index, const Pass& oth ); 00263 Pass& operator=(const Pass& oth); 00264 virtual ~Pass(); 00265 00267 bool isProgrammable(void) const { return mVertexProgramUsage || mFragmentProgramUsage || mGeometryProgramUsage; } 00269 bool hasVertexProgram(void) const { return mVertexProgramUsage != NULL; } 00271 bool hasFragmentProgram(void) const { return mFragmentProgramUsage != NULL; } 00273 bool hasGeometryProgram(void) const { return mGeometryProgramUsage != NULL; } 00275 bool hasShadowCasterVertexProgram(void) const { return mShadowCasterVertexProgramUsage != NULL; } 00277 bool hasShadowCasterFragmentProgram(void) const { return mShadowCasterFragmentProgramUsage != NULL; } 00279 bool hasShadowReceiverVertexProgram(void) const { return mShadowReceiverVertexProgramUsage != NULL; } 00281 bool hasShadowReceiverFragmentProgram(void) const { return mShadowReceiverFragmentProgramUsage != NULL; } 00282 00283 00285 unsigned short getIndex(void) const { return mIndex; } 00286 /* Set the name of the pass 00287 @remarks 00288 The name of the pass is optional. Its useful in material scripts where a material could inherit 00289 from another material and only want to modify a particular pass. 00290 */ 00291 void setName(const String& name); 00293 const String& getName(void) const { return mName; } 00294 00306 void setAmbient(Real red, Real green, Real blue); 00307 00320 void setAmbient(const ColourValue& ambient); 00321 00332 void setDiffuse(Real red, Real green, Real blue, Real alpha); 00333 00344 void setDiffuse(const ColourValue& diffuse); 00345 00358 void setSpecular(Real red, Real green, Real blue, Real alpha); 00359 00372 void setSpecular(const ColourValue& specular); 00373 00379 void setShininess(Real val); 00380 00390 void setSelfIllumination(Real red, Real green, Real blue); 00391 00396 void setEmissive(Real red, Real green, Real blue) 00397 { 00398 setSelfIllumination(red, green, blue); 00399 } 00400 00410 void setSelfIllumination(const ColourValue& selfIllum); 00411 00416 void setEmissive(const ColourValue& emissive) 00417 { 00418 setSelfIllumination(emissive); 00419 } 00420 00423 void setVertexColourTracking(TrackVertexColourType tracking); 00424 00430 Real getPointSize(void) const; 00431 00447 void setPointSize(Real ps); 00448 00454 void setPointSpritesEnabled(bool enabled); 00455 00459 bool getPointSpritesEnabled(void) const; 00460 00477 void setPointAttenuation(bool enabled, 00478 Real constant = 0.0f, Real linear = 1.0f, Real quadratic = 0.0f); 00479 00481 bool isPointAttenuationEnabled(void) const; 00482 00484 Real getPointAttenuationConstant(void) const; 00486 Real getPointAttenuationLinear(void) const; 00488 Real getPointAttenuationQuadratic(void) const; 00489 00491 void setPointMinSize(Real min); 00493 Real getPointMinSize(void) const; 00497 void setPointMaxSize(Real max); 00501 Real getPointMaxSize(void) const; 00502 00505 const ColourValue& getAmbient(void) const; 00506 00509 const ColourValue& getDiffuse(void) const; 00510 00513 const ColourValue& getSpecular(void) const; 00514 00517 const ColourValue& getSelfIllumination(void) const; 00518 00523 const ColourValue& getEmissive(void) const 00524 { 00525 return getSelfIllumination(); 00526 } 00527 00530 Real getShininess(void) const; 00531 00534 TrackVertexColourType getVertexColourTracking(void) const; 00535 00540 TextureUnitState* createTextureUnitState(void); 00551 TextureUnitState* createTextureUnitState( const String& textureName, unsigned short texCoordSet = 0); 00557 void addTextureUnitState(TextureUnitState* state); 00560 TextureUnitState* getTextureUnitState(unsigned short index); 00564 TextureUnitState* getTextureUnitState(const String& name); 00567 const TextureUnitState* getTextureUnitState(unsigned short index) const; 00571 const TextureUnitState* getTextureUnitState(const String& name) const; 00572 00579 unsigned short getTextureUnitStateIndex(const TextureUnitState* state) const; 00580 00581 typedef VectorIterator<TextureUnitStates> TextureUnitStateIterator; 00583 TextureUnitStateIterator getTextureUnitStateIterator(void); 00584 00585 typedef ConstVectorIterator<TextureUnitStates> ConstTextureUnitStateIterator; 00587 ConstTextureUnitStateIterator getTextureUnitStateIterator(void) const; 00588 00593 void removeTextureUnitState(unsigned short index); 00594 00597 void removeAllTextureUnitStates(void); 00598 00601 unsigned short getNumTextureUnitStates(void) const 00602 { 00603 return static_cast<unsigned short>(mTextureUnitStates.size()); 00604 } 00605 00622 void setSceneBlending( const SceneBlendType sbt ); 00623 00642 void setSeparateSceneBlending( const SceneBlendType sbt, const SceneBlendType sbta ); 00643 00666 void setSceneBlending( const SceneBlendFactor sourceFactor, const SceneBlendFactor destFactor); 00667 00694 void setSeparateSceneBlending( const SceneBlendFactor sourceFactor, const SceneBlendFactor destFactor, const SceneBlendFactor sourceFactorAlpha, const SceneBlendFactor destFactorAlpha ); 00695 00697 bool hasSeparateSceneBlending() const; 00698 00701 SceneBlendFactor getSourceBlendFactor() const; 00702 00705 SceneBlendFactor getDestBlendFactor() const; 00706 00709 SceneBlendFactor getSourceBlendFactorAlpha() const; 00710 00713 SceneBlendFactor getDestBlendFactorAlpha() const; 00714 00725 void setSceneBlendingOperation(SceneBlendOperation op); 00726 00740 void setSeparateSceneBlendingOperation(SceneBlendOperation op, SceneBlendOperation alphaOp); 00741 00743 bool hasSeparateSceneBlendingOperations() const; 00744 00746 SceneBlendOperation getSceneBlendingOperation() const; 00747 00749 SceneBlendOperation getSceneBlendingOperationAlpha() const; 00750 00752 bool isTransparent(void) const; 00753 00765 void setDepthCheckEnabled(bool enabled); 00766 00771 bool getDepthCheckEnabled(void) const; 00772 00783 void setDepthWriteEnabled(bool enabled); 00784 00789 bool getDepthWriteEnabled(void) const; 00790 00798 void setDepthFunction( CompareFunction func ); 00803 CompareFunction getDepthFunction(void) const; 00804 00815 void setColourWriteEnabled(bool enabled); 00817 bool getColourWriteEnabled(void) const; 00818 00832 void setCullingMode( CullingMode mode ); 00833 00836 CullingMode getCullingMode(void) const; 00837 00851 void setManualCullingMode( ManualCullingMode mode ); 00852 00857 ManualCullingMode getManualCullingMode(void) const; 00858 00867 void setLightingEnabled(bool enabled); 00868 00871 bool getLightingEnabled(void) const; 00872 00881 void setMaxSimultaneousLights(unsigned short maxLights); 00883 unsigned short getMaxSimultaneousLights(void) const; 00884 00895 void setStartLight(unsigned short startLight); 00897 unsigned short getStartLight(void) const; 00898 00900 void setLightMask(uint32 mask); 00902 uint32 getLightMask() const; 00903 00908 void setShadingMode( ShadeOptions mode ); 00909 00912 ShadeOptions getShadingMode(void) const; 00913 00918 void setPolygonMode( PolygonMode mode ); 00919 00922 PolygonMode getPolygonMode(void) const; 00923 00929 virtual void setPolygonModeOverrideable(bool override) 00930 { 00931 mPolygonModeOverrideable = override; 00932 } 00933 00937 virtual bool getPolygonModeOverrideable(void) const 00938 { 00939 return mPolygonModeOverrideable; 00940 } 00970 void setFog( 00971 bool overrideScene, 00972 FogMode mode = FOG_NONE, 00973 const ColourValue& colour = ColourValue::White, 00974 Real expDensity = 0.001, Real linearStart = 0.0, Real linearEnd = 1.0 ); 00975 00978 bool getFogOverride(void) const; 00979 00984 FogMode getFogMode(void) const; 00985 00988 const ColourValue& getFogColour(void) const; 00989 00994 Real getFogStart(void) const; 00995 01000 Real getFogEnd(void) const; 01001 01006 Real getFogDensity(void) const; 01007 01027 void setDepthBias(float constantBias, float slopeScaleBias = 0.0f); 01028 01030 float getDepthBiasConstant(void) const; 01032 float getDepthBiasSlopeScale(void) const; 01039 void setIterationDepthBias(float biasPerIteration); 01043 float getIterationDepthBias() const; 01044 01054 void setAlphaRejectSettings(CompareFunction func, unsigned char value, bool alphaToCoverageEnabled = false); 01055 01058 void setAlphaRejectFunction(CompareFunction func); 01059 01062 void setAlphaRejectValue(unsigned char val); 01063 01066 CompareFunction getAlphaRejectFunction(void) const { return mAlphaRejectFunc; } 01067 01070 unsigned char getAlphaRejectValue(void) const { return mAlphaRejectVal; } 01071 01079 void setAlphaToCoverageEnabled(bool enabled); 01080 01083 bool isAlphaToCoverageEnabled() const { return mAlphaToCoverageEnabled; } 01084 01097 void setTransparentSortingEnabled(bool enabled); 01098 01101 bool getTransparentSortingEnabled(void) const; 01102 01112 void setTransparentSortingForced(bool enabled); 01113 01116 bool getTransparentSortingForced(void) const; 01117 01160 void setIteratePerLight(bool enabled, 01161 bool onlyForOneLightType = true, Light::LightTypes lightType = Light::LT_POINT); 01162 01164 bool getIteratePerLight(void) const { return mIteratePerLight; } 01166 bool getRunOnlyForOneLightType(void) const { return mRunOnlyForOneLightType; } 01169 Light::LightTypes getOnlyLightType() const { return mOnlyLightType; } 01170 01180 void setLightCountPerIteration(unsigned short c); 01184 unsigned short getLightCountPerIteration(void) const; 01185 01187 Technique* getParent(void) const { return mParent; } 01188 01190 const String& getResourceGroup(void) const; 01191 01208 void setVertexProgram(const String& name, bool resetParams = true); 01215 void setVertexProgramParameters(GpuProgramParametersSharedPtr params); 01217 const String& getVertexProgramName(void) const; 01219 GpuProgramParametersSharedPtr getVertexProgramParameters(void) const; 01221 const GpuProgramPtr& getVertexProgram(void) const; 01222 01223 01253 void setShadowCasterVertexProgram(const String& name); 01260 void setShadowCasterVertexProgramParameters(GpuProgramParametersSharedPtr params); 01262 const String& getShadowCasterVertexProgramName(void) const; 01264 GpuProgramParametersSharedPtr getShadowCasterVertexProgramParameters(void) const; 01267 const GpuProgramPtr& getShadowCasterVertexProgram(void) const; 01268 01298 void setShadowCasterFragmentProgram(const String& name); 01305 void setShadowCasterFragmentProgramParameters(GpuProgramParametersSharedPtr params); 01307 const String& getShadowCasterFragmentProgramName(void) const; 01309 GpuProgramParametersSharedPtr getShadowCasterFragmentProgramParameters(void) const; 01312 const GpuProgramPtr& getShadowCasterFragmentProgram(void) const; 01313 01339 void setShadowReceiverVertexProgram(const String& name); 01346 void setShadowReceiverVertexProgramParameters(GpuProgramParametersSharedPtr params); 01347 01368 void setShadowReceiverFragmentProgram(const String& name); 01375 void setShadowReceiverFragmentProgramParameters(GpuProgramParametersSharedPtr params); 01376 01378 const String& getShadowReceiverVertexProgramName(void) const; 01380 GpuProgramParametersSharedPtr getShadowReceiverVertexProgramParameters(void) const; 01383 const GpuProgramPtr& getShadowReceiverVertexProgram(void) const; 01384 01386 const String& getShadowReceiverFragmentProgramName(void) const; 01388 GpuProgramParametersSharedPtr getShadowReceiverFragmentProgramParameters(void) const; 01391 const GpuProgramPtr& getShadowReceiverFragmentProgram(void) const; 01392 01409 void setFragmentProgram(const String& name, bool resetParams = true); 01414 void setFragmentProgramParameters(GpuProgramParametersSharedPtr params); 01416 const String& getFragmentProgramName(void) const; 01418 GpuProgramParametersSharedPtr getFragmentProgramParameters(void) const; 01420 const GpuProgramPtr& getFragmentProgram(void) const; 01421 01438 void setGeometryProgram(const String& name, bool resetParams = true); 01443 void setGeometryProgramParameters(GpuProgramParametersSharedPtr params); 01445 const String& getGeometryProgramName(void) const; 01447 GpuProgramParametersSharedPtr getGeometryProgramParameters(void) const; 01449 const GpuProgramPtr& getGeometryProgram(void) const; 01450 01462 Pass* _split(unsigned short numUnits); 01463 01465 void _notifyIndex(unsigned short index); 01466 01468 void _prepare(void); 01470 void _unprepare(void); 01472 void _load(void); 01474 void _unload(void); 01475 // Is this loaded? 01476 bool isLoaded(void) const; 01477 01484 uint32 getHash(void) const { return mHash; } 01486 void _dirtyHash(void); 01493 void _recalculateHash(void); 01495 void _notifyNeedsRecompile(void); 01496 01501 void _updateAutoParams(const AutoParamDataSource* source, uint16 variabilityMask) const; 01502 01509 unsigned short _getTextureUnitWithContentTypeIndex( 01510 TextureUnitState::ContentType contentType, unsigned short index) const; 01511 01520 void setTextureFiltering(TextureFilterOptions filterType); 01529 void setTextureAnisotropy(unsigned int maxAniso); 01541 void setNormaliseNormals(bool normalise) { mNormaliseNormals = normalise; } 01542 01544 bool getNormaliseNormals(void) const {return mNormaliseNormals; } 01545 01549 static const PassSet& getDirtyHashList(void) 01550 { return msDirtyHashList; } 01553 static const PassSet& getPassGraveyard(void) 01554 { return msPassGraveyard; } 01562 static void clearDirtyHashList(void); 01563 01565 static void processPendingPassUpdates(void); 01566 01568 void queueForDeletion(void); 01569 01572 bool isAmbientOnly(void) const; 01573 01587 void setPassIterationCount(const size_t count) { mPassIterationCount = count; } 01588 01591 size_t getPassIterationCount(void) const { return mPassIterationCount; } 01592 01604 bool applyTextureAliases(const AliasTextureNamePairList& aliasList, const bool apply = true) const; 01605 01626 void setLightScissoringEnabled(bool enabled) { mLightScissoring = enabled; } 01630 bool getLightScissoringEnabled() const { return mLightScissoring; } 01631 01655 void setLightClipPlanesEnabled(bool enabled) { mLightClipPlanes = enabled; } 01659 bool getLightClipPlanesEnabled() const { return mLightClipPlanes; } 01660 01682 void setIlluminationStage(IlluminationStage is) { mIlluminationStage = is; } 01684 IlluminationStage getIlluminationStage() const { return mIlluminationStage; } 01688 enum BuiltinHashFunction 01689 { 01691 MIN_TEXTURE_CHANGE, 01696 MIN_GPU_PROGRAM_CHANGE 01697 }; 01710 static void setHashFunction(BuiltinHashFunction builtin); 01711 01723 static void setHashFunction(HashFunc* hashFunc) { msHashFunc = hashFunc; } 01724 01727 static HashFunc* getHashFunction(void) { return msHashFunc; } 01728 01731 static HashFunc* getBuiltinHashFunction(BuiltinHashFunction builtin); 01732 01737 UserObjectBindings& getUserObjectBindings() { return mUserObjectBindings; } 01738 01743 const UserObjectBindings& getUserObjectBindings() const { return mUserObjectBindings; } 01744 }; 01745 01755 struct IlluminationPass : public PassAlloc 01756 { 01757 IlluminationStage stage; 01759 Pass* pass; 01761 bool destroyOnShutdown; 01763 Pass* originalPass; 01764 01765 IlluminationPass() {} 01766 }; 01767 01768 typedef vector<IlluminationPass*>::type IlluminationPassList; 01769 01773 } 01774 01775 #endif
Copyright © 2012 Torus Knot Software Ltd
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
Last modified Fri May 25 23:36:25 2012