Example #1
0
        /// <summary>
        /// </summary>
        protected static ushort GetIndexDescending(float value, LodValueList materialLodValueList)
        {
            ushort index = 0;

            for (var i = 0; i < materialLodValueList.Count; i++, index++)
            {
                if (materialLodValueList[i] < value)
                {
                    return((ushort)(index - 1));
                }
            }
            return((ushort)(materialLodValueList.Count - 1));
        }
Example #2
0
 public Region(StaticGeometry parent, string name, SceneManager mgr, UInt32 regionID, Vector3 center)
     : base(name)
 {
     MovableType            = "StaticGeometry";
     this.parent            = parent;
     this.sceneMgr          = mgr;
     this.regionID          = regionID;
     this.center            = center;
     this.queuedSubMeshes   = new List <QueuedSubMesh>();
     this.lodValues         = new LodValueList();
     this.aabb              = new AxisAlignedBox();
     this.lodBucketList     = new List <LODBucket>();
     this.shadowRenderables = new ShadowRenderableList();
 }
Example #3
0
        public void GetIndexDescendingTest()
        {
            var materialLodUsageList = new LodValueList()
            {
                new Real(3.0f), new Real(2.0f), new Real(1.0f), new Real(0.0f)
            };
            var lodStrategy = new LodStategyDescending();

            for (int expected = 0; expected < materialLodUsageList.Count; expected++)
            {
                int actual = lodStrategy.GetIndex(3.0f - expected, materialLodUsageList);
                Assert.AreEqual(expected, actual);
            }
        }
Example #4
0
 /// <summary>
 /// Implementation of isSorted suitable for descending values.
 /// </summary>
 /// <param name="values"></param>
 /// <returns></returns>
 protected static bool IsSortedDescending(LodValueList values)
 {
     for (var i = 0; i < values.Count; i++)
     {
         float prev = values[i];
         if (i + 1 < values.Count)
         {
             if (values[i + 1] > prev)
             {
                 return(false);
             }
         }
     }
     return(true);
 }
Example #5
0
		public void GenerateLodLevels( LodValueList lodValues, ProgressiveMesh.VertexReductionQuota reductionMethod,
		                               Real reductionValue )
		{
			RemoveLodLevels();

			LogManager.Instance.Write( "Generating {0} lower LODs for mesh {1}.", lodValues.Count, Name );

			foreach ( var subMesh in this._subMeshList )
			{
				// check if triangles are present
				if ( subMesh.IndexData.indexCount > 0 )
				{
					// Set up data for reduction
					var vertexData = subMesh.useSharedVertices ? this._sharedVertexData : subMesh.vertexData;

					var pm = new ProgressiveMesh( vertexData, subMesh.indexData );
					pm.Build( (ushort)lodValues.Count, subMesh.lodFaceList, reductionMethod, reductionValue );
				}
				else
				{
					// create empty index data for each lod
					for ( var i = 0; i < lodValues.Count; ++i )
					{
						subMesh.LodFaceList.Add( new IndexData() );
					}
				}
			}

			// Iterate over the lods and record usage
			foreach ( var value in lodValues )
			{
				// Record usage
				var lod = new MeshLodUsage();
				lod.UserValue = value;
				lod.Value = this._lodStrategy.TransformUserValue( value );
				lod.EdgeData = null;
				lod.ManualMesh = null;
				this.meshLodUsageList.Add( lod );
			}
		}
			/// <summary>
			/// 
			/// </summary>
			/// <param name="terrain"></param>
			/// <returns></returns>
			public override Material Generate( Terrain terrain )
			{
				// re-use old material if exists
				Material mat = terrain._Material;
				if ( mat == null )
				{
					MaterialManager matMgr = MaterialManager.Instance;
					// it's important that the names are deterministic for a given terrain, so
					// use the terrain pointer as an ID+
					string matName = terrain.MaterialName;
					mat = (Material)matMgr.GetByName( matName );
					if ( mat == null )
					{
						mat = (Material)matMgr.Create( matName, ResourceGroupManager.DefaultResourceGroupName );
					}
				}

				// clear everything
				mat.RemoveAllTechniques();
				AddTechnique( mat, terrain, TechniqueType.HighLod );

				//LOD
				if ( this.mCompositeMapEnabled )
				{
					AddTechnique( mat, terrain, TechniqueType.LowLod );
					var lodValues = new LodValueList();
					lodValues.Add( 3000 ); //TerrainGlobalOptions.CompositeMapDistance);
					mat.SetLodLevels( lodValues );
					Technique lowLodTechnique = mat.GetTechnique( 1 );
					lowLodTechnique.LodIndex = 1;
				}
				UpdateParams( mat, terrain );
				//mat.Compile(true);
				return mat;
			}
Example #7
0
 public override bool IsSorted(LodValueList values)
 {
     // Check if values are sorted descending
     return(IsSortedDescending(values));
 }
Example #8
0
 public override bool IsSorted(LodValueList values)
 {
     return(IsSortedAscending(values));
 }
Example #9
0
			public Region( StaticGeometry parent, string name, SceneManager mgr, UInt32 regionID, Vector3 center )
				: base( name )
			{
				MovableType = "StaticGeometry";
				this.parent = parent;
				this.sceneMgr = mgr;
				this.regionID = regionID;
				this.center = center;
				this.queuedSubMeshes = new List<QueuedSubMesh>();
				this.lodValues = new LodValueList();
				this.aabb = new AxisAlignedBox();
				this.lodBucketList = new List<LODBucket>();
				this.shadowRenderables = new ShadowRenderableList();
			}
Example #10
0
 public abstract bool IsSorted(LodValueList values);
Example #11
0
 public override ushort GetIndex(Real value, LodValueList materialLodValueList)
 {
     return(GetIndexAscending(value, materialLodValueList));
 }
Example #12
0
		protected static bool ParseLodDistances( string parameters, MaterialScriptContext context )
		{
			context.material.LodStrategy = LodStrategyManager.Instance.GetStrategy( DistanceLodStrategy.StrategyName );

			string[] values = parameters.Split( new char[] { ' ', '\t' } );

			LodValueList lodDistances = new LodValueList();

			for ( int i = 0; i < values.Length; i++ )
			{
				lodDistances.Add( StringConverter.ParseFloat( values[ i ] ) );
			}

			context.material.SetLodLevels( lodDistances );

			return false;
		}
Example #13
0
 public override ushort GetIndex(Real value, LodValueList materialLodValueList)
 {
     // Values are descending
     return(GetIndexDescending(value, materialLodValueList));
 }
Example #14
0
            /// <see cref="Translator.Translate"/>
            public override void Translate(ScriptCompiler compiler, AbstractNode node)
            {
                var obj = (ObjectAbstractNode)node;

                if (obj != null)
                {
                    if (string.IsNullOrEmpty(obj.Name))
                    {
                        compiler.AddError(CompileErrorCode.ObjectNameExpected, obj.File, obj.Line);
                    }
                }
                else
                {
                    compiler.AddError(CompileErrorCode.ObjectNameExpected, node.File, node.Line);
                    return;
                }

                // Create a material with the given name
                object mat;
                ScriptCompilerEvent evt = new CreateMaterialScriptCompilerEvent(node.File, obj.Name, compiler.ResourceGroup);
                var processed           = compiler._fireEvent(ref evt, out mat);

                if (!processed)
                {
                    //TODO
                    // The original translated implementation of this code block was simply the following:
                    // _material = (Material)MaterialManager.Instance.Create( obj.Name, compiler.ResourceGroup );
                    // but sometimes it generates an exception due to a duplicate resource.
                    // In order to avoid the above mentioned exception, the implementation was changed, but
                    // it need to be checked when ResourceManager._add will be updated to the latest version

                    var checkForExistingMat = (Material)MaterialManager.Instance.GetByName(obj.Name);

                    if (checkForExistingMat == null)
                    {
                        this._material = (Material)MaterialManager.Instance.Create(obj.Name, compiler.ResourceGroup);
                    }
                    else
                    {
                        this._material = checkForExistingMat;
                    }
                }
                else
                {
                    this._material = (Material)mat;

                    if (this._material == null)
                    {
                        compiler.AddError(CompileErrorCode.ObjectAllocationError, obj.File, obj.Line,
                                          "failed to find or create material \"" + obj.Name + "\"");
                    }
                }

                this._material.RemoveAllTechniques();
                obj.Context           = this._material;
                this._material.Origin = obj.File;

                foreach (var i in obj.Children)
                {
                    if (i is PropertyAbstractNode)
                    {
                        var prop = (PropertyAbstractNode)i;

                        switch ((Keywords)prop.Id)
                        {
                            #region ID_LOD_VALUES

                        case Keywords.ID_LOD_VALUES:
                        {
                            var lods = new LodValueList();
                            foreach (var j in prop.Values)
                            {
                                Real v = 0;
                                if (getReal(j, out v))
                                {
                                    lods.Add(v);
                                }
                                else
                                {
                                    compiler.AddError(CompileErrorCode.NumberExpected, prop.File, prop.Line,
                                                      "lod_values expects only numbers as arguments");
                                }
                            }
                            this._material.SetLodLevels(lods);
                        }
                        break;

                            #endregion ID_LOD_VALUES

                            #region ID_LOD_DISTANCES

                        case Keywords.ID_LOD_DISTANCES:
                        {
                            // Set strategy to distance strategy
                            LodStrategy strategy = DistanceLodStrategy.Instance;
                            this._material.LodStrategy = strategy;

                            // Real in lod distances
                            var lods = new LodValueList();
                            foreach (var j in prop.Values)
                            {
                                Real v = 0;
                                if (getReal(j, out v))
                                {
                                    lods.Add(v);
                                }
                                else
                                {
                                    compiler.AddError(CompileErrorCode.NumberExpected, prop.File, prop.Line,
                                                      "lod_values expects only numbers as arguments");
                                }
                            }
                            this._material.SetLodLevels(lods);
                        }
                        break;

                            #endregion ID_LOD_DISTANCES

                            #region ID_LOD_STRATEGY

                        case Keywords.ID_LOD_STRATEGY:
                            if (prop.Values.Count == 0)
                            {
                                compiler.AddError(CompileErrorCode.StringExpected, prop.File, prop.Line);
                            }
                            else if (prop.Values.Count > 1)
                            {
                                compiler.AddError(CompileErrorCode.FewerParametersExpected, prop.File, prop.Line,
                                                  "lod_strategy only supports 1 argument");
                            }
                            else
                            {
                                var strategyName = string.Empty;
                                var result       = getString(prop.Values[0], out strategyName);
                                if (result)
                                {
                                    var strategy = LodStrategyManager.Instance.GetStrategy(strategyName);

                                    result = strategy != null;

                                    if (result)
                                    {
                                        this._material.LodStrategy = strategy;
                                    }
                                }

                                if (!result)
                                {
                                    compiler.AddError(CompileErrorCode.InvalidParameters, prop.File, prop.Line,
                                                      "lod_strategy argument must be a valid lod strategy");
                                }
                            }
                            break;

                            #endregion ID_LOD_STRATEGY

                            #region ID_RECEIVE_SHADOWS

                        case Keywords.ID_RECEIVE_SHADOWS:
                            if (prop.Values.Count == 0)
                            {
                                compiler.AddError(CompileErrorCode.StringExpected, prop.File, prop.Line);
                            }
                            else if (prop.Values.Count > 1)
                            {
                                compiler.AddError(CompileErrorCode.FewerParametersExpected, prop.File, prop.Line,
                                                  "receive_shadows only supports 1 argument");
                            }
                            else
                            {
                                var val = true;
                                if (getBoolean(prop.Values[0], out val))
                                {
                                    this._material.ReceiveShadows = val;
                                }
                                else
                                {
                                    compiler.AddError(CompileErrorCode.InvalidParameters, prop.File, prop.Line,
                                                      "receive_shadows argument must be \"true\", \"false\", \"yes\", \"no\", \"on\", or \"off\"");
                                }
                            }
                            break;

                            #endregion ID_RECEIVE_SHADOWS

                            #region ID_TRANSPARENCY_CASTS_SHADOWS

                        case Keywords.ID_TRANSPARENCY_CASTS_SHADOWS:
                            if (prop.Values.Count == 0)
                            {
                                compiler.AddError(CompileErrorCode.StringExpected, prop.File, prop.Line);
                            }
                            else if (prop.Values.Count > 1)
                            {
                                compiler.AddError(CompileErrorCode.FewerParametersExpected, prop.File, prop.Line,
                                                  "transparency_casts_shadows only supports 1 argument");
                            }
                            else
                            {
                                var val = true;
                                if (getBoolean(prop.Values[0], out val))
                                {
                                    this._material.TransparencyCastsShadows = val;
                                }
                                else
                                {
                                    compiler.AddError(CompileErrorCode.InvalidParameters, prop.File, prop.Line,
                                                      "transparency_casts_shadows argument must be \"true\", \"false\", \"yes\", \"no\", \"on\", or \"off\"");
                                }
                            }
                            break;

                            #endregion ID_TRANSPARENCY_CASTS_SHADOWS

                            #region ID_SET_TEXTURE_ALIAS

                        case Keywords.ID_SET_TEXTURE_ALIAS:
                            if (prop.Values.Count == 0)
                            {
                                compiler.AddError(CompileErrorCode.StringExpected, prop.File, prop.Line);
                            }
                            else if (prop.Values.Count > 3)
                            {
                                compiler.AddError(CompileErrorCode.FewerParametersExpected, prop.File, prop.Line);
                            }
                            else
                            {
                                AbstractNode i0 = getNodeAt(prop.Values, 0), i1 = getNodeAt(prop.Values, 1);
                                String       name, value;
                                if (getString(i0, out name) && getString(i1, out value))
                                {
                                    this._textureAliases.Add(name, value);
                                }
                                else
                                {
                                    compiler.AddError(CompileErrorCode.InvalidParameters, prop.File, prop.Line,
                                                      "set_texture_alias must have 2 string argument");
                                }
                            }
                            break;

                            #endregion ID_SET_TEXTURE_ALIAS

                        default:
                            compiler.AddError(CompileErrorCode.UnexpectedToken, prop.File, prop.Line,
                                              "token \"" + prop.Name + "\" is not recognized");
                            break;
                        } //end of switch statement
                    }
                    else if (i is ObjectAbstractNode)
                    {
                        processNode(compiler, i);
                    }
                }

                // Apply the texture aliases
                ScriptCompilerEvent locEvt = new PreApplyTextureAliasesScriptCompilerEvent(this._material, ref this._textureAliases);
                compiler._fireEvent(ref locEvt);

                this._material.ApplyTextureAliases(this._textureAliases);
                this._textureAliases.Clear();
            }
Example #15
0
		public override ushort GetIndex( Real value, LodValueList materialLodValueList )
		{
			// Values are descending
			return GetIndexDescending( value, materialLodValueList );
		}
Example #16
0
 public override bool IsSorted(LodValueList values)
 {
     throw new NotImplementedException();
 }
Example #17
0
        public void GetIndexDescendingTest()
        {
            var materialLodUsageList = new LodValueList()
                                       {
                                           new Real( 3.0f ), new Real( 2.0f ), new Real( 1.0f ), new Real( 0.0f )
                                       };
            var lodStrategy = new LodStategyDescending();

            for ( int expected = 0; expected < materialLodUsageList.Count; expected++ )
            {
                int actual = lodStrategy.GetIndex( 3.0f - expected, materialLodUsageList );
                Assert.AreEqual( expected, actual );
            }
        }
Example #18
0
 public override ushort GetIndex(Axiom.Math.Real value, LodValueList materialLodValueList)
 {
     return(GetIndexDescending(value, materialLodValueList));
 }
Example #19
0
 public override ushort GetIndex( Axiom.Math.Real value, LodValueList materialLodValueList )
 {
     return GetIndexDescending( value, materialLodValueList );
 }
Example #20
0
 public override bool IsSorted( LodValueList values )
 {
     throw new NotImplementedException();
 }
Example #21
0
		public override bool IsSorted( LodValueList values )
		{
			// Check if values are sorted descending
			return IsSortedDescending( values );
		}
Example #22
0
 public abstract ushort GetIndex(Real value, LodValueList materialLodValueList);
Example #23
0
			/// <see cref="Translator.Translate"/>
			public override void Translate( ScriptCompiler compiler, AbstractNode node )
			{
				var obj = (ObjectAbstractNode)node;
				if ( obj != null )
				{
					if ( string.IsNullOrEmpty( obj.Name ) )
					{
						compiler.AddError( CompileErrorCode.ObjectNameExpected, obj.File, obj.Line );
					}
				}
				else
				{
					compiler.AddError( CompileErrorCode.ObjectNameExpected, node.File, node.Line );
					return;
				}

				// Create a material with the given name
				object mat;
				ScriptCompilerEvent evt = new CreateMaterialScriptCompilerEvent( node.File, obj.Name, compiler.ResourceGroup );
				var processed = compiler._fireEvent( ref evt, out mat );

				if ( !processed )
				{
					//TODO
					// The original translated implementation of this code block was simply the following:
					// _material = (Material)MaterialManager.Instance.Create( obj.Name, compiler.ResourceGroup );
					// but sometimes it generates an exception due to a duplicate resource.
					// In order to avoid the above mentioned exception, the implementation was changed, but
					// it need to be checked when ResourceManager._add will be updated to the latest version

					var checkForExistingMat = (Material)MaterialManager.Instance.GetByName( obj.Name );

					if ( checkForExistingMat == null )
					{
						this._material = (Material)MaterialManager.Instance.Create( obj.Name, compiler.ResourceGroup );
					}
					else
					{
						this._material = checkForExistingMat;
					}
				}
				else
				{
					this._material = (Material)mat;

					if ( this._material == null )
					{
						compiler.AddError( CompileErrorCode.ObjectAllocationError, obj.File, obj.Line,
						                   "failed to find or create material \"" + obj.Name + "\"" );
					}
				}

				this._material.RemoveAllTechniques();
				obj.Context = this._material;
				this._material.Origin = obj.File;

				foreach ( var i in obj.Children )
				{
					if ( i is PropertyAbstractNode )
					{
						var prop = (PropertyAbstractNode)i;

						switch ( (Keywords)prop.Id )
						{
								#region ID_LOD_VALUES

							case Keywords.ID_LOD_VALUES:
							{
								var lods = new LodValueList();
								foreach ( var j in prop.Values )
								{
									Real v = 0;
									if ( getReal( j, out v ) )
									{
										lods.Add( v );
									}
									else
									{
										compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line,
										                   "lod_values expects only numbers as arguments" );
									}
								}
								this._material.SetLodLevels( lods );
							}
								break;

								#endregion ID_LOD_VALUES

								#region ID_LOD_DISTANCES

							case Keywords.ID_LOD_DISTANCES:
							{
								// Set strategy to distance strategy
								LodStrategy strategy = DistanceLodStrategy.Instance;
								this._material.LodStrategy = strategy;

								// Real in lod distances
								var lods = new LodValueList();
								foreach ( var j in prop.Values )
								{
									Real v = 0;
									if ( getReal( j, out v ) )
									{
										lods.Add( v );
									}
									else
									{
										compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line,
										                   "lod_values expects only numbers as arguments" );
									}
								}
								this._material.SetLodLevels( lods );
							}
								break;

								#endregion ID_LOD_DISTANCES

								#region ID_LOD_STRATEGY

							case Keywords.ID_LOD_STRATEGY:
								if ( prop.Values.Count == 0 )
								{
									compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line );
								}
								else if ( prop.Values.Count > 1 )
								{
									compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line,
									                   "lod_strategy only supports 1 argument" );
								}
								else
								{
									var strategyName = string.Empty;
									var result = getString( prop.Values[ 0 ], out strategyName );
									if ( result )
									{
										var strategy = LodStrategyManager.Instance.GetStrategy( strategyName );

										result = strategy != null;

										if ( result )
										{
											this._material.LodStrategy = strategy;
										}
									}

									if ( !result )
									{
										compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line,
										                   "lod_strategy argument must be a valid lod strategy" );
									}
								}
								break;

								#endregion ID_LOD_STRATEGY

								#region ID_RECEIVE_SHADOWS

							case Keywords.ID_RECEIVE_SHADOWS:
								if ( prop.Values.Count == 0 )
								{
									compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line );
								}
								else if ( prop.Values.Count > 1 )
								{
									compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line,
									                   "receive_shadows only supports 1 argument" );
								}
								else
								{
									var val = true;
									if ( getBoolean( prop.Values[ 0 ], out val ) )
									{
										this._material.ReceiveShadows = val;
									}
									else
									{
										compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line,
										                   "receive_shadows argument must be \"true\", \"false\", \"yes\", \"no\", \"on\", or \"off\"" );
									}
								}
								break;

								#endregion ID_RECEIVE_SHADOWS

								#region ID_TRANSPARENCY_CASTS_SHADOWS

							case Keywords.ID_TRANSPARENCY_CASTS_SHADOWS:
								if ( prop.Values.Count == 0 )
								{
									compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line );
								}
								else if ( prop.Values.Count > 1 )
								{
									compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line,
									                   "transparency_casts_shadows only supports 1 argument" );
								}
								else
								{
									var val = true;
									if ( getBoolean( prop.Values[ 0 ], out val ) )
									{
										this._material.TransparencyCastsShadows = val;
									}
									else
									{
										compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line,
										                   "transparency_casts_shadows argument must be \"true\", \"false\", \"yes\", \"no\", \"on\", or \"off\"" );
									}
								}
								break;

								#endregion ID_TRANSPARENCY_CASTS_SHADOWS

								#region ID_SET_TEXTURE_ALIAS

							case Keywords.ID_SET_TEXTURE_ALIAS:
								if ( prop.Values.Count == 0 )
								{
									compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line );
								}
								else if ( prop.Values.Count > 3 )
								{
									compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line );
								}
								else
								{
									AbstractNode i0 = getNodeAt( prop.Values, 0 ), i1 = getNodeAt( prop.Values, 1 );
									String name, value;
									if ( getString( i0, out name ) && getString( i1, out value ) )
									{
										this._textureAliases.Add( name, value );
									}
									else
									{
										compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line,
										                   "set_texture_alias must have 2 string argument" );
									}
								}
								break;

								#endregion ID_SET_TEXTURE_ALIAS

							default:
								compiler.AddError( CompileErrorCode.UnexpectedToken, prop.File, prop.Line,
								                   "token \"" + prop.Name + "\" is not recognized" );
								break;
						} //end of switch statement
					}
					else if ( i is ObjectAbstractNode )
					{
						processNode( compiler, i );
					}
				}

				// Apply the texture aliases
				ScriptCompilerEvent locEvt = new PreApplyTextureAliasesScriptCompilerEvent( this._material, ref this._textureAliases );
				compiler._fireEvent( ref locEvt );

				this._material.ApplyTextureAliases( this._textureAliases );
				this._textureAliases.Clear();
			}
Example #24
0
		/// <summary>
		///		Sets the distance at which level-of-detail (LOD) levels come into effect.
		/// </summary>
		/// <remarks>
		///		You should only use this if you have assigned LOD indexes to the <see cref="Technique"/>
		///		instances attached to this <see cref="Material"/>. If you have done so, you should call this
		///		method to determine the distance at which the low levels of detail kick in.
		///		The decision about what distance is actually used is a combination of this
		///		and the LOD bias applied to both the current <see cref="Camera"/> and the current Entity.
		/// </remarks>
        /// <param name="lodDistanceList">
		///		A list of floats which indicate the distance at which to
		///		switch to lower details. They are listed in LOD index order, starting at index
		///		1 (ie the first level down from the highest level 0, which automatically applies
		///		from a distance of 0).
		/// </param>
		/// <ogre name="setLoadLevels" />
		public void SetLodLevels( LodValueList lodDistanceList )
		{
			// clear and add the 0 distance entry
			this._lodValues.Clear();
			this.UserLodValues.Clear();
			this.UserLodValues.Add( float.NaN );
			this._lodValues.Add( LodStrategy.BaseValue );

			foreach ( Real lodValue in lodDistanceList )
			{
				this.UserLodValues.Add( lodValue );
				if ( LodStrategy != null )
				{
					this._lodValues.Add( LodStrategy.TransformUserValue( lodValue ) );
				}
			}
		}