public void Assign( QueuedSubMesh qsm ) { this.queuedSubMeshes.Add( qsm ); // update lod distances var mesh = qsm.submesh.Parent; var lodStrategy = mesh.LodStrategy; if ( this.lodStrategy == null ) { this.lodStrategy = lodStrategy; // First LOD mandatory, and always from base lod value this.lodValues.Add( this.lodStrategy.BaseValue ); } else { if ( this.lodStrategy != lodStrategy ) { throw new AxiomException( "Lod strategies do not match." ); } } var lodLevels = mesh.LodLevelCount; if ( qsm.geometryLodList.Count != lodLevels ) { var msg = string.Format( "QueuedSubMesh '{0}' lod count of {1} does not match parent count of {2}", qsm.submesh.Name, qsm.geometryLodList.Count, lodLevels ); throw new AxiomException( msg ); } while ( this.lodValues.Count < lodLevels ) { this.lodValues.Add( 0.0f ); } // Make sure LOD levels are max of all at the requested level for ( ushort lod = 1; lod < lodLevels; ++lod ) { var meshLod = qsm.submesh.Parent.GetLodLevel( lod ); this.lodValues[ lod ] = Utility.Max( (float)this.lodValues[ lod ], meshLod.Value ); } // update bounds // Transform world bounds relative to our center var localBounds = new AxisAlignedBox( qsm.worldBounds.Minimum - this.center, qsm.worldBounds.Maximum - this.center ); this.aabb.Merge( localBounds ); foreach ( var corner in localBounds.Corners ) { this.boundingRadius = Utility.Max( this.boundingRadius, corner.Length ); } }
/// <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(); }