/// <summary> /// Create the corresponding <see cref="LightsState.Light"/> for this object. /// </summary> /// <returns> /// It returns the <see cref="LightsState.Light"/> equivalent to this SceneObjectLight. /// </returns> public override LightsState.Light ToLight(GraphicsContext ctx, SceneGraphContext sceneCtx) { TransformStateBase transformState = (TransformStateBase)sceneCtx.GraphicsStateStack.Current[TransformStateBase.StateSetIndex]; LightsState.LightSpot light = new LightsState.LightSpot(); SetLightParameters(sceneCtx, light); IModelMatrix worldModel = transformState.LocalModelView; IMatrix3x3 normalMatrix = worldModel.GetComplementMatrix(3, 3).GetInverseMatrix().Transpose(); light.Direction = ((Vertex3f)normalMatrix.Multiply((Vertex3f)Direction)).Normalized; light.Position = (Vertex3f)worldModel.Multiply(Vertex3f.Zero); light.AttenuationFactors = AttenuationFactors; light.FallOff = new Vertex2f((float)Math.Cos(Angle.ToRadians(FalloffAngle)), FalloffExponent); // Shadow mapping if (_ShadowMap != null && _ShadowViewMatrix != null) { // Determined later: light.ShadowMapIndex light.ShadowMapMvp.Set(_ShadowViewMatrix); light.ShadowMap2D = _ShadowMap; } else { light.ShadowMapIndex = -1; light.ShadowMap2D = null; } return(light); }
/// <summary> /// Get geometries related to this object. /// </summary> /// <param name="ctx"></param> /// <param name="ctxScene"></param> /// <returns></returns> internal override IEnumerable <SceneObjectBatch> GetGeometries(GraphicsContext ctx, SceneGraphContext ctxScene) { List <SceneObjectBatch> geometries = new List <SceneObjectBatch>(); GraphicsStateSet sceneGeometryState = ctxScene.GraphicsStateStack.Current.Push(); TransformStateBase sceneGeometryModel = (TransformStateBase)sceneGeometryState[TransformStateBase.StateSetIndex]; if ((ctxScene.Scene.SceneFlags & SceneGraphFlags.CullingViewFrustum) != 0) { // View-frustum culling geometries.AddRange(GetGeometriesViewFrustum(ctxScene)); } else { // All geometries geometries.AddRange(GetGeometries(sceneGeometryState)); } // Bounding volumes if ((ctxScene.Scene.SceneFlags & SceneGraphFlags.BoundingVolumes) != 0) { if ((ctxScene.Scene.SceneFlags & SceneGraphFlags.CullingViewFrustum) != 0) { // View-frustum culling geometries.AddRange(GetBoundingVolumes(ctxScene)); } } return(geometries); }
internal override IEnumerable <SceneObjectBatch> GetGeometries(GraphicsContext ctx, SceneGraphContext ctxScene) { if ((ctxScene.Scene.SceneFlags & SceneGraphFlags.BoundingVolumes) != 0) { GraphicsStateSet boundingVolumeState = ctxScene.GraphicsStateStack.Current.Push(); // Transform TransformStateBase boundingVolumeModel = (TransformStateBase)boundingVolumeState[TransformStateBase.StateSetIndex]; float lightVolumeDepth = 100.0f; float lightVolumeSize = lightVolumeDepth * (float)Math.Tan(Angle.ToRadians(FalloffAngle)); boundingVolumeModel.LocalModelViewProjection.Set(boundingVolumeModel.LocalModelViewProjection.Multiply(LightMatrix)); boundingVolumeModel.LocalModelViewProjection.Translate(0.0f, 0.0f, lightVolumeDepth); boundingVolumeModel.LocalModelViewProjection.Scale(lightVolumeSize, lightVolumeSize, lightVolumeDepth); // Uniform color ShaderUniformState uniformState = new ShaderUniformState("UniformState"); uniformState.SetUniformState("glo_UniformColor", new ColorRGBAF(1.0f, 1.0f, 0.0f, 0.5f)); boundingVolumeState.DefineState(uniformState); // Alpha blending boundingVolumeState.DefineState(BlendState.AlphaBlending); yield return(new SceneObjectBatch( _BoundingVolumeArrays, boundingVolumeState, _BoundingVolumeProgram )); } yield break; }
/// <summary> /// Get all geometries compositing this SceneObjectGeometry, filtering them using view-frustum. /// </summary> /// <param name="currentState"> /// A <see cref="State.GraphicsStateSet"/> that specifies the current graphics state to be merged with /// each returned geometry. /// </param> /// <param name="clippingPlanes"> /// /// </param> /// <param name="viewModel"> /// /// </param> /// <returns> /// It returns a <see cref="IEnumerable{SceneObjectBatch}"/>. /// </returns> private IEnumerable <SceneObjectBatch> GetGeometriesViewFrustum(SceneGraphContext ctxScene) { GraphicsStateSet currentState = ctxScene.GraphicsStateStack.Current.Push(); TransformStateBase sceneGeometryModel = (TransformStateBase)currentState[TransformStateBase.StateSetIndex]; IMatrix4x4 viewModel = sceneGeometryModel.ModelView; if (_GeometryInstances.Count > 0) { foreach (Geometry sceneObjectBatch in _GeometryInstances) { IBoundingVolume instanceVolume = sceneObjectBatch.BoundingVolume ?? _BoundingVolume; if (instanceVolume != null && instanceVolume.IsClipped(ctxScene.ViewFrustumPlanes, viewModel)) { continue; } GraphicsStateSet geometryState; if (sceneObjectBatch.State != null) { geometryState = currentState.Push(); geometryState.Merge(sceneObjectBatch.State); } else { geometryState = currentState; } yield return(new SceneObjectBatch( sceneObjectBatch.VertexArray ?? VertexArray, geometryState, sceneObjectBatch.Program ?? Program )); } } else { if (_BoundingVolume != null && _BoundingVolume.IsClipped(ctxScene.ViewFrustumPlanes, viewModel)) { yield break; } if (VertexArray == null) { yield break; } yield return(new SceneObjectBatch(VertexArray, currentState, Program)); } }
/// <summary> /// Create the corresponding <see cref="LightsState.Light"/> for this object. /// </summary> /// <returns> /// It returns the <see cref="LightsState.Light"/> equivalent to this SceneObjectLight. /// </returns> public override LightsState.Light ToLight(GraphicsContext ctx, SceneGraphContext sceneCtx) { LightsState.LightDirectional light = new LightsState.LightDirectional(); SetLightParameters(sceneCtx, light); TransformStateBase transformState = (TransformStateBase)sceneCtx.GraphicsStateStack.Current[TransformStateBase.StateSetIndex]; IMatrix3x3 normalMatrix = transformState.NormalMatrix; light.Direction = ((Vertex3f)normalMatrix.Multiply((Vertex3f)Direction)).Normalized; light.HalfVector = (Vertex3f.UnitZ + light.Direction).Normalized; return(light); }
private static void SetBoundingVolumeState(BoundingBox boundingVolume, GraphicsStateSet volumeState) { // Set transform state TransformStateBase transformState = (TransformStateBase)volumeState[TransformStateBase.StateSetIndex]; if (transformState == null) { return; } Vertex3f min = boundingVolume.MinPosition, max = boundingVolume.MaxPosition; Vertex3f size = boundingVolume.Size; // Scale model matrix in order to represent the bounding box with the correct size and barycenter transformState.LocalModelViewProjection.Translate((max + min) / 2.0f); transformState.LocalModelViewProjection.Scale(size); }
/// <summary> /// Traverse delegate for collecting geometries to be drawn. /// </summary> /// <param name="ctx"> /// The <see cref="GraphicsContext"/> used for drawing. /// </param> /// <param name="ctxScene"></param> /// <param name="sceneObject"></param> /// <param name="data"></param> /// <returns></returns> private static bool GraphDrawDelegate(GraphicsContext ctx, SceneGraphContext ctxScene, SceneObject sceneObject, object data) { ObjectBatchContext objectBatchContext = (ObjectBatchContext)data; if (sceneObject.ObjectType == SceneObjectGeometry.ClassObjectType) { SceneObjectGeometry sceneGeometry = (SceneObjectGeometry)sceneObject; GraphicsStateSet sceneGeometryState = ctxScene.GraphicsStateStack.Current; TransformStateBase sceneGeometryModel = (TransformStateBase)sceneGeometryState[TransformStateBase.StateSetIndex]; IEnumerable <SceneObjectBatch> geometries; if ((ctxScene.Scene.SceneFlags & SceneGraphFlags.CullingViewFrustum) != 0) { // View-frustum culling geometries = sceneGeometry.GetGeometries(sceneGeometryState, objectBatchContext.ViewFrustumPlanes, sceneGeometryModel.ModelView); } else { // All geometries geometries = sceneGeometry.GetGeometries(sceneGeometryState); } objectBatchContext.Objects.AddRange(geometries); // Bounding volumes if ((ctxScene.Scene.SceneFlags & SceneGraphFlags.BoundingVolumes) != 0) { } } else if (sceneObject.ObjectType == SceneObjectLightZone.ClassObjectType) { SceneObjectLightZone sceneObjectLightZone = (SceneObjectLightZone)sceneObject; // TODO: Push instead of Clear to support stacked zones objectBatchContext.Lights.Clear(); objectBatchContext.LightZone = sceneObjectLightZone; } else if (sceneObject.ObjectType == SceneObjectLight.ClassObjectType) { objectBatchContext.Lights.Add((SceneObjectLight)sceneObject); } return(true); }
internal IEnumerable <SceneObjectBatch> GetBoundingVolumes(SceneGraphContext ctxScene) { GraphicsStateSet currentState = ctxScene.GraphicsStateStack.Current.Push(); TransformStateBase sceneGeometryModel = (TransformStateBase)currentState[TransformStateBase.StateSetIndex]; IMatrix4x4 viewModel = sceneGeometryModel.ModelView; if (_GeometryInstances.Count > 0) { foreach (Geometry sceneObjectBatch in _GeometryInstances) { IBoundingVolume instanceVolume = sceneObjectBatch.BoundingVolume ?? _BoundingVolume; if (instanceVolume != null && instanceVolume.IsClipped(ctxScene.ViewFrustumPlanes, viewModel)) { continue; } GraphicsStateSet volumeState = currentState.Push(); SetBoundingVolumeState(instanceVolume, volumeState); yield return(new SceneObjectBatch( _BoundingVolumeArray, volumeState, _BoundingVolumeProgram )); } } else { if (_BoundingVolume == null || _BoundingVolume.IsClipped(ctxScene.ViewFrustumPlanes, viewModel)) { yield break; } GraphicsStateSet volumeState = currentState.Push(); SetBoundingVolumeState(_BoundingVolume, volumeState); yield return(new SceneObjectBatch(_BoundingVolumeArray, volumeState, _BoundingVolumeProgram)); } }