Пример #1
0
        // Creates the draw jobs for a billboard node.
        private void AddJob(BillboardNode node, bool sortByDistance, bool backToFront)
        {
            var billboard = node.Billboard;

            float distance = 0;

            if (sortByDistance)
            {
                // Determine distance to camera.
                Vector3 cameraToNode = node.PoseWorld.Position - _cameraPose.Position;

                // Planar distance: Project vector onto look direction.
                distance = Vector3.Dot(cameraToNode, _cameraForward);

                // Use linear distance for viewpoint-oriented and world-oriented billboards.
                if (billboard.Orientation.Normal != BillboardNormal.ViewPlaneAligned)
                {
                    distance = cameraToNode.LengthSquared() * Math.Sign(distance);
                }

                if (backToFront)
                {
                    distance = -distance;
                }
            }

            uint textureId;
            var  imageBillboard = billboard as ImageBillboard;

            if (imageBillboard != null)
            {
                // Image billboard
                textureId = GetTextureId(imageBillboard.Texture);
            }
            else
            {
                // Text billboard: Use predefined constant.
                textureId = FontTextureId;
            }

            // Add draw job to list.
            var job = new Job
            {
                SortKey = GetSortKey(distance, 0, textureId),
                Node    = node,
            };

            _jobs.Add(ref job);
        }
Пример #2
0
        private void Draw(BillboardNode node)
        {
            var billboard = (ImageBillboard)node.Billboard;
            var data      = new BillboardArgs
            {
                Position       = node.PoseWorld.Position,
                Normal         = (billboard.Orientation.Normal == BillboardNormal.ViewPlaneAligned) ? _defaultNormal : node.Normal,
                Axis           = node.Axis,
                Orientation    = billboard.Orientation,
                Size           = node.ScaleWorld.Y * billboard.Size, // Assume uniform scale for size.
                Softness       = Numeric.IsNaN(billboard.Softness) ? -1 : billboard.Softness,
                Color          = node.Color * billboard.Color,
                Alpha          = node.Alpha * billboard.Alpha,
                ReferenceAlpha = billboard.AlphaTest,
                AnimationTime  = (Numeric.IsNaN(node.AnimationTime)) ? billboard.AnimationTime : node.AnimationTime,
                BlendMode      = billboard.BlendMode,
            };

            var texture = billboard.Texture ?? _debugTexture;

            _billboardBatch.DrawBillboard(ref data, texture);
        }
Пример #3
0
 public NodeFactory()
 {
     m_builtin["Anchor"]                  = new AnchorNode();
     m_builtin["Appearance"]              = new AppearanceNode();
     m_builtin["Background"]              = new BackgroundNode();
     m_builtin["Billboard"]               = new BillboardNode();
     m_builtin["Box"]                     = new BoxNode();
     m_builtin["Color"]                   = new ColorNode();
     m_builtin["ColorInterpolator"]       = new ColorInterpolatorNode();
     m_builtin["Cone"]                    = new ConeNode();
     m_builtin["Coordinate"]              = new CoordinateNode();
     m_builtin["CoordinateInterpolator"]  = new CoordinateInterpolatorNode();
     m_builtin["Cylinder"]                = new CylinderNode();
     m_builtin["DirectionalLight"]        = new DirectionalLightNode();
     m_builtin["Extrusion"]               = new ExtrusionNode();
     m_builtin["FontStyle"]               = new FontStyleNode();
     m_builtin["Group"]                   = new GroupNode();
     m_builtin["IndexedFaceSet"]          = new IndexedFaceSetNode();
     m_builtin["IndexedLineSet"]          = new IndexedLineSetNode();
     m_builtin["Material"]                = new MaterialNode();
     m_builtin["NavigationInfo"]          = new NavigationInfoNode();
     m_builtin["OrientationInterpolator"] = new OrientationInterpolatorNode();
     m_builtin["Normal"]                  = new NormalNode();
     m_builtin["PixelTexture"]            = new PixelTextureNode();
     m_builtin["PointLight"]              = new PointLightNode();
     m_builtin["PositionInterpolator"]    = new PositionInterpolatorNode();
     m_builtin["ScalarInterpolator"]      = new ScalarInterpolationNode();
     m_builtin["Shape"]                   = new ShapeNode();
     m_builtin["Sphere"]                  = new SphereNode();
     m_builtin["SpotLight"]               = new SpotLightNode();
     m_builtin["Text"]                    = new TextNode();
     m_builtin["TextureCoordinate"]       = new TextureCoordinateNode();
     m_builtin["TimeSensor"]              = new TimeSensorNode();
     m_builtin["TouchSensor"]             = new TouchSensorNode();
     m_builtin["Transform"]               = new TransformNode();
     m_builtin["Viewpoint"]               = new ViewpointNode();
     m_builtin["WorldInfo"]               = new WorldInfoNode();
 }
Пример #4
0
        public BillboardSample(Microsoft.Xna.Framework.Game game)
            : base(game)
        {
            SampleFramework.IsMouseVisible = false;
            var delegateGraphicsScreen = new DelegateGraphicsScreen(GraphicsService)
            {
                RenderCallback = Render,
            };

            GraphicsService.Screens.Insert(0, delegateGraphicsScreen);

            // Add a custom game object which controls the camera.
            _cameraObject = new CameraObject(Services);
            GameObjectService.Objects.Add(_cameraObject);

            // In this example we need three renderers:
            // The MeshRenderer handles MeshNodes.
            _meshRenderer = new MeshRenderer();

            // The BillboardRenderer handles BillboardNodes and ParticleSystemNodes.
            _billboardRenderer = new BillboardRenderer(GraphicsService, 2048);

            // The DebugRenderer is used to draw text.
            var spriteFont = UIContentManager.Load <SpriteFont>("UI Themes/BlendBlue/Default");

            _debugRenderer = new DebugRenderer(GraphicsService, spriteFont);

            // Create a new empty scene.
            _scene = new Scene();

            // Add the camera node to the scene.
            _scene.Children.Add(_cameraObject.CameraNode);

            // Add a few models to the scene.
            var sandbox = ContentManager.Load <ModelNode>("Sandbox/Sandbox").Clone();

            _scene.Children.Add(sandbox);

            // Add some lights to the scene which have the same properties as the lights
            // of BasicEffect.EnableDefaultLighting().
            SceneSample.InitializeDefaultXnaLights(_scene);

            var texture = new PackedTexture(ContentManager.Load <Texture2D>("Billboard/BillboardReference"));

            // ----- View plane-aligned billboards with variations.
            // View plane-aligned billboards are rendered parallel to the screen.
            // The up-axis of the BillboardNode determines the up direction of the
            // billboard.
            var pose0         = new Pose(new Vector3(-9, 1.0f, 1.5f));
            var pose1         = pose0;
            var billboard     = new ImageBillboard(texture);
            var billboardNode = new BillboardNode(billboard);

            billboardNode.Name      = "View plane-aligned\nVarying color\nVarying alpha";
            billboardNode.PoseWorld = pose1;
            _scene.Children.Add(billboardNode);

            pose1.Position.Z       -= 1;
            billboardNode           = new BillboardNode(billboard);
            billboardNode.PoseWorld = pose1;
            billboardNode.Color     = new Vector3(1, 0, 0);
            billboardNode.Alpha     = 0.9f;
            _scene.Children.Add(billboardNode);

            pose1.Position.Z       -= 1;
            billboardNode           = new BillboardNode(billboard);
            billboardNode.PoseWorld = pose1;
            billboardNode.Color     = new Vector3(0, 1, 0);
            billboardNode.Alpha     = 0.7f;
            _scene.Children.Add(billboardNode);

            pose1.Position.Z       -= 1;
            billboardNode           = new BillboardNode(billboard);
            billboardNode.PoseWorld = pose1;
            billboardNode.Color     = new Vector3(0, 0, 1);
            billboardNode.Alpha     = 0.3f;
            _scene.Children.Add(billboardNode);

            // ----- View plane-aligned billboards with different blend modes
            // blend mode = 0 ... additive blend
            // blend mode = 1 ... alpha blend
            pose0.Position.X       += 2;
            pose1                   = pose0;
            billboard               = new ImageBillboard(texture);
            billboard.BlendMode     = 0.0f;
            billboardNode           = new BillboardNode(billboard);
            billboardNode.Name      = "View plane-aligned\nVarying blend mode";
            billboardNode.PoseWorld = pose1;
            _scene.Children.Add(billboardNode);

            pose1.Position.Z       -= 1;
            billboard               = new ImageBillboard(texture);
            billboard.BlendMode     = 0.333f;
            billboardNode           = new BillboardNode(billboard);
            billboardNode.PoseWorld = pose1;
            _scene.Children.Add(billboardNode);

            pose1.Position.Z       -= 1;
            billboard               = new ImageBillboard(texture);
            billboard.BlendMode     = 0.667f;
            billboardNode           = new BillboardNode(billboard);
            billboardNode.PoseWorld = pose1;
            _scene.Children.Add(billboardNode);

            pose1.Position.Z       -= 1;
            billboard               = new ImageBillboard(texture);
            billboard.BlendMode     = 1.0f;
            billboardNode           = new BillboardNode(billboard);
            billboardNode.PoseWorld = pose1;
            _scene.Children.Add(billboardNode);

            // ----- View plane-aligned billboards with alpha test
            pose0.Position.X       += 2;
            pose1                   = pose0;
            billboard               = new ImageBillboard(texture);
            billboard.AlphaTest     = 0.9f;
            billboardNode           = new BillboardNode(billboard);
            billboardNode.Name      = "View plane-aligned\nVarying reference alpha";
            billboardNode.PoseWorld = pose1;
            _scene.Children.Add(billboardNode);

            pose1.Position.Z       -= 1;
            billboard               = new ImageBillboard(texture);
            billboard.AlphaTest     = 0.667f;
            billboardNode           = new BillboardNode(billboard);
            billboardNode.PoseWorld = pose1;
            _scene.Children.Add(billboardNode);

            pose1.Position.Z       -= 1;
            billboard               = new ImageBillboard(texture);
            billboard.AlphaTest     = 0.333f;
            billboardNode           = new BillboardNode(billboard);
            billboardNode.PoseWorld = pose1;
            _scene.Children.Add(billboardNode);

            pose1.Position.Z       -= 1;
            billboard               = new ImageBillboard(texture);
            billboard.AlphaTest     = 0.0f;
            billboardNode           = new BillboardNode(billboard);
            billboardNode.PoseWorld = pose1;
            _scene.Children.Add(billboardNode);

            // ----- View plane-aligned billboards with different scale and rotation
            pose0.Position.X        += 2;
            pose1                    = pose0;
            billboard                = new ImageBillboard(texture);
            billboard.Orientation    = BillboardOrientation.ViewPlaneAligned;
            billboardNode            = new BillboardNode(billboard);
            billboardNode.Name       = "View plane-aligned\nVarying scale\nVarying rotation";
            billboardNode.PoseWorld  = pose1;
            billboardNode.ScaleLocal = new Vector3(0.4f);
            _scene.Children.Add(billboardNode);

            pose1.Position.Z        -= 1;
            billboardNode            = billboardNode.Clone();
            billboardNode.Name       = null;
            billboardNode.PoseWorld  = pose1 * new Pose(Matrix.CreateRotationZ(MathHelper.ToRadians(-15)));
            billboardNode.ScaleLocal = new Vector3(0.6f);
            _scene.Children.Add(billboardNode);

            pose1.Position.Z        -= 1;
            billboardNode            = billboardNode.Clone();
            billboardNode.Name       = null;
            billboardNode.PoseWorld  = pose1 * new Pose(Matrix.CreateRotationZ(MathHelper.ToRadians(-30)));
            billboardNode.ScaleLocal = new Vector3(0.8f);
            _scene.Children.Add(billboardNode);

            pose1.Position.Z        -= 1;
            billboardNode            = billboardNode.Clone();
            billboardNode.Name       = null;
            billboardNode.PoseWorld  = pose1 * new Pose(Matrix.CreateRotationZ(MathHelper.ToRadians(-45)));
            billboardNode.ScaleLocal = new Vector3(1.0f);
            _scene.Children.Add(billboardNode);

            // ----- Viewpoint-oriented billboards
            // Viewpoint-orientated billboards always face the player. (The face normal
            // points directly to the camera.)
            pose0.Position.X       += 2;
            pose1                   = pose0;
            billboard               = new ImageBillboard(texture);
            billboard.Orientation   = BillboardOrientation.ViewpointOriented;
            billboardNode           = new BillboardNode(billboard);
            billboardNode.Name      = "Viewpoint-oriented";
            billboardNode.PoseWorld = pose1;
            _scene.Children.Add(billboardNode);

            pose1.Position.Z       -= 1;
            billboardNode           = new BillboardNode(billboard);
            billboardNode.PoseWorld = pose1;
            _scene.Children.Add(billboardNode);

            pose1.Position.Z       -= 1;
            billboardNode           = new BillboardNode(billboard);
            billboardNode.PoseWorld = pose1;
            _scene.Children.Add(billboardNode);

            pose1.Position.Z       -= 1;
            billboardNode           = new BillboardNode(billboard);
            billboardNode.PoseWorld = pose1;
            _scene.Children.Add(billboardNode);

            // ----- Screen-aligned billboards
            // View plane-aligned billboards and screen-aligned billboards are similar. The
            // billboards are rendered parallel to the screen. The orientation can be changed
            // by rotating the BillboardNode. The difference is that the orientation of view
            // plane-aligned billboards is relative to world space and the orientation of
            // screen-aligned billboards is relative to view space.
            // Screen-aligned billboards are, for example, used for text label.
            pose0.Position.X       += 2;
            pose1                   = pose0;
            billboard               = new ImageBillboard(texture);
            billboard.Orientation   = BillboardOrientation.ScreenAligned;
            billboardNode           = new BillboardNode(billboard);
            billboardNode.Name      = "Screen-aligned";
            billboardNode.PoseWorld = pose1;
            _scene.Children.Add(billboardNode);

            pose1.Position.Z       -= 1;
            billboardNode           = new BillboardNode(billboard);
            billboardNode.PoseWorld = pose1;
            _scene.Children.Add(billboardNode);

            pose1.Position.Z       -= 1;
            billboardNode           = new BillboardNode(billboard);
            billboardNode.PoseWorld = pose1;
            _scene.Children.Add(billboardNode);

            pose1.Position.Z       -= 1;
            billboardNode           = new BillboardNode(billboard);
            billboardNode.PoseWorld = pose1;
            _scene.Children.Add(billboardNode);

            // ----- Axial, view plane-aligned billboards
            pose0.Position.X       += 2;
            pose1                   = pose0;
            billboard               = new ImageBillboard(texture);
            billboard.Orientation   = BillboardOrientation.AxialViewPlaneAligned;
            billboardNode           = new BillboardNode(billboard);
            billboardNode.Name      = "Axial, view plane-aligned";
            billboardNode.PoseWorld = pose1;
            _scene.Children.Add(billboardNode);

            pose1.Position.Z       -= 1;
            billboardNode           = billboardNode.Clone();
            billboardNode.Name      = null;
            billboardNode.PoseWorld = pose1;
            _scene.Children.Add(billboardNode);

            pose1.Position.Z       -= 1;
            billboardNode           = new BillboardNode(billboard);
            billboardNode.PoseWorld = pose1;
            _scene.Children.Add(billboardNode);

            pose1.Position.Z       -= 1;
            billboardNode           = new BillboardNode(billboard);
            billboardNode.PoseWorld = pose1;
            _scene.Children.Add(billboardNode);

            // ----- Axial, viewpoint-oriented billboards
            pose0.Position.X       += 2;
            pose1                   = pose0;
            billboard               = new ImageBillboard(texture);
            billboard.Orientation   = BillboardOrientation.AxialViewpointOriented;
            billboardNode           = new BillboardNode(billboard);
            billboardNode.Name      = "Axial, viewpoint-oriented";
            billboardNode.PoseWorld = pose1;
            _scene.Children.Add(billboardNode);

            pose1.Position.Z       -= 1;
            billboardNode           = new BillboardNode(billboard);
            billboardNode.PoseWorld = pose1;
            _scene.Children.Add(billboardNode);

            pose1.Position.Z       -= 1;
            billboardNode           = new BillboardNode(billboard);
            billboardNode.PoseWorld = pose1;
            _scene.Children.Add(billboardNode);

            pose1.Position.Z       -= 1;
            billboardNode           = new BillboardNode(billboard);
            billboardNode.PoseWorld = pose1;
            _scene.Children.Add(billboardNode);

            // ----- World-oriented billboards
            // World-oriented billboards have a fixed orientation in world space. The
            // orientation is determine by the BillboardNode.
            pose0.Position.X       += 2;
            pose1                   = pose0;
            pose1.Orientation      *= Matrix.CreateRotationY(0.2f);
            billboard               = new ImageBillboard(texture);
            billboard.Orientation   = BillboardOrientation.WorldOriented;
            billboardNode           = new BillboardNode(billboard);
            billboardNode.Name      = "World-oriented";
            billboardNode.PoseWorld = pose1;
            _scene.Children.Add(billboardNode);

            pose1.Position.Z       -= 1;
            pose1.Orientation      *= Matrix.CreateRotationY(0.2f);
            billboardNode           = new BillboardNode(billboard);
            billboardNode.PoseWorld = pose1 * new Pose(Matrix.CreateRotationZ(MathHelper.ToRadians(15)));
            _scene.Children.Add(billboardNode);

            pose1.Position.Z       -= 1;
            pose1.Orientation      *= Matrix.CreateRotationY(0.2f);
            billboardNode           = new BillboardNode(billboard);
            billboardNode.PoseWorld = pose1 * new Pose(Matrix.CreateRotationZ(MathHelper.ToRadians(30)));
            _scene.Children.Add(billboardNode);

            pose1.Position.Z       -= 1;
            pose1.Orientation      *= Matrix.CreateRotationY(0.2f);
            billboardNode           = new BillboardNode(billboard);
            billboardNode.PoseWorld = pose1 * new Pose(Matrix.CreateRotationZ(MathHelper.ToRadians(45)));
            _scene.Children.Add(billboardNode);

            // ----- Animated billboards
            // DigitalRune Graphics supports "texture atlases". I.e. textures can be packed
            // together into a single, larger texture file. A PackedTexture can describe a
            // single texture packed into a texture atlas or a tile set packed into a
            // texture atlas. In this example the "beeWingFlap" is a set of three tiles.
            // Tile sets can be used for sprite animations. (The animation is set below in
            // Update().)
            pose0.Position.X       += 2;
            pose1                   = pose0;
            texture                 = new PackedTexture("Bee", ContentManager.Load <Texture2D>("Particles/beeWingFlap"), Vector2F.Zero, Vector2F.One, 3, 1);
            _animatedBillboard      = new ImageBillboard(texture);
            billboardNode           = new BillboardNode(_animatedBillboard);
            billboardNode.Name      = "Animated billboards";
            billboardNode.PoseWorld = pose1;
            _scene.Children.Add(billboardNode);

            pose1.Position.Z       -= 1;
            billboardNode           = new BillboardNode(_animatedBillboard);
            billboardNode.PoseWorld = pose1;
            _scene.Children.Add(billboardNode);

            pose1.Position.Z       -= 1;
            billboardNode           = new BillboardNode(_animatedBillboard);
            billboardNode.PoseWorld = pose1;
            _scene.Children.Add(billboardNode);

            // Use DebugRenderer to draw node names above billboard nodes.
            foreach (var node in _scene.GetDescendants().OfType <BillboardNode>())
            {
                _debugRenderer.DrawText(node.Name, node.PoseWorld.Position + new Vector3(0, 1, 0), new Vector2F(0.5f), Color.Yellow, false);
            }
        }