Sign in to follow this  
s3mt3x

OpenGL Can someone try this for me (cool camera code)

Recommended Posts

s3mt3x    118
Hi Guys, I'm porting an old applicatin over from OpenGl to managed directx, and i'm getting poor performance on my machine. I was wondering if some of you could try the following code on your machines to see if you get the same? I need to know whether this is just my crappy old PC or an issue with mdx. I'm repainting responding to mouse events (it's a modelling app, not a game before i get flamed!!). The code features a cool maya style camera for anyone who's interested. Any feedback would be great.
public partial class Form1 : Form
    {
        //our device
        Device device;

        //constant to convert degrees to radians
        const float RAD = 0.0174532925f;

        #region Camera Variables
        //integers to track our mouse position
        int mouseX;
        int mouseY;

        //our mouse button states
        private bool leftMouseDown = false;
        private bool middleMouseDown = false;
        private bool rightMouseDown = false;

        private Vector3 translation = new Vector3();
        //Up Vector
        Vector3 up = new Vector3(0, 1, 0);
        //Left Vector 
        Vector3 left = new Vector3(1, 0, 0);
        //forward Vector
        Vector3 forward = new Vector3(0, 0, 1);
        //vector to store our rotation
        Vector3 rotation = new Vector3();
        //our zoom value
        private float zoom = 100f;
        //the plane we drag our mouse on
        private Plane middleMouseDragPlane;
        //our view matricies
        Matrix projectionMatrix;
        Matrix viewMatrix;
        //our viewport
        Viewport viewPort;
        #endregion

        #region Grid Variables
        //the grid vertices
        CustomVertex.PositionColored[] gridGeometry;
        //the grid size
        int gridSize = 500;
        //the grid step
        int gridStep = 10;
        #endregion

        /// <summary>
        /// Returns the camera's position in world space
        /// </summary>
        public Vector3 CameraPosition
        {
            get
            {
                Matrix inverseView = Matrix.Multiply(this.viewMatrix, Matrix.Identity);
                inverseView.Invert();
                Vector4 temp = Vector3.Transform(new Vector3(), inverseView);
                return new Vector3(temp.X, temp.Y, temp.Z);
            }
        }

        public Form1()
        {
            this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            this.SetStyle(ControlStyles.Opaque, true);
            this.SetStyle(ControlStyles.UserPaint, true);
            InitializeComponent();
            InitializeGraphics();

            //manually call our resize method to initialize our viewport
            this.OnResize(new System.EventArgs());
        }

        private void InitializeGraphics()
        {
            PresentParameters present = new PresentParameters();
            present = new PresentParameters();
            present.SwapEffect = SwapEffect.Discard;
            present.Windowed = true;
            present.EnableAutoDepthStencil = true;
            present.AutoDepthStencilFormat = DepthFormat.D16;

            this.device = new Device(0, DeviceType.Hardware, this, CreateFlags.SoftwareVertexProcessing, present);

            this.InitializeGrid();
        }

        private void Form1_Resize(object sender, EventArgs e)
        {
            this.viewPort = new Viewport();
            this.viewPort.X = 0;
            this.viewPort.Y = 0;
            this.viewPort.Width = this.ClientSize.Width;
            this.viewPort.Height = this.ClientSize.Height;

            this.viewPort.MinZ = 0.0f;
            this.viewPort.MaxZ = 1.0f;
        }

        public void SetupView(Device device)
        {
            device.Viewport = this.viewPort;

            this.projectionMatrix = Matrix.PerspectiveFovLH((float)Math.PI / 4, ((float)this.ClientSize.Width) / ((float)this.ClientSize.Height), 1f, 20000.0f);
            device.Transform.Projection = this.projectionMatrix;

            Matrix zoomMat = Matrix.LookAtLH(new Vector3(0, 0, this.zoom), new Vector3(), new Vector3(0, 1, 0));
            Matrix rotationXMat = Matrix.RotationX(this.rotation.X * RAD);
            Matrix rotationYMat = Matrix.RotationY(this.rotation.Y * RAD);
            Matrix translationMat = Matrix.Translation(this.translation.X, this.translation.Y, this.translation.Z);

            this.viewMatrix = translationMat * rotationYMat * rotationXMat * zoomMat;
            device.Transform.View = this.viewMatrix;

            Matrix negativeRotationX = Matrix.RotationX(-this.rotation.X * RAD);
            Matrix negativeRotationY = Matrix.RotationY(-this.rotation.Y * RAD);

            Matrix axisRotation = negativeRotationX * negativeRotationY;

            //transform static view vectors
            Vector4 tempUp = Vector3.Transform(new Vector3(0, 1, 0), axisRotation);
            Vector4 tempLeft = Vector3.Transform(new Vector3(1, 0, 0), axisRotation);
            Vector4 tempForward = Vector3.Transform(new Vector3(0, 0, 1), axisRotation);

            //set our view vectors to the result
            this.up = new Vector3(tempUp.X, tempUp.Y, tempUp.Z);
            this.left = new Vector3(tempLeft.X, tempLeft.Y, tempLeft.Z);
            this.forward = new Vector3(tempForward.X, tempForward.Y, tempForward.Z);
            //make sure we've normailised our view vectors
            this.up.Normalize();
            this.left.Normalize();
            this.up.Normalize();
        }

        public Microsoft.DirectX.Vector3 GenerateNormalizedPickRay(int x, int y)
        {
            Vector3 near = new Vector3(x, y, 0);
            Vector3 far = new Vector3(x, y, 1);
            Viewport viewPort = new Viewport();
            viewPort.Width = this.viewPort.Width;
            viewPort.Height = this.viewPort.Height;
            viewPort.MinZ = 0;
            viewPort.MaxZ = 1;
            near.Unproject(viewPort, this.projectionMatrix, this.viewMatrix, Matrix.Identity);
            far.Unproject(viewPort, this.projectionMatrix, this.viewMatrix, Matrix.Identity);

            Vector3 direction = Vector3.Subtract(far, near);

            return Vector3.Normalize(direction);
        }

        private void Form1_MouseDown(object sender, MouseEventArgs e)
        {
            int x = e.X;
            int y = e.Y;
            System.Windows.Forms.MouseButtons buttons = e.Button;
            switch (buttons)
            {
                case System.Windows.Forms.MouseButtons.Left:
                    this.leftMouseDown = true;
                    break;
                case System.Windows.Forms.MouseButtons.Middle:
                    Vector3 cameraPosition = this.CameraPosition;
                    Vector3 focalDirection = new Vector3(this.forward.X, this.forward.Y, this.forward.Z);
                    Vector3 focalPoint = new Vector3(cameraPosition.X - 
(focalDirection.X * this.zoom), cameraPosition.Y - (focalDirection.Y * this.zoom), cameraPosition.Z - (focalDirection.Z * this.zoom));
                    this.middleMouseDragPlane = Plane.FromPointNormal(focalPoint, this.forward);
                    this.middleMouseDown = true;
                    break;
                case System.Windows.Forms.MouseButtons.Right:
                    this.rightMouseDown = true;
                    break;
            }
            this.mouseX = x;
            this.mouseY = y;
        }

        private void Form1_MouseMove(object sender, MouseEventArgs e)
        {
            int x = e.X;
            int y = e.Y;
            System.Windows.Forms.MouseButtons buttons = e.Button;
            if (this.leftMouseDown)
            {
                this.rotation.Y += this.mouseX - x;
                this.rotation.X -= this.mouseY - y;

                if (this.rotation.X > 90)
                {
                    this.rotation.X = 90;
                }

                if (this.rotation.X < -90)
                {
                    this.rotation.X = -90;
                }

                if (this.rotation.Y > 360)
                {
                    this.rotation.Y = this.rotation.Y % 360.0f;
                }

                if (this.rotation.Y < 0)
                {
                    this.rotation.Y = 360.0f - this.rotation.Y;
                }
            }
            else if (this.middleMouseDown)
            {
                Vector3 cameraPosition = this.CameraPosition;

                Vector3 newPosition = Plane.IntersectLine(this.middleMouseDragPlane, cameraPosition, this.CameraPosition + (this.GenerateNormalizedPickRay(x, y) * this.zoom));
                Vector3 currentPosition = Plane.IntersectLine
(this.middleMouseDragPlane, cameraPosition, this.CameraPosition + 
(this.GenerateNormalizedPickRay(this.mouseX, this.mouseY) * this.zoom));
                Vector3 difference = newPosition - currentPosition;
                this.translation.X += difference.X;
                this.translation.Y += difference.Y;
                this.translation.Z += difference.Z;
            }
            else if (this.rightMouseDown)
            {
                int deltaY = y - this.mouseY;
                this.zoom -= ((float)deltaY) * (this.zoom / 1000.0f);
            }

            this.mouseX = x;
            this.mouseY = y;

            if (this.leftMouseDown | this.middleMouseDown | this.rightMouseDown)
            {
                this.Invalidate();
            }
        }

        private void Form1_MouseUp(object sender, MouseEventArgs e)
        {
            int x = e.X;
            int y = e.Y;
            System.Windows.Forms.MouseButtons buttons = e.Button;
            switch (buttons)
            {
                case System.Windows.Forms.MouseButtons.Left:
                    this.leftMouseDown = false;
                    break;
                case System.Windows.Forms.MouseButtons.Middle:
                    this.middleMouseDown = false;
                    break;
                case System.Windows.Forms.MouseButtons.Right:
                    this.rightMouseDown = false;
                    break;
            }
            this.mouseX = x;
            this.mouseY = y;

            this.Invalidate();
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            device.RenderState.Lighting = false;

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

            this.SetupView(device);

            device.BeginScene();

            //draw our grid
            device.VertexFormat = CustomVertex.PositionColored.Format;
            device.DrawUserPrimitives(PrimitiveType.LineList, this.gridGeometry.Length / 2, this.gridGeometry);

            device.EndScene();

            device.Present();
            
            base.OnPaint(e);
        }


        private void InitializeGrid()
        {
            int numLines = this.gridSize / this.gridStep;

            this.gridGeometry = new CustomVertex.PositionColored[((numLines * 2) * 2) + 4];
            int gridIndex = 0;
            for (int x = 0 - this.gridSize / 2; x <= this.gridSize / 2; x += this.gridStep)
            {
                this.gridGeometry[gridIndex].X = x;
                this.gridGeometry[gridIndex].Y = 0;
                this.gridGeometry[gridIndex].Z = 0 - this.gridSize / 2;
                if (x != 0)
                {
                    this.gridGeometry[gridIndex].Color = System.Drawing.Color.FromArgb(128, 128, 128).ToArgb();
                }
                else
                {
                    this.gridGeometry[gridIndex].Color = System.Drawing.Color.Black.ToArgb();
                }



                this.gridGeometry[gridIndex + 1].X = x;
                this.gridGeometry[gridIndex + 1].Y = 0;
                this.gridGeometry[gridIndex + 1].Z = this.gridSize / 2;
                if (x != 0)
                {
                    this.gridGeometry[gridIndex + 1].Color = System.Drawing.Color.FromArgb(128, 128, 128).ToArgb();
                }
                else
                {
                    this.gridGeometry[gridIndex + 1].Color = System.Drawing.Color.Black.ToArgb();
                }

                gridIndex += 2;
            }

            for (int z = 0 - this.gridSize / 2; z <= this.gridSize / 2; z += this.gridStep)
            {
                this.gridGeometry[gridIndex].X = 0 - this.gridSize / 2;
                this.gridGeometry[gridIndex].Y = 0;
                this.gridGeometry[gridIndex].Z = z;
                if (z != 0)
                {
                    this.gridGeometry[gridIndex].Color = System.Drawing.Color.FromArgb(128, 128, 128).ToArgb();
                }
                else
                {
                    this.gridGeometry[gridIndex].Color = System.Drawing.Color.Black.ToArgb();
                }


                this.gridGeometry[gridIndex + 1].X = this.gridSize / 2;
                this.gridGeometry[gridIndex + 1].Y = 0;
                this.gridGeometry[gridIndex + 1].Z = z;
                if (z != 0)
                {
                    this.gridGeometry[gridIndex + 1].Color = System.Drawing.Color.FromArgb(128, 128, 128).ToArgb();
                }
                else
                {
                    this.gridGeometry[gridIndex + 1].Color = System.Drawing.Color.Black.ToArgb();
                }

                gridIndex += 2;
            }
        }
    }


Thanks, Chris [Edited by - s3mt3x on May 6, 2007 6:08:24 AM]

Share this post


Link to post
Share on other sites
devronious    108
Chris,

Yea that works super. I have an exact one of those that I use for level editing. Setup on the form a bit different but still operates the same. I like that style, it gives you good control over the environment.

-Devin

[edit] Oops, should have addressed the pefromance issue. You should be using a render loop instead of the OnPaint event of the Form if you want better performance. Look at the following thread:

Render Loop Thread

Share this post


Link to post
Share on other sites
s3mt3x    118
Hi Devin,

Thanks for trying it out - with regard to the rendering loop, like i said, i'm repainting based on mouse movements - there's no need to repaint using a render loop - the only time the display needs to be updated is in response to input in some shape or form.

Did the camera motion go "scratchy"? On my pc once i start the application it drops in performance when the mouse is moved - however, sometimes it's smooth as expected.


Thanks again,


Chris

Share this post


Link to post
Share on other sites
devronious    108
Oh, OK, I see. If that is the case then I'm unsure what performance you are talking about. Is it rotating slow for you? It seems fine on my machine. I'll look at the code again just to verify everything's tops.

-Devin

Share this post


Link to post
Share on other sites
devronious    108
Just going thru your code to point a couple of things out. The following code is reduntant because any matrix multiplied by the identity is the matrix. Multiplying a matrix by the identity does nothing. If you're trying to get a new matrix then simply assigning it would be suffice (ie: Matrix inverseView = this.viewMatrix;). The reason for this is that Matrix is a struct and duplicates itself on assignment rather than assigning a reference of itself like an object would do.

[source lang = "c#"]
Matrix inverseView = Matrix.Multiply(this.viewMatrix, Matrix.Identity);



You might try Hardware Vertex Processing as well in the Device constructor. Just perhaps it might speed things up?:

[source lang = "c#"]
this.device = new Device(0, DeviceType.Hardware, this, CreateFlags.SoftwareVertexProcessing, present);



Again, it works super.

If you really need more efficiency in your code there are more efficient approaches to doing that. I think if you tweak at it and study the matrices and vector math more you will eventually get your code more and more efficient as time goes on. For now perhaps it's just super :).

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this  

  • Partner Spotlight

  • Similar Content

    • By pseudomarvin
      I assumed that if a shader is computationally expensive then the execution is just slower. But running the following GLSL FS instead just crashes
      void main() { float x = 0; float y = 0; int sum = 0; for (float x = 0; x < 10; x += 0.00005) { for (float y = 0; y < 10; y += 0.00005) { sum++; } } fragColor = vec4(1, 1, 1 , 1.0); } with unhandled exception in nvoglv32.dll. Are there any hard limits on the number of steps/time that a shader can take before it is shut down? I was thinking about implementing some time intensive computation in shaders where it would take on the order of seconds to compute a frame, is that possible? Thanks.
    • By Arulbabu Donbosco
      There are studios selling applications which is just copying any 3Dgraphic content and regenerating into another new window. especially for CAVE Virtual reality experience. so that the user opens REvite or CAD or any other 3D applications and opens a model. then when the user selects the rendered window the VR application copies the 3D model information from the OpenGL window. 
      I got the clue that the VR application replaces the windows opengl32.dll file. how this is possible ... how can we copy the 3d content from the current OpenGL window.
      anyone, please help me .. how to go further... to create an application like VR CAVE. 
       
      Thanks
    • By cebugdev
      hi all,

      i am trying to build an OpenGL 2D GUI system, (yeah yeah, i know i should not be re inventing the wheel, but this is for educational and some other purpose only),
      i have built GUI system before using 2D systems such as that of HTML/JS canvas, but in 2D system, i can directly match a mouse coordinates to the actual graphic coordinates with additional computation for screen size/ratio/scale ofcourse.
      now i want to port it to OpenGL, i know that to render a 2D object in OpenGL we specify coordiantes in Clip space or use the orthographic projection, now heres what i need help about.
      1. what is the right way of rendering the GUI? is it thru drawing in clip space or switching to ortho projection?
      2. from screen coordinates (top left is 0,0 nd bottom right is width height), how can i map the mouse coordinates to OpenGL 2D so that mouse events such as button click works? In consideration ofcourse to the current screen/size dimension.
      3. when let say if the screen size/dimension is different, how to handle this? in my previous javascript 2D engine using canvas, i just have my working coordinates and then just perform the bitblk or copying my working canvas to screen canvas and scale the mouse coordinates from there, in OpenGL how to work on a multiple screen sizes (more like an OpenGL ES question).
      lastly, if you guys know any books, resources, links or tutorials that handle or discuss this, i found one with marekknows opengl game engine website but its not free,
      Just let me know. Did not have any luck finding resource in google for writing our own OpenGL GUI framework.
      IF there are no any available online, just let me know, what things do i need to look into for OpenGL and i will study them one by one to make it work.
      thank you, and looking forward to positive replies.
    • By fllwr0491
      I have a few beginner questions about tesselation that I really have no clue.
      The opengl wiki doesn't seem to talk anything about the details.
       
      What is the relationship between TCS layout out and TES layout in?
      How does the tesselator know how control points are organized?
          e.g. If TES input requests triangles, but TCS can output N vertices.
             What happens in this case?
      In this article,
      http://www.informit.com/articles/article.aspx?p=2120983
      the isoline example TCS out=4, but TES in=isoline.
      And gl_TessCoord is only a single one.
      So which ones are the control points?
      How are tesselator building primitives?
    • By Orella
      I've been developing a 2D Engine using SFML + ImGui.
      Here you can see an image
      The editor is rendered using ImGui and the scene window is a sf::RenderTexture where I draw the GameObjects and then is converted to ImGui::Image to render it in the editor.
      Now I need to create a 3D Engine during this year in my Bachelor Degree but using SDL2 + ImGui and I want to recreate what I did with the 2D Engine. 
      I've managed to render the editor like I did in the 2D Engine using this example that comes with ImGui. 
      3D Editor preview
      But I don't know how to create an equivalent of sf::RenderTexture in SDL2, so I can draw the 3D scene there and convert it to ImGui::Image to show it in the editor.
      If you can provide code will be better. And if you want me to provide any specific code tell me.
      Thanks!
  • Popular Now