Ejemplo n.º 1
0
        /// <summary>
        /// Sets the opacity (alpha) of a scene node - see remarks.
        /// </summary>
        /// <param name="node">The scene node.</param>
        /// <param name="alpha">The alpha value.</param>
        /// <remarks>
        /// This method can be called for all types of <see cref="SceneNode"/>s. If the node is a
        /// <see cref="MeshNode"/>, the method sets the
        /// <see cref="DefaultEffectParameterSemantics.InstanceAlpha"/> effect parameter bindings in
        /// the material instances. Currently, this method does nothing for all other types of scene
        /// nodes.
        /// </remarks>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="node"/> is <see langword="null"/>.
        /// </exception>
        public static void SetInstanceAlpha(this SceneNode node, float alpha)
        {
            if (node == null)
            {
                throw new ArgumentNullException("node");
            }

            // ReSharper disable CompareOfFloatsByEqualityOperator
            if (alpha == 1)
            {
                // Abort if node's alpha is already equal to 1.
                if (!node.GetFlag(SceneNodeFlags.IsAlphaSet))
                {
                    return;
                }

                // Remember that node's alpha is reset to 1.
                node.ClearFlag(SceneNodeFlags.IsAlphaSet);
            }
            else
            {
                // Remember that node's alpha is not 1.
                node.SetFlag(SceneNodeFlags.IsAlphaSet);
            }
            // ReSharper restore CompareOfFloatsByEqualityOperator

            // The only node which sets the HasAlpha flag is a MeshNode!
            // Cast to MeshNode and update the InstanceAlpha parameter bindings.
            // See also MeshNode.SetHasAlpha().
            var meshNode = node as MeshNode;

            if (meshNode != null)
            {
                foreach (var materialInstance in meshNode.MaterialInstances)
                {
                    foreach (var effectBinding in materialInstance.EffectBindings)
                    {
                        foreach (var parameterBinding in effectBinding.ParameterBindings)
                        {
                            if (ReferenceEquals(parameterBinding.Description.Semantic, DefaultEffectParameterSemantics.InstanceAlpha))
                            {
                                var constParameterBinding = parameterBinding as ConstParameterBinding <float>;
                                if (constParameterBinding != null)
                                {
                                    constParameterBinding.Value = alpha;
                                }

                                break;
                            }
                        }
                    }
                }
            }
        }
Ejemplo n.º 2
0
        /// <inheritdoc/>
        public T Query <T>(SceneNode referenceNode, RenderContext context) where T : class, ISceneQuery, new()
        {
            if (referenceNode == null)
            {
                throw new ArgumentNullException("referenceNode");
            }

            // Use proxy node instead of specified node, if set.
            while (referenceNode.Proxy != null)
            {
                referenceNode = referenceNode.Proxy;
            }

            // Check if the node was modified since Scene.Update(). This can happen, for
            // example, if a CameraNode is rotated to capture 6 sides of a cube map.
            if (referenceNode.GetFlag(SceneNodeFlags.IsDirtyScene))
            {
                // Reset all queries that use this node.
                int numberOfQueries = _queries.Count;
                for (int i = 0; i < numberOfQueries; i++)
                {
                    if (_queries[i].ReferenceNode == referenceNode)
                    {
                        _queries[i].Reset();
                    }
                }

                referenceNode.ClearFlag(SceneNodeFlags.IsDirtyScene);
            }

            try
            {
                // ----- Get query of type T.
                T   query           = null;
                int numberOfQueries = _queries.Count;
                for (int i = 0; i < numberOfQueries; i++)
                {
                    query = _queries[i] as T;
                    if (query != null)
                    {
                        break;
                    }
                }

                if (query != null)
                {
                    // Query exists.
                    // Return cached result if the reference node is the same.
                    if (query.ReferenceNode == referenceNode)
                    {
                        return(query);
                    }
                }
                else
                {
                    // Create new query.
                    query = new T();
                    _queries.Add(query);
                }

                if (referenceNode.Shape is InfiniteShape)
                {
                    // ----- Infinite shape queries.
                    // Return all scene nodes.
                    GetSceneNodes(this, referenceNode, _filter, _tempNodes);
                    query.Set(referenceNode, _tempNodes, context);
                    return(query);
                }

                // Add infinite nodes to temporary list.
                foreach (var node in _infiniteNodes)
                {
                    if (node.ActualIsEnabled && _filter.Filter(new Pair <SceneNode>(referenceNode, node)))
                    {
                        _tempNodes.Add(node);
                    }
                }

                var cameraNode = referenceNode as CameraNode;
                if (cameraNode != null)
                {
                    // ----- Camera frustum queries.
                    // Extract frustum planes.
                    Matrix44F viewProjection = cameraNode.Camera.Projection * cameraNode.View;
                    GeometryHelper.ExtractPlanes(viewProjection, _tempPlanes, false);

                    // Use broad phase to do frustum culling.
                    foreach (var collisionObject in ((DualPartition <CollisionObject>)_collisionDomain.BroadPhase).GetOverlaps(_tempPlanes))
                    {
                        // ISupportFrustumCulling.GetOverlaps() does not apply filtering.
                        // --> Manually check if collision object is enabled.
                        if (collisionObject.Enabled)
                        {
                            //if (collisionObject.GeometricObject.Shape is PlaneShape
                            //    && !HaveAabbPlaneContact(referenceNode, collisionObject))
                            //  continue;

                            var sceneNode = collisionObject.GeometricObject as SceneNode;
                            if (sceneNode != null && _filter.Filter(new Pair <SceneNode>(referenceNode, sceneNode)))
                            {
                                _tempNodes.Add(sceneNode);
                            }
                        }
                    }
                }
                else
                {
                    // ----- Normal object queries.
                    var collisionObject = GetCollisionObject(referenceNode, false);
                    foreach (var contactSet in _collisionDomain.ContactSets.GetContacts(collisionObject))
                    {
                        SceneNode sceneNode;
                        if (contactSet.ObjectA == collisionObject)
                        {
                            sceneNode = contactSet.ObjectB.GeometricObject as SceneNode;
                        }
                        else
                        {
                            sceneNode = contactSet.ObjectA.GeometricObject as SceneNode;
                        }

                        Debug.Assert(sceneNode != null);
                        _tempNodes.Add(sceneNode);
                    }
                }

                query.Set(referenceNode, _tempNodes, context);
                return(query);
            }
            finally
            {
                _tempPlanes.Clear();
                _tempNodes.Clear();
            }
        }