.NET ISceneNode.AddChild() makes the child disappear

You discovered a bug in the engine, and you are sure that it is not a problem of your code? Just post it in here. Please read the bug posting guidelines first.
Post Reply
nicthu
Posts: 4
Joined: Sat Nov 19, 2005 6:48 am

.NET ISceneNode.AddChild() makes the child disappear

Post by nicthu »

Hosting Irrlicht in a Windows .NET Form, using 3rd person camera.

I create 2 TestSceneNodes.
When I set one as the child of the other, it disappears.

Code follows:

Code: Select all

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using Irrlicht; // compiler error here? Look at the next comment
using Irrlicht.Video;
using Irrlicht.Core;
using Irrlicht.Scene;
//using Peake;

// PROBLEMS with this source? 
// Some solutions wich might help:
//
// - If your compiler complains that 'Irrlicht' cannot be found,
//  add the Irrlicht.NET.dll file (in bin\visualStudio) as Reference
//  in the solution browser.
// 
// - It compiles, but your program throws an exception like this:
//  "An unhandled exception of type 'System.IO.FileNotFoundException' occurred in Unknown Module.
//  Additional information: File or assembly name Irrlicht.NET, or one of its dependencies,
//  was not found."
//  Solution: You are missing the file Irrlicht.DLL. Copy it where Visual studio can find it.
//  For example where this program is.

namespace IrrlichtTest1
{
    /// <summary>
    /// Summary description for Form1.
    /// </summary>
    public class Form1 : System.Windows.Forms.Form
    {
        private System.Windows.Forms.Button buttonRotateLeft;
        private System.Windows.Forms.Button buttonRotateRight;
        private System.Windows.Forms.Button buttonRotateUp;
        private System.Windows.Forms.Button buttonRotateDown;
        private System.Windows.Forms.Button buttonRotateHome;
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.Container components = null;

        public Form1()
        {
            //
            // Required for Windows Form Designer support
            //
            InitializeComponent();

            //
            // TODO: Add any constructor code after InitializeComponent call
            //
        }

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                this.camera = null;
                this.container = null;
                this.device.CloseDevice();
                this.device.__dtor();
                this.device = null;

                if (components != null)
                {
                    components.Dispose();
                }
            }
            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.buttonRotateLeft = new System.Windows.Forms.Button();
            this.buttonRotateRight = new System.Windows.Forms.Button();
            this.buttonRotateUp = new System.Windows.Forms.Button();
            this.buttonRotateDown = new System.Windows.Forms.Button();
            this.buttonRotateHome = new System.Windows.Forms.Button();
            this.SuspendLayout();
            // 
            // buttonRotateLeft
            // 
            this.buttonRotateLeft.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
            this.buttonRotateLeft.Location = new System.Drawing.Point(622, 558);
            this.buttonRotateLeft.Name = "buttonRotateLeft";
            this.buttonRotateLeft.Size = new System.Drawing.Size(27, 21);
            this.buttonRotateLeft.TabIndex = 0;
            this.buttonRotateLeft.Text = "<";
            this.buttonRotateLeft.MouseDown += new System.Windows.Forms.MouseEventHandler(this.buttonRotateLeft_MouseDown);
            this.buttonRotateLeft.MouseUp += new System.Windows.Forms.MouseEventHandler(this.buttonRotateLeft_MouseUp);
            // 
            // buttonRotateRight
            // 
            this.buttonRotateRight.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
            this.buttonRotateRight.Location = new System.Drawing.Point(662, 558);
            this.buttonRotateRight.Name = "buttonRotateRight";
            this.buttonRotateRight.Size = new System.Drawing.Size(27, 21);
            this.buttonRotateRight.TabIndex = 1;
            this.buttonRotateRight.Text = ">";
            this.buttonRotateRight.MouseDown += new System.Windows.Forms.MouseEventHandler(this.buttonRotateRight_MouseDown);
            this.buttonRotateRight.MouseUp += new System.Windows.Forms.MouseEventHandler(this.buttonRotateRight_MouseUp);
            // 
            // buttonRotateUp
            // 
            this.buttonRotateUp.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
            this.buttonRotateUp.Font = new System.Drawing.Font("Microsoft Sans Serif", 10.2F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.buttonRotateUp.Location = new System.Drawing.Point(711, 485);
            this.buttonRotateUp.Name = "buttonRotateUp";
            this.buttonRotateUp.Size = new System.Drawing.Size(27, 21);
            this.buttonRotateUp.TabIndex = 2;
            this.buttonRotateUp.Text = "^";
            this.buttonRotateUp.TextAlign = System.Drawing.ContentAlignment.TopCenter;
            this.buttonRotateUp.MouseDown += new System.Windows.Forms.MouseEventHandler(this.buttonRotateUp_MouseDown);
            this.buttonRotateUp.MouseUp += new System.Windows.Forms.MouseEventHandler(this.buttonRotateUp_MouseUp);
            // 
            // buttonRotateDown
            // 
            this.buttonRotateDown.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
            this.buttonRotateDown.Font = new System.Drawing.Font("Microsoft Sans Serif", 7.8F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.buttonRotateDown.Location = new System.Drawing.Point(711, 521);
            this.buttonRotateDown.Name = "buttonRotateDown";
            this.buttonRotateDown.Size = new System.Drawing.Size(27, 21);
            this.buttonRotateDown.TabIndex = 3;
            this.buttonRotateDown.Text = "v";
            this.buttonRotateDown.MouseDown += new System.Windows.Forms.MouseEventHandler(this.buttonRotateDown_MouseDown);
            this.buttonRotateDown.MouseUp += new System.Windows.Forms.MouseEventHandler(this.buttonRotateDown_MouseUp);
            // 
            // buttonRotateHome
            // 
            this.buttonRotateHome.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
            this.buttonRotateHome.Location = new System.Drawing.Point(702, 558);
            this.buttonRotateHome.Name = "buttonRotateHome";
            this.buttonRotateHome.Size = new System.Drawing.Size(36, 21);
            this.buttonRotateHome.TabIndex = 4;
            this.buttonRotateHome.Text = "0,0";
            this.buttonRotateHome.Click += new System.EventHandler(this.buttonRotateHome_Click);
            // 
            // Form1
            // 
            this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
            this.ClientSize = new System.Drawing.Size(762, 604);
            this.Controls.Add(this.buttonRotateHome);
            this.Controls.Add(this.buttonRotateDown);
            this.Controls.Add(this.buttonRotateUp);
            this.Controls.Add(this.buttonRotateRight);
            this.Controls.Add(this.buttonRotateLeft);
            this.Name = "Form1";
            this.Text = "Form1";
            this.Paint += new System.Windows.Forms.PaintEventHandler(this.Form1_Paint);
            this.MouseClick += new System.Windows.Forms.MouseEventHandler(this.Form1_MouseClick);
            this.Closed += new System.EventHandler(this.Form1_Closed);
            this.Resize += new System.EventHandler(this.Form1_Resize);
            this.Activated += new System.EventHandler(this.Form1_Activated);
            this.ResizeEnd += new System.EventHandler(this.Form1_ResizeEnd);
            this.Load += new System.EventHandler(this.Form1_Load);
            this.ResumeLayout(false);

        }
        #endregion

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.Run(new Form1());
            System.Diagnostics.Trace.WriteLine("Where am i?");
        }

        IrrlichtDevice device = null;
        ICameraSceneNode camera = null;
        ISceneNode container = null;

        ITexture texWall;
        ITexture texStones;

        Dimension2D InitialViewportDimensions;
        static float initialCameraDistance = 25;
        static float downViewRatio = 0.2f;
        static float leftViewRatio = 0.2f;

        bool OKtoDraw = false;

        private void Form1_Load(object sender, System.EventArgs e)
        {
            this.InitialViewportDimensions = new Dimension2D(this.Width, this.Height);

            // start up the engine

            //IrrlichtDevice device = new IrrlichtDevice(DriverType.OPENGL);
            //Vector3D initialCameraPosition = new Vector3D(30, 5, 5);
            this.device = new IrrlichtDevice(
                //DriverType.OPENGL,
                //DriverType.SOFTWARE2,
                DriverType.DIRECT3D9,
              this.InitialViewportDimensions,
              8,
              false,
              false,
              false,
              false,
              this.Handle
              );

            this.device.ResizeAble = true;

            // load some textures 
            texWall = this.device.VideoDriver.GetTexture(@"C:\irrlicht-0.14.0\media\wall.bmp");
            texStones = this.device.VideoDriver.GetTexture(@"C:\irrlicht-0.14.0\media\stones.jpg");

            // add a camera to the scene	
            this.camera = this.device.SceneManager.AddCameraSceneNode(null,
              CameraPosition(initialCameraDistance, downViewRatio, leftViewRatio),
              new Vector3D(0, 0, 0), -1);

            // Floor of the container:
            ISceneNode containerFloor = this.device.SceneManager.AddTestSceneNode(1,
              null, 1,
              // The geometric center of the object is placed here:
              new Vector3D(10, 0, 4),
              new Vector3D(0, 0, 0),
              // Length, Height, Width (in layman's terms)
              new Vector3D(20, 0, 8)
              );
            containerFloor.SetMaterialTexture(0, texWall);
            containerFloor.Name = "ContainerFloor";

            // Closed end of the container ("Front" in the direction of driving):
            ISceneNode containerClosedEnd = this.device.SceneManager.AddTestSceneNode(1,
              null, 2,
              new Vector3D(0, 5, 4),
              //new Vector3D(0, 0, 0),
              new Vector3D(0, 0, 0),
              new Vector3D(0, 10, 8)
              );
            containerClosedEnd.SetMaterialTexture(0, texWall);
            containerClosedEnd.Name = "ContainerClosedEnd";

            // Attach the Closed End to the Floor:
            MessageBox.Show("Now you see it...");
            containerFloor.AddChild(containerClosedEnd);
            MessageBox.Show("Now you don't!");
            //containerClosedEnd.SetParent(containerFloor);
            //containerFloor.SetParent(containerClosedEnd);

            this.container = containerFloor;
            //this.container = containerClosedEnd;

            //Peake.Container.Box testBox = new Peake.Container.Box(
            //    new Peake.Container.Dimensions(3, 2, 1),
            //    texStones, null, null);
            //testBox.AddToScene(this.device, this.container);

            // Fire up the engine
            this.device.Run();

            // View Form
            this.Show();
            this.OKtoDraw = true;

            // Draw container contents [must come after this.Show() to be effective!]
            // Let _Paint event handle it in a little while!  RefreshWindow();

            //this.Update();

            //IntPtr hWnd = this.Handle;
            //System.Diagnostics.Trace.WriteLine(String.Format("{0}", hWnd));
            //System.Diagnostics.Trace.WriteLine(String.Format("BorderSize: {0}, Border3DSize: {1}, BorderMultiplierFactor: {2}",
            //    System.Windows.Forms.SystemInformation.BorderSize,
            //    System.Windows.Forms.SystemInformation.Border3DSize,
            //    System.Windows.Forms.SystemInformation.BorderMultiplierFactor
            //    ));
        }

        void RefreshWindow()
        {
            if (this.OKtoDraw)
            {
                this.device.VideoDriver.BeginScene(true, true, new Irrlicht.Video.Color(0, 100, 100, 100));
                this.device.SceneManager.DrawAll();
                this.device.VideoDriver.EndScene();
            }
        }

        private void Form1_Resize(object sender, System.EventArgs e)
        {
            RefreshWindow();
        }

        private void Form1_Closed(object sender, System.EventArgs e)
        {
            Application.Exit();
        }

        private void Form1_Activated(object sender, System.EventArgs e)
        {
            RefreshWindow();
        }

        private void Form1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
        {
            RefreshWindow();
        }

        private float DegreesToRotate(uint msSinceLastMove, bool positive)
        {
            float directionMultiplier = (positive ? 1f : -1f);
            // First movement, or single press:
            float initialDegrees = 2f;
            if (msSinceLastMove == 0)
                return initialDegrees * directionMultiplier;

            float rotationsPerSecond = 1f / 3f;
            float moveDegrees = msSinceLastMove / 1000f * (rotationsPerSecond * 360f);
            //System.Diagnostics.Trace.WriteLine(String.Format("rps: {2}, ms: {0}, degrees = {1}", msSinceLastMove, moveDegrees, rotationsPerSecond));
            //      if (moveDegrees < 1f)
            //        moveDegrees = 0.5f;
            return moveDegrees * directionMultiplier;
        }

        bool rotatingLeftOrRight = false;

        private void RotateLeftOrRight(bool left)
        {
            // Useless!  this.container.Rotation.RotateXZBy(2, this.camera.AbsolutePosition);
            // Single movement: this.container.Rotation = new Vector3D(this.container.Rotation.X, this.container.Rotation.Y + 2, this.container.Rotation.Z);
            // Useless!  ISceneNodeAnimator rotateLeft = this.device.SceneManager.CreateRotationAnimator(new Vector3D(0, rotationsPerSecond, 0));
            this.rotatingLeftOrRight = true;
            uint prevRealTime = 0;
            while (this.rotatingLeftOrRight)
            {
                uint nowRealTime = this.device.Timer.RealTime;
                float moveDegrees = DegreesToRotate(
                  (prevRealTime == 0) ? 0 : (nowRealTime - prevRealTime),
                  left
                  );
                prevRealTime = nowRealTime;
                // Single movement:
                float newY = this.container.Rotation.Y + moveDegrees;
                while (newY > 360f)
                    newY = newY - 360f;
                while (newY < 0f)
                    newY = newY + 360f;
                this.container.Rotation = new Vector3D(this.container.Rotation.X, newY, this.container.Rotation.Z);
                //System.Diagnostics.Trace.WriteLine(String.Format("Container Rotation is ({0}, {1}, {2}) @ {3} (real {4}) after moving {5} degrees.", this.container.Rotation.X, this.container.Rotation.Y, this.container.Rotation.Z, this.device.Timer.Time, this.device.Timer.RealTime, moveDegrees));
                RefreshWindow();
                // Advance virtual time:  this.device.Timer.Tick();
                Application.DoEvents();
            }
        }


        private void buttonRotateLeft_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            RotateLeftOrRight(true);
        }

        private void buttonRotateLeft_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            this.rotatingLeftOrRight = false;
        }

        private void buttonRotateRight_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            RotateLeftOrRight(false);
        }

        private void buttonRotateRight_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            this.rotatingLeftOrRight = false;
        }

        static double DegreeToRadian(double degrees)
        {
            return degrees * Math.PI / 180f;
        }

        bool rotatingUpOrDown = false;

        private void RotateUpOrDown(bool up)
        {
            this.rotatingUpOrDown = true;
            uint prevRealTime = 0;
            while (this.rotatingUpOrDown)
            {
                uint nowRealTime = this.device.Timer.RealTime;
                float moveDegrees = DegreesToRotate(
                  (prevRealTime == 0) ? 0 : (nowRealTime - prevRealTime),
                  up
                  );
                prevRealTime = nowRealTime;
                float newZ = this.container.Rotation.Z + moveDegrees;
                while (newZ > 360f)
                    newZ = newZ - 360f;
                while (newZ < 0f)
                    newZ = newZ + 360f;
                this.container.Rotation = new Vector3D(this.container.Rotation.X, this.container.Rotation.Y, newZ);
                //System.Diagnostics.Trace.WriteLine(String.Format("Container Rotation is ({0}, {1}, {2}) @ {3} (real {4}) after moving {5} degrees Z.", this.container.Rotation.X, this.container.Rotation.Y, this.container.Rotation.Z, this.device.Timer.Time, this.device.Timer.RealTime, moveDegrees));
                RefreshWindow();
                Application.DoEvents();
            }
        }

        private void buttonRotateUp_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            RotateUpOrDown(true);
        }

        private void buttonRotateUp_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            this.rotatingUpOrDown = false;
        }

        private void buttonRotateDown_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            RotateUpOrDown(false);
        }

        private void buttonRotateDown_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            this.rotatingUpOrDown = false;
        }

        private void buttonRotateHome_Click(object sender, System.EventArgs e)
        {
            this.container.Rotation = new Vector3D(0, 0, 0);
            RefreshWindow();
            // For some reason, the first DrawAll does not do anything,
            // until another button is pressed or a Paint event occurs (causing another DrawAll).
            // So we force it ourselves!
            RefreshWindow();
        }

        private void Form1_MouseClick(object sender, MouseEventArgs e)
        {
            ISceneCollisionManager collisionMgr = this.device.SceneManager.SceneCollisionManager;
            ISceneNode currentNode = collisionMgr.GetSceneNodeFromScreenCoordinatesBB(
                new Position2D(
                e.X,
                e.Y
                 + this.BorderTopAdjustPixels
                 - (this.Height - this.InitialViewportDimensions.Height)
                ),
                0);
            if (currentNode != null)
            {
                currentNode.SetMaterialTexture(0, texStones);
                RefreshWindow();
            }
        }

        /// <summary>
        /// Increase this value if drawn objects are lower than GetSceneNodeFromScreenCoordinatesBB() registers.
        /// </summary>
        private int BorderTopAdjustPixels
        {
            get
            {
                switch (this.FormBorderStyle)
                {
                    case FormBorderStyle.Fixed3D:
                    case FormBorderStyle.Sizable:
                        return System.Windows.Forms.SystemInformation.Border3DSize.Height
                            + System.Windows.Forms.SystemInformation.CaptionHeight
                            + 7;
                    case FormBorderStyle.None:
                        return 0;
                    default:
                        return System.Windows.Forms.SystemInformation.BorderSize.Height * System.Windows.Forms.SystemInformation.BorderMultiplierFactor
                            + System.Windows.Forms.SystemInformation.CaptionHeight
                            + 5;
                }
            }
        }

        //private void Form1_MouseMove_1(object sender, MouseEventArgs e)
        //{
        //    ISceneCollisionManager collisionMgr = this.device.SceneManager.SceneCollisionManager;
        //    ISceneNode currentNode = collisionMgr.GetSceneNodeFromScreenCoordinatesBB(
        //        new Position2D(
        //        e.X,
        //        e.Y
        //         + this.BorderTopAdjustPixels
        //         - (this.Height - this.initialViewportDimensions.Height)
        //        ),
        //        0);
        //    System.Diagnostics.Trace.WriteLine(String.Format("{2} @ ({0}, {1}), Viewport: ({3}, {4}), Window: ({5}, {6})",
        //        e.X, e.Y, currentNode == null ? "Nothing" : currentNode.Name,
        //        this.initialViewportDimensions.Width, this.initialViewportDimensions.Height,
        //        this.Width, this.Height));

        //}

        /// <summary>
        /// Derivation:
        ///    d = Camera Distance (as the crow flies)
        ///    (x,y,z) = Camera Position
        ///    vlr = View Left Ratio (as a fraction of x)
        ///    vdr = View Down Ratio (as a fraction of x)
        /// 
        ///    z = x * vlr
        ///    y = x * vdr
        ///    d^2 = z^2 + (x^2 + y^2)
        ///    d^2 = vlr^2 x^2 + x^2 + vdr^2 x^2
        ///    d^2 = (vlr^2 + vdr^2 + 1) * x^2
        ///    x = d / sqrt(vlr^2 + vdr^2 + 1)
        /// </summary>
        /// <param name="cameraDistance"></param>
        /// <param name="downViewRatio"></param>
        /// <param name="leftViewRatio"></param>
        /// <returns></returns>
        static Vector3D CameraPosition(float cameraDistance, float downViewRatio, float leftViewRatio)
        {
            float x = cameraDistance / (float) Math.Sqrt((double)(leftViewRatio * leftViewRatio + downViewRatio * downViewRatio + 1));
            return new Vector3D(x, x * downViewRatio, x * leftViewRatio);
        }

        float NewCameraDistance
        {
            get
            {
                return initialCameraDistance
                    / (float) Math.Sqrt(Math.Pow(this.Size.Width, 2) + Math.Pow(this.Size.Height, 2))
                    * (float) Math.Sqrt(Math.Pow(this.InitialViewportDimensions.Width, 2) + Math.Pow(this.InitialViewportDimensions.Height, 2));
            }
        }

        private void Form1_ResizeEnd(object sender, EventArgs e)
        {
            this.camera.Position = CameraPosition(NewCameraDistance, downViewRatio, leftViewRatio);
            // ?? this.device.ViewportDimensions = new Dimension2D(this.Width, this.Height);
            // ?? this.device.VideoDriver.ViewPort.Height = this.Height;
            // ?? this.device.VideoDriver.ViewPort.Width = this.Width;
            RefreshWindow();
            RefreshWindow();
            System.Diagnostics.Trace.WriteLine(String.Format("New viewport size: {0}", this.Size));
        }
    }
}
Post Reply