// 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); }
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); }
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(); }
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); } }