0

我对 DirectX 库有点陌生,我想知道是否有人可以帮助我解决相机问题。在我的主表单中,我加载了一组表示 3D 对象的多边形数据,然后将该多边形数据传递给另一个表单,并希望将多边形绘制为三角形列表。不幸的是,我似乎无法让相机达到 1)具有正确的视锥或 2)让相机正确聚焦和调整图像大小。多边形数据正在作为世界坐标数据加载。

下面是初始化二级窗体、directx、camera等的代码。

#region Public Members

    /// <summary>
    /// Default Constructor.
    /// </summary>
    public STLViewer()
    {
        // Set the form size, form text, icon
        this.ClientSize = new Size(500, 500);
        this.Text = "Object Name: " + stlFile.SolidName + ", Polygon Count: " + stlFile.GetPolygons().Count;
        this.Icon = RetrieveFormIcon();

        // Change our drawing style so there is no drawing happening outside our main form
        this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.Opaque, true);

        // Get our vertex data in a prepared format
        verts = PrepareObjectForRender();
    }

    /// <summary>
    /// This function is responsible for retrieving the specified
    /// icon from the assembly.
    /// </summary>
    /// <returns>Form icon</returns>
    private Icon RetrieveFormIcon()
    {
        Assembly assembly = Assembly.GetExecutingAssembly();
        Stream str = assembly.GetManifestResourceStream(icon);

        return new Icon(str);
    }

    #endregion

    #region Main Line

    public static void Main()
    {
        // Create our form object
        STLViewer stlViewer = new STLViewer();

        // Initialize D3D
        if (stlViewer.InitializeDirect3D() == false)
        {
            MessageBox.Show("Could not initialize Direct3D.", "Error");
            return;
        }

        // Display our form
        stlViewer.Show();

        // Main message loop
        while (stlViewer.Created)
        {
            // Keep rendering the image until the form is terminated
            //stlViewer.Render();

            // Handle aall events here: keyboard, mouse, etc.
            Application.DoEvents();
        }
    }

    #endregion

    #region Rendering

    protected override void OnPaint(PaintEventArgs e)
    {
        if (directXDevice.RenderState.FillMode == FillMode.Solid)
        {
            directXDevice.RenderState.FillMode = FillMode.WireFrame;
        }

        // Clear the window to black
        directXDevice.Clear(ClearFlags.Target, Color.Black, 1.0f, 0);

        // Setup the camera for viewing
        SetupCamera();

        // Begin the rendering process
        directXDevice.BeginScene();

        // Set the vertext format
        directXDevice.VertexFormat = CustomVertex.PositionColored.Format;

        // Draw our vertices
        directXDevice.DrawUserPrimitives(PrimitiveType.TriangleList, stlFile.GetPolygons().Count, verts);

        // End rendering and present the drawing to the screen
        directXDevice.EndScene();
        directXDevice.Present();

        // Force our form to refresh its viewing area
        this.Invalidate();
    }

    /// <summary>
    /// This function is responsible for rendering the image
    /// to the screen.
    /// </summary>
    private void Render()
    {
        // IF we cannot connect to a device then return
        if (directXDevice == null)
        {
            return;
        }

        // Get our vertex data in a prepared format
        CustomVertex.PositionColored[] verts = PrepareObjectForRender();

        // Clear the window to black
        directXDevice.Clear(ClearFlags.Target, Color.Black, 1.0f, 0);

        // Setup the camera for viewing
        SetupCamera();

        // Begin the rendering process
        directXDevice.BeginScene();

        // Set the vertext format
        directXDevice.VertexFormat = CustomVertex.PositionColored.Format;

        // Draw our vertices
        directXDevice.DrawUserPrimitives(PrimitiveType.TriangleList, stlFile.GetPolygons().Count, verts);

        // End rendering and present the drawing to the screen
        directXDevice.EndScene();
        directXDevice.Present();
    }

    /// <summary>
    /// This function is responsible for creating the necessary
    /// DirectX objects, setting the vertices and normals, colors
    /// and/or materials for the object so we can draw it in the
    /// form.
    /// </summary>
    private CustomVertex.PositionColored[] PrepareObjectForRender()
    {
        // List to hold our colored vertices
        List<CustomVertex.PositionColored> vertices = new List<CustomVertex.PositionColored>();

        // List to hold our polygons, contained within the STL file
        List<Polygon.Polygon> polygons = stlFile.GetPolygons();

        // Create a custom vertex that will be used to hold our vertices
        CustomVertex.PositionColored custVert = new CustomVertex.PositionColored();

        // Iterate through our polygons and pulled a vertex list
        for (int i = 0; i < polygons.Count; i++)
        {
            // Set the position and color of our 1st vertex in our polygon, add it to our list
            custVert.Position = new Vector3((float)polygons[i].GetDoublePoints1()[0],
                (float)polygons[i].GetDoublePoints1()[1], (float)polygons[i].GetDoublePoints1()[2]);
            custVert.Color = Color.YellowGreen.ToArgb();
            vertices.Add(custVert);

            // Set the position and color of our 2nd vertex in our polygon, add it to our list
            custVert.Position = new Vector3((float)polygons[i].GetDoublePoints2()[0],
                (float)polygons[i].GetDoublePoints2()[1], (float)polygons[i].GetDoublePoints2()[2]);
            custVert.Color = Color.YellowGreen.ToArgb();
            vertices.Add(custVert);

            // Set the position and color of our 3rd vertex in our polygon, add it to our list
            custVert.Position = new Vector3((float)polygons[i].GetDoublePoints3()[0],
                (float)polygons[i].GetDoublePoints3()[1], (float)polygons[i].GetDoublePoints3()[2]);
            custVert.Color = Color.YellowGreen.ToArgb();
            vertices.Add(custVert);
        }

        // Cast our list to an array of vertices
        CustomVertex.PositionColored[] verts = vertices.ToArray();

        return verts;
    }

    #endregion

    #region Initialization & Configuration

    private bool InitializeDirect3D()
    {
        bool retVal = false;

        try
        {
            // Create a new PresentParameters object so our device knows how to display
            PresentParameters pps = new PresentParameters();

            // Display in a windowed mode
            pps.Windowed = true;

            // After the current screen is draw, discard it from memory
            pps.SwapEffect = SwapEffect.Discard;

            // Create the new D3D Device and set our PresentParameters within
            directXDevice = new Device(0, DeviceType.Hardware, this, 
                CreateFlags.SoftwareVertexProcessing, pps);

            // Use wireframe as our drawing mode
            directXDevice.RenderState.FillMode = FillMode.WireFrame;

            retVal = true;
        }
        catch (DirectXException e)
        {
            // Display our error message
            MessageBox.Show(e.ToString(), "Error");

            retVal = false;
        }

        return retVal;
    }

    private void SetupCamera()
    {
        directXDevice.Transform.Projection = Matrix.PerspectiveFovLH(1.85f,
(float)(this.Width / this.Height), 1.0f, 1.00f);

        directXDevice.Transform.View = Matrix.LookAtLH(new Vector3(0.0f, 0.0f, 5.0f),
            new Vector3(0.0f, 0.0f, 0.0f), new Vector3(0.0f, 1.0f, 0.0f));

        directXDevice.RenderState.Lighting = false;
    }

    #endregion
4

1 回答 1

0

有一些小事情不合适,并在drinkenhyena 找到了一个我忘记的教程,它帮助我完成了剩下的工作。

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.IO;
using System.Reflection;
using Polygon;
using STL;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;

namespace STLView
{
    public class STLViewer : Form
    {
        #region Private Members

        #region DirectX Objects

        /// <summary>
        /// DirectX Device object that will allow us to perform drawing
        /// </summary>
        private Device directXDevice = null;

        /// <summary>
        /// Array of vertices that will hold our Polygon vertices
        /// </summary>
        private static CustomVertex.PositionColored[] verts;

        #endregion

        #region STL Viewer Specific Objects

        /// <summary>
        /// String to hold the name of the path in the assembly for our form icon
        /// </summary>
        private static string icon = "STLView.Resources.Symbol17.ico";

        /// <summary>
        /// STLFile object that will be used to draw the object
        /// </summary>
        public static STLFile stlFile;

        #endregion

        #endregion

        #region Public Members

        /// <summary>
        /// Default Constructor.
        /// </summary>
        public STLViewer()
        {
            // Set the form size, form text, icon
            this.ClientSize = new Size(800, 600);
            this.Text = "Object Name: " + stlFile.SolidName + ", Polygon Count: " + stlFile.GetPolygons().Count;
            this.Icon = RetrieveFormIcon();

            // Change our drawing style so there is no drawing happening outside our main form
            this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.Opaque, true);

            // Get our vertex data in a prepared format
            verts = PrepareObjectForRender();
        }

        /// <summary>
        /// This function is responsible for retrieving the specified
        /// icon from the assembly.
        /// </summary>
        /// <returns>Form icon</returns>
        private Icon RetrieveFormIcon()
        {
            Assembly assembly = Assembly.GetExecutingAssembly();
            Stream str = assembly.GetManifestResourceStream(icon);

            return new Icon(str);
        }

        #endregion

        #region Main Line

        public static void Main()
        {
            // Create our form object
            STLViewer stlViewer = new STLViewer();

            // Initialize D3D
            if (stlViewer.InitializeDirect3D() == false)
            {
                MessageBox.Show("Could not initialize Direct3D.", "Error");
                return;
            }

            // Display our form
            stlViewer.Show();

            // Main message loop
            while (stlViewer.Created)
            {
                // Handle aall events here: keyboard, mouse, etc.
                Application.DoEvents();
            }
        }

        #endregion

        #region Rendering

        /// <summary>
        /// This function is the overloaded OnPaint method, which is responsible
        /// for drawing our scene.
        /// </summary>
        /// <param name="e"></param>
        protected override void OnPaint(PaintEventArgs e)
        {
            // IF we have a forced switch to Solid mode switch to Wireframe
            if (directXDevice.RenderState.FillMode == FillMode.Solid)
            {
                directXDevice.RenderState.FillMode = FillMode.WireFrame;
            }

            // Clear the window to black
            directXDevice.Clear(ClearFlags.Target, Color.Navy, 1.0f, 0);

            // Disable culling
            directXDevice.RenderState.CullMode = Cull.None;

            // Setup the camera for viewing
            SetupCamera();

            // Begin the rendering process
            directXDevice.BeginScene();

            // Set the vertext format
            directXDevice.VertexFormat = CustomVertex.PositionColored.Format;

            // Draw our vertices
            directXDevice.DrawUserPrimitives(PrimitiveType.TriangleList, stlFile.GetPolygons().Count, verts);

            // End rendering and present the drawing to the screen
            directXDevice.EndScene();
            directXDevice.Present();

            // Force our form to refresh its viewing area
            this.Invalidate();
        }

        /// <summary>
        /// This function is responsible for creating the necessary
        /// DirectX objects, setting the vertices and normals, colors
        /// and/or materials for the object so we can draw it in the
        /// form.
        /// </summary>
        private CustomVertex.PositionColored[] PrepareObjectForRender()
        {
            // List to hold our colored vertices
            List<CustomVertex.PositionColored> vertices = new List<CustomVertex.PositionColored>();

            // List to hold our polygons, contained within the STL file
            List<Polygon.Polygon> polygons = stlFile.GetPolygons();

            // Create a custom vertex that will be used to hold our vertices
            CustomVertex.PositionColored custVert = new CustomVertex.PositionColored();

            // Iterate through our polygons and pulled a vertex list
            for (int i = 0; i < polygons.Count; i++)
            {
                // Set the position and color of our 1st vertex in our polygon, add it to our list
                custVert.Position = new Vector3((float)polygons[i].GetDoublePoints1()[0],
                    (float)polygons[i].GetDoublePoints1()[1], (float)polygons[i].GetDoublePoints1()[2]);
                custVert.Color = Color.YellowGreen.ToArgb();
                vertices.Add(custVert);

                // Set the position and color of our 2nd vertex in our polygon, add it to our list
                custVert.Position = new Vector3((float)polygons[i].GetDoublePoints2()[0],
                    (float)polygons[i].GetDoublePoints2()[1], (float)polygons[i].GetDoublePoints2()[2]);
                custVert.Color = Color.YellowGreen.ToArgb();
                vertices.Add(custVert);

                // Set the position and color of our 3rd vertex in our polygon, add it to our list
                custVert.Position = new Vector3((float)polygons[i].GetDoublePoints3()[0],
                    (float)polygons[i].GetDoublePoints3()[1], (float)polygons[i].GetDoublePoints3()[2]);
                custVert.Color = Color.YellowGreen.ToArgb();
                vertices.Add(custVert);
            }

            // Cast our list to an array of vertices
            CustomVertex.PositionColored[] verts = vertices.ToArray();

            return verts;
        }

        #endregion

        #region Initialization & Configuration

        /// <summary>
        /// This function is responsible for initializing our Direct3D device.
        /// </summary>
        /// <returns>TRUE if successful, FALSE if not</returns>
        private bool InitializeDirect3D()
        {
            bool retVal = false;

            // TRY to create our Direct3D device
            // CATCH and report any errors
            try
            {
                #region Present Parameters

                // Create a new PresentParameters object so our device knows how to display
                PresentParameters pps = new PresentParameters();

                // Display in a windowed mode
                pps.Windowed = true;

                // After the current screen is draw, discard it from memory
                pps.SwapEffect = SwapEffect.Discard;

                // No Z (Depth) buffer or Stencil buffer
                pps.EnableAutoDepthStencil = false;

                // 1 Back buffer for double-buffering
                pps.BackBufferCount = 1;

                // Set our back buffer dimensions and format
                pps.BackBufferHeight = 0;
                pps.BackBufferWidth = 0;
                pps.BackBufferFormat = Format.Unknown;

                #endregion

                // Create the new D3D Device and set our PresentParameters within
                directXDevice = new Device(0, DeviceType.Hardware, this,
                    CreateFlags.SoftwareVertexProcessing, pps);

                // Use wireframe as our drawing mode
                directXDevice.RenderState.FillMode = FillMode.WireFrame;

                retVal = true;
            }
            catch (DirectXException e)
            {
                // Display our error message
                MessageBox.Show(e.ToString(), "Error");
            }

            return retVal;
        }

        #endregion

        #region Camera

        /// <summary>
        /// This function is responsible for setting up the camera.
        /// </summary>
        private void SetupCamera()
        {
            #region View Matrix

            // This is the camera location and is commonly referred to as the "eye point"
            Vector3 eyeVector = new Vector3(0.0f, 0.0f, -500.0f);

            // The Look At Vector defines the point that the camera is aimed at
            Vector3 lookAtVector = new Vector3(0, 0, 0);

            // The "up" direction is the positive direction on the y-axis
            Vector3 upVector = new Vector3(0, 1, 0);

            // Register our View Matrix so it can be used to place and aim our camera
            directXDevice.Transform.View = Matrix.LookAtLH(eyeVector,
                lookAtVector, upVector);

            #endregion

            #region Projection Matrix

            //45 degree field of view
            float fieldOfView = (float)Math.PI / 4.0f;

            //Typical aspect ratio is approximately 1.333...
            float aspectRatio = (float)ClientSize.Width / ClientSize.Height;

            // Register our Projection Matrix so it can be used for viewing items in
            // front of the camera
            directXDevice.Transform.Projection = Matrix.PerspectiveFovLH(fieldOfView,
                aspectRatio, 1.0f, 1000.0f);

            #endregion

            #region World Matrix

            // Create a scaling matrix
            Matrix scaleMatrix = Matrix.Scaling(0.5f, 0.5f, 0.5f);

            // World Matrix = Scaling Matrix
            directXDevice.Transform.World = scaleMatrix;

            #endregion

            #region Lighting

            // Enable/Disable lighting
            directXDevice.RenderState.Lighting = false;

            #endregion
        }

        #endregion
    }
}
于 2010-09-08T19:39:06.110 回答