Ejemplo n.º 1
0
        private void CreateLod()
        {
            ProgressiveMesh pPMesh           = null;
            int             cVerticesMin     = 0;
            int             cVerticesMax     = 0;
            int             cVerticesPerMesh = 0;

            pPMesh = new ProgressiveMesh(m_mesh, m_adj, null, 1, MeshFlags.SimplifyVertex);

            cVerticesMin = pPMesh.MinVertices;
            cVerticesMax = pPMesh.MaxVertices;

            if (m_pMeshes != null)
            {
                for (int iPMesh = 0; iPMesh < m_pMeshes.Length; iPMesh++)
                {
                    m_pMeshes[iPMesh].Dispose();
                }
            }

            cVerticesPerMesh = (cVerticesMax - cVerticesMin) / m_nNumLOD;
            m_pMeshes        = new ProgressiveMesh[m_nNumLOD];

            // clone all the separate m_pMeshes
            for (int iPMesh = 0; iPMesh < m_pMeshes.Length; iPMesh++)
            {
                m_pMeshes[m_pMeshes.Length - 1 - iPMesh] = pPMesh.Clone(MeshFlags.Managed | MeshFlags.VbShare, pPMesh.VertexFormat, CGameEngine.Device3D);
                // trim to appropriate space
                if (m_nNumLOD > 1)
                {
                    m_pMeshes[m_pMeshes.Length - 1 - iPMesh].TrimByVertices(cVerticesMin + cVerticesPerMesh * iPMesh, cVerticesMin + cVerticesPerMesh * (iPMesh + 1));
                }

                m_pMeshes[m_pMeshes.Length - 1 - iPMesh].OptimizeBaseLevelOfDetail(MeshFlags.OptimizeVertexCache);
            }
            m_currentPmesh = 0;
            m_pMeshes[m_currentPmesh].NumberVertices = cVerticesMax;
            pPMesh.Dispose();
        }
Ejemplo n.º 2
0
        /// <summary>
        /// This event will be fired immediately after the Direct3D device has been
        /// created, which will happen during application initialization and windowed/full screen
        /// toggles. This is the best location to create Pool.Managed resources since these
        /// resources need to be reloaded whenever the device is destroyed. Resources created
        /// here should be released in the Disposing event.
        /// </summary>
        private void OnCreateDevice(object sender, DeviceEventArgs e)
        {
            // Initialize the stats font
            statsFont = ResourceCache.GetGlobalInstance().CreateFont(e.Device, 15, 0, FontWeight.Bold, 1, false, CharacterSet.Default,
                                                                     Precision.Default, FontQuality.Default, PitchAndFamily.FamilyDoNotCare | PitchAndFamily.DefaultPitch
                                                                     , "Arial");

            // Define DEBUG_VS and/or DEBUG_PS to debug vertex and/or pixel shaders with the
            // shader debugger. Debugging vertex shaders requires either REF or software vertex
            // processing, and debugging pixel shaders requires REF.  The
            // ShaderFlags.Force*SoftwareNoOptimizations flag improves the debug experience in the
            // shader debugger.  It enables source level debugging, prevents instruction
            // reordering, prevents dead code elimination, and forces the compiler to compile
            // against the next higher available software target, which ensures that the
            // unoptimized shaders do not exceed the shader model limitations.  Setting these
            // flags will cause slower rendering since the shaders will be unoptimized and
            // forced into software.  See the DirectX documentation for more information about
            // using the shader debugger.
            ShaderFlags shaderFlags = ShaderFlags.None;

#if (DEBUG_VS)
            shaderFlags |= ShaderFlags.ForceVertexShaderSoftwareNoOptimizations;
#endif
#if (DEBUG_PS)
            shaderFlags |= ShaderFlags.ForcePixelShaderSoftwareNoOptimizations;
#endif
            // Read the D3DX effect file
            string path = Utility.FindMediaFile("ProgressiveMesh.fx");
            effect = ResourceCache.GetGlobalInstance().CreateEffectFromFile(e.Device,
                                                                            path, null, null, shaderFlags, null);

            // Set the technique now, it will never be updated
            effect.Technique = "RenderScene";

            // Load the mesh
            GraphicsStream     adjacencyBuffer = null;
            ExtendedMaterial[] materials       = null;

            // Find the mesh
            path = Utility.FindMediaFile("dwarf\\dwarf.x");

            // Change the current directory to the mesh's directory so we can
            // find the textures.
            string             currentFolder = System.IO.Directory.GetCurrentDirectory();
            System.IO.FileInfo info          = new System.IO.FileInfo(path);
            System.IO.Directory.SetCurrentDirectory(info.Directory.FullName);

            using (Mesh originalMesh = Mesh.FromFile(path, MeshFlags.Managed, e.Device,
                                                     out adjacencyBuffer, out materials))
            {
                int use32Bit = (int)(originalMesh.Options.Value & MeshFlags.Use32Bit);

                // Perform simple cleansing operations on mesh
                using (Mesh mesh = Mesh.Clean(CleanType.Simplification, originalMesh, adjacencyBuffer, adjacencyBuffer))
                {
                    // Perform a weld to try and remove excess vertices.
                    // Weld the mesh using all epsilons of 0.0f.  A small epsilon like 1e-6 works well too
                    WeldEpsilons epsilons = new WeldEpsilons();
                    mesh.WeldVertices(0, epsilons, adjacencyBuffer, adjacencyBuffer);

                    // Verify validity of mesh for simplification
                    mesh.Validate(adjacencyBuffer);

                    // Allocate a material/texture arrays
                    meshMaterials = new Material[materials.Length];
                    meshTextures  = new Texture[materials.Length];

                    // Copy the materials and load the textures
                    for (int i = 0; i < meshMaterials.Length; i++)
                    {
                        meshMaterials[i] = materials[i].Material3D;
                        meshMaterials[i].AmbientColor = meshMaterials[i].DiffuseColor;

                        if ((materials[i].TextureFilename != null) && (materials[i].TextureFilename.Length > 0))
                        {
                            // Create the texture
                            meshTextures[i] = ResourceCache.GetGlobalInstance().CreateTextureFromFile(e.Device, materials[i].TextureFilename);
                        }
                    }

                    // Find the mesh's center, then generate a centering matrix
                    using (VertexBuffer vb = mesh.VertexBuffer)
                    {
                        using (GraphicsStream stm = vb.Lock(0, 0, LockFlags.NoSystemLock))
                        {
                            try
                            {
                                objectRadius = Geometry.ComputeBoundingSphere(stm,
                                                                              mesh.NumberVertices, mesh.VertexFormat, out objectCenter);

                                worldCenter = Matrix.Translation(-objectCenter);
                                float scaleFactor = 2.0f / objectRadius;
                                worldCenter *= Matrix.Scaling(scaleFactor, scaleFactor, scaleFactor);
                            }
                            finally
                            {
                                vb.Unlock();
                            }
                        }
                    }

                    // If the mesh is missing normals, generate them.
                    Mesh currentMesh = mesh;
                    if ((mesh.VertexFormat & VertexFormats.Normal) == 0)
                    {
                        currentMesh = mesh.Clone(MeshFlags.Managed | (MeshFlags)use32Bit,
                                                 mesh.VertexFormat | VertexFormats.Normal, e.Device);

                        // Compute normals now
                        currentMesh.ComputeNormals();
                    }

                    using (currentMesh)
                    {
                        // Generate progressive meshes
                        using (ProgressiveMesh pMesh = new ProgressiveMesh(currentMesh, adjacencyBuffer, null, 1, MeshFlags.SimplifyVertex))
                        {
                            int minVerts     = pMesh.MinVertices;
                            int maxVerts     = pMesh.MaxVertices;
                            int vertsPerMesh = (maxVerts - minVerts + 10) / 10;

                            // How many meshes should be in the array
                            int numMeshes = Math.Max(1, (int)Math.Ceiling((maxVerts - minVerts + 1) / (float)vertsPerMesh));
                            meshes = new ProgressiveMesh[numMeshes];

                            // Clone full sized pmesh
                            fullMesh = pMesh.Clone(MeshFlags.Managed | MeshFlags.VbShare, pMesh.VertexFormat, e.Device);

                            // Clone all the separate pmeshes
                            for (int iMesh = 0; iMesh < numMeshes; iMesh++)
                            {
                                meshes[iMesh] = pMesh.Clone(MeshFlags.Managed | MeshFlags.VbShare, pMesh.VertexFormat, e.Device);

                                // Trim to appropriate space
                                meshes[iMesh].TrimByVertices(minVerts + vertsPerMesh * iMesh, minVerts + vertsPerMesh * (iMesh + 1));
                                meshes[iMesh].OptimizeBaseLevelOfDetail(MeshFlags.OptimizeVertexCache);
                            }

                            // Set the current to be max vertices
                            currentMeshIndex = numMeshes - 1;
                            meshes[currentMeshIndex].NumberVertices = maxVerts;
                            fullMesh.NumberVertices = maxVerts;

                            // Set up the slider to reflect the vertices range the mesh has
                            sampleUi.GetSlider(Detail).SetRange(meshes[0].MinVertices,
                                                                meshes[meshes.Length - 1].MaxVertices);
                            sampleUi.GetSlider(Detail).Value = (meshes[currentMeshIndex] as BaseMesh).NumberVertices;
                        }
                    }
                }
            }

            // Restore the original folder
            System.IO.Directory.SetCurrentDirectory(currentFolder);
            // Setup the camera's view parameters
            camera.SetViewParameters(new Vector3(0.0f, 0.0f, -5.0f), Vector3.Empty);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// The device has been created.  Resources that are not lost on
        /// Reset() can be created here -- resources in Pool.Managed,
        /// Pool.Scratch, or Pool.SystemMemory.  Image surfaces created via
        /// CreateImageSurface are never lost and can be created here.  Vertex
        /// shaders and pixel shaders can also be created here as they are not
        /// lost on Reset().
        /// </summary>
        protected override void InitializeDeviceObjects()
        {
            // Initialize the font's internal textures
            font.InitializeDeviceObjects(device);

            string         path      = DXUtil.FindMediaFile(initialDirectory, meshFilename);
            Mesh           pMesh     = null;
            Mesh           pTempMesh = null;
            GraphicsStream adj       = null;

            ExtendedMaterial[] mtrl = null;
            MeshFlags          i32BitFlag;
            WeldEpsilons       Epsilons = new WeldEpsilons();
            ProgressiveMesh    pPMesh   = null;
            int cVerticesMin            = 0;
            int cVerticesMax            = 0;
            int cVerticesPerMesh        = 0;

            try
            {
                // Load the mesh from the specified file
                pMesh      = Mesh.FromFile(path, MeshFlags.Managed, device, out adj, out mtrl);
                i32BitFlag = pMesh.Options.Use32Bit ? MeshFlags.Use32Bit : 0;

                // perform simple cleansing operations on mesh
                pTempMesh = Mesh.Clean(pMesh, adj, adj);
                pMesh.Dispose();
                pMesh = pTempMesh;

                //  Perform a weld to try and remove excess vertices like the model bigship1.x in the DX9.0 SDK (current model is fixed)
                //    Weld the mesh using all epsilons of 0.0f.  A small epsilon like 1e-6 works well too
                pMesh.WeldVertices(0, Epsilons, adj, adj);
                // verify validity of mesh for simplification
                pMesh.Validate(adj);

                meshMaterials = new Direct3D.Material[mtrl.Length];
                meshTextures  = new Texture[mtrl.Length];
                for (int i = 0; i < mtrl.Length; i++)
                {
                    meshMaterials[i]         = mtrl[i].Material3D;
                    meshMaterials[i].Ambient = meshMaterials[i].Diffuse;
                    if ((mtrl[i].TextureFilename != null) && (mtrl[i].TextureFilename != ""))
                    {
                        path = DXUtil.FindMediaFile(initialDirectory, mtrl[i].TextureFilename);
                        // Find the path to the texture and create that texture
                        try
                        {
                            meshTextures[i] = TextureLoader.FromFile(device, path);
                        }
                        catch
                        {
                            meshTextures[i] = null;
                        }
                    }
                }

                // Lock the vertex buffer to generate a simple bounding sphere
                VertexBuffer   vb         = pMesh.VertexBuffer;
                GraphicsStream vertexData = vb.Lock(0, 0, LockFlags.NoSystemLock);
                objectRadius = Geometry.ComputeBoundingSphere(vertexData, pMesh.NumberVertices, pMesh.VertexFormat, out objectCenter);
                vb.Unlock();
                vb.Dispose();
                if (meshMaterials.Length == 0)
                {
                    throw new Exception();
                }

                if ((pMesh.VertexFormat & VertexFormats.Normal) == 0)
                {
                    pTempMesh = pMesh.Clone(i32BitFlag | MeshFlags.Managed, pMesh.VertexFormat | VertexFormats.Normal, device);
                    pTempMesh.ComputeNormals();
                    pMesh.Dispose();
                    pMesh = pTempMesh;
                }
                pPMesh = new ProgressiveMesh(pMesh, adj, null, 1, MeshFlags.SimplifyVertex);

                cVerticesMin = pPMesh.MinVertices;
                cVerticesMax = pPMesh.MaxVertices;

                cVerticesPerMesh = (cVerticesMax - cVerticesMin) / 10;
                pmeshes          = new ProgressiveMesh[(int)Math.Max(1, Math.Ceiling((cVerticesMax - cVerticesMin) / (float)cVerticesPerMesh))];

                // clone full size pmesh
                fullPmesh = pPMesh.Clone(MeshFlags.Managed | MeshFlags.VbShare, pPMesh.VertexFormat, device);

                // clone all the separate pmeshes
                for (int iPMesh = 0; iPMesh < pmeshes.Length; iPMesh++)
                {
                    pmeshes[iPMesh] = pPMesh.Clone(MeshFlags.Managed | MeshFlags.VbShare, pPMesh.VertexFormat, device);
                    // trim to appropriate space
                    pmeshes[iPMesh].TrimByVertices(cVerticesMin + cVerticesPerMesh * iPMesh, cVerticesMin + cVerticesPerMesh * (iPMesh + 1));

                    pmeshes[iPMesh].OptimizeBaseLevelOfDetail(MeshFlags.OptimizeVertexCache);
                }
                currentPmesh = pmeshes.Length - 1;
                pmeshes[currentPmesh].NumberVertices = cVerticesMax;
                fullPmesh.NumberVertices             = cVerticesMax;
                pPMesh.Dispose();
            }
            catch
            {
                // hide error so that device changes will not cause exit, shows blank screen instead
                return;
            }
        }