[2 days left] What’s wrong with your cloud strategy? Learn why multicloud solutions matter with Nimble Storage.Register Now


draw text in 3d world (pref c# other ok)

Posted on 2006-10-21
Medium Priority
Last Modified: 2013-12-08
I would like to know how to draw text in a 3d world using directX. I use c# so i would like samples in c# code but if not possible other languages will be ok as long as i can translate easily.
I dont wont any 2d drawing samples! I´ve already seen them, but i cant find any 3d samples?

For example, i want to have a spinning cube and on every side i want to show the seconds since the program started or just the time right now. As long as its text thats changing.

In the long run i will be able to change the text fast so creating an image eveytime doesnt seem fast enough..

Is there an easy way to use drawtext using a position as x,y,z ?

You know what i mean :)

Question by:lidingo
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
  • 2

Accepted Solution

OutsideTheBox earned 1500 total points
ID: 17783703
Sorry, I feel your pain,

DrawText only draws on to the window, not the objects in the window(like your cube). DrawText items have only an X,Y coord . They are the coords of the window client area, not 3d coords of your world.

If you have a cube that is spinning, one way to get the seconds (or time) on to each side of it is to create 10 textures (one for each number, 0 thru 9) & apply whichever of them you need to the sides in the right position and change them out as needed between frames. You may need 6 textures per face (2 for hours, 2 for min, two for sec) so the challenge would be in positioning them correctly. They can be swapped out between frames as necessary as time increments.

Applying textures to your cube is very similar to applying textures to a skybox. This is a common enough exercise that many tutorials show how it is done and give you the code. My favorite for C# & MDX is http://www.thehazymind.com/3DEngine.htm  Scroll down to see the first four or five lessons.

The difference between the skybox in the tutorial & your project is that your normals face outwards and you would need up to 6 textures per face instead of one. Also, your camera is outside the cube instead of inside.


Author Comment

ID: 17789240

The problem is i want to have several numbers and i want them to change from the values sent to them by a socket and they will sometimes change very fast. It doesnt seem like a good way to have a texture for every digit and then change them.

But if thats the only solution there is, its not much to do...

I will leave this for another day or two and is noone can come up with a better solution for me i will give you the points.

Thanks for your answer!


Author Comment

ID: 17794262
Since it seems like this is the only solution i will give you the points.

Thanks for the help.


Expert Comment

ID: 17795572
Here is an example of doing this in a slightly different way. It eliminates the need for so many textures. This method only needs one. It also uses DrawText to update a texture then applies that single texture to the cube.

It is fromTom Miller's book on Managed DirectX. He has a chapter on Rendering to surfaces and another on 2d & 3d text. http://www.amazon.com/Managed-DirectX-Kick-Start-Programming/dp/0672325969/sr=1-1/qid=1161696045/ref=sr_1_1/104-8413604-7171909?ie=UTF8&s=books

I combined some sample code from each chapter and threw in a cube & an incrementer and here is the code. It assumes you have a mesh called "cubeExample1a.x" 2 folders up from the debug folder. Also, don't forget to add all the appropriate references (the directX ones). Let me know if you need any explainations of the code.

Although it may sound slow to you it does display faster than you are able to read it.

If you have trouble running it, I can upload the project file to ee-stuff.

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;

namespace Chapter10Code
      /// <summary>
      /// Summary description for Form1.
      /// </summary>
      public class Form1 : System.Windows.Forms.Form
        private Device device = null;
        private Mesh mesh = null;
        private Material[] meshMaterials;
        private Texture[] meshTextures;

        private Texture renderTexture = null;
        private Surface renderSurface = null;
        private RenderToSurface rts = null;
        private const int RenderSurfaceSize = 128;
        System.Drawing.Font myFont = new System.Drawing.Font("Arial", 36.0f, FontStyle.Bold);
        private Microsoft.DirectX.Direct3D.Font my3DFont = null;
        private string TexText;
        private int increment = 1;
        private int value = 0;

        /// <summary>
            /// Required designer variable.
            /// </summary>
            private System.ComponentModel.Container components = null;
        private float angle = 0.0f;

            public Form1()
                  // Required for Windows Form Designer support

            this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.Opaque, true);

        /// <summary>
        /// We will initialize our graphics device here
        /// </summary>
        public void InitializeGraphics()
            // Set our presentation parameters
            PresentParameters presentParams = new PresentParameters();

            presentParams.Windowed = true;
            presentParams.SwapEffect = SwapEffect.Discard;
            presentParams.AutoDepthStencilFormat = DepthFormat.D16;
            presentParams.EnableAutoDepthStencil = true;

            // Create our device
            device = new Device(0, DeviceType.Hardware, this, CreateFlags.SoftwareVertexProcessing, presentParams);
            device.DeviceReset +=new EventHandler(OnDeviceReset);
            OnDeviceReset(device, null);
            my3DFont = new Microsoft.DirectX.Direct3D.Font(device,myFont);

            // Load our mesh

        private void OnDeviceReset(object sender, EventArgs e)
            Device dev = (Device)sender;

            if (dev.DeviceCaps.VertexProcessingCaps.SupportsDirectionalLights)
                uint maxLights = (uint)dev.DeviceCaps.MaxActiveLights;
                if (maxLights > 0)
                    dev.Lights[0].Type = LightType.Directional;
                    dev.Lights[0].Diffuse = Color.White;
                    dev.Lights[0].Direction = new Vector3(0, -1, -1);
                    dev.Lights[0].Enabled = true;

                if (maxLights > 1)
                    dev.Lights[1].Type = LightType.Directional;
                    dev.Lights[1].Diffuse = Color.White;
                    dev.Lights[1].Direction = new Vector3(0, -1, 1);
                    dev.Lights[1].Enabled = true;


            rts = new RenderToSurface(dev, RenderSurfaceSize, RenderSurfaceSize,
                Format.X8R8G8B8, true, DepthFormat.D16);

            renderTexture = new Texture(dev, RenderSurfaceSize, RenderSurfaceSize, 1,
                Usage.RenderTarget, Format.X8R8G8B8, Pool.Default);

            renderSurface = renderTexture.GetSurfaceLevel(0);

        private void LoadMesh(string file)
            ExtendedMaterial[] mtrl;

            // Load our mesh
            mesh = Mesh.FromFile(file, MeshFlags.Managed, device, out mtrl);

            // If we have any materials, store them
            if ((mtrl != null) && (mtrl.Length > 0))
                meshMaterials = new Material[mtrl.Length];
                meshTextures = new Texture[mtrl.Length];

                // Store each material and texture
                for (int i = 0; i < mtrl.Length; i++)
                    meshMaterials[i] = mtrl[i].Material3D;
                    if ((mtrl[i].TextureFilename != null) && (mtrl[i].TextureFilename != string.Empty))
                        // We have a texture, try to load it
                        meshTextures[i] = TextureLoader.FromFile(device, @"..\..\" + mtrl[i].TextureFilename);

        private void SetupCamera()
            device.Transform.Projection = Matrix.PerspectiveFovLH((float)Math.PI / 4, this.Width / this.Height, 1.0f, 10000.0f);
            device.Transform.View = Matrix.LookAtLH(new Vector3(0,0, 580.0f), new Vector3(), new Vector3(0,1,0));

        private void RenderIntoSurface()
            // Render to this surface
            Viewport view = new Viewport();
            view.Width = RenderSurfaceSize;
            view.Height = RenderSurfaceSize;
            view.MaxZ = 1.0f;

            rts.BeginScene(renderSurface, view);

            device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.DarkBlue, 1.0f, 0);
            device.Transform.Projection = Matrix.PerspectiveFovLH((float)Math.PI / 4,
                this.Width / this.Height, 1.0f, 10000.0f);

            device.Transform.View = Matrix.LookAtLH(new Vector3(0,0, -580.0f),
                new Vector3(), new Vector3(0, 1,0));

           // DrawMesh(angle / (float)Math.PI, angle / (float)Math.PI * 2.0f,
             //   angle / (float)Math.PI / 4.0f, 0.0f, 0.0f, 0.0f);

           // DrawMesh(angle / (float)Math.PI, angle / (float)Math.PI / 2.0f,
             //   angle / (float)Math.PI * 4.0f, 150.0f, -100.0f, 175.0f);
            value = value + increment;
            TexText = Convert.ToString(value);

            if (value > 990) { value = 0; }

            my3DFont.DrawText(null, TexText, 5, 5, Color.Red);


        protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)

            device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.CornflowerBlue, 1.0f, 0);



            // Draw our Mesh
            DrawMesh(angle / (float)Math.PI, angle / (float)Math.PI * 2.0f,
                angle / (float)Math.PI / 4.0f, 0.0f, 0.0f, 0.0f);

            using (Sprite s = new Sprite(device))
                s.Draw(renderTexture, new Rectangle(0, 0, RenderSurfaceSize, RenderSurfaceSize),
                    new Vector3(0, 0, 0), new Vector3(0, 0, 1.0f), Color.White);




        private void DrawMesh(float yaw, float pitch, float roll, float x, float y, float z)
            angle += 0.01f;

            device.Transform.World = Matrix.RotationYawPitchRoll(yaw, pitch, roll) * Matrix.Translation(x, y, z);
            for (int i = 0; i < meshMaterials.Length; i++)
                device.Material = meshMaterials[i];
                device.SetTexture(0, renderTexture);

        /// <summary>
            /// Clean up any resources being used.
            /// </summary>
            protected override void Dispose( bool disposing )
                  if( disposing )
                        if (components != null)
                  base.Dispose( disposing );

            #region Windows Form Designer generated code
            /// <summary>
            /// Required method for Designer support - do not modify
            /// the contents of this method with the code editor.
            /// </summary>
            private void InitializeComponent()
                  this.components = new System.ComponentModel.Container();
                  this.Size = new Size(800,600);
                  this.Text = "Form1";

            /// <summary>
            /// The main entry point for the application.
            /// </summary>
        static void Main()
            using (Form1 frm = new Form1())
                // Show our form and initialize our graphics engine


Author Comment

ID: 17829242
Hi again.
Thanks a lot for your help!

The problem still is that its using drawtext in 2d.
In the end i want the cube to be able to spin and the number to keep incrementing during the spin.
Lets say i want to show two sides of the cube and want to see both sides with there own incrementing numbers.

Starting to think i have to make my own drawtext function :(
If you should think of anything i would really appreciate it!
Thanks for your help!


Featured Post

Learn how to optimize MySQL for your business need

With the increasing importance of apps & networks in both business & personal interconnections, perfor. has become one of the key metrics of successful communication. This ebook is a hands-on business-case-driven guide to understanding MySQL query parameter tuning & database perf

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Artificial Intelligence comes in many forms, and for game developers, Path-Finding is an important ability for making an NPC (Non-Playable Character) maneuver through terrain.  A* is a particularly easy way to approach it.  I’ll start with the algor…
Performance in games development is paramount: every microsecond counts to be able to do everything in less than 33ms (aiming at 16ms). C# foreach statement is one of the worst performance killers, and here I explain why.
Video by: ITPro.TV
In this episode Don builds upon the troubleshooting techniques by demonstrating how to properly monitor a vSphere deployment to detect problems before they occur. He begins the show using tools found within the vSphere suite as ends the show demonst…
Want to learn how to record your desktop screen without having to use an outside camera. Click on this video and learn how to use the cool google extension called "Screencastify"! Step 1: Open a new google tab Step 2: Go to the left hand upper corn…

649 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question