/// <summary> /// This callback function will be called immediately after the Direct3D device has /// been destroyed, which generally happens as a result of application termination or /// windowed/full screen toggles. Resources created in the OnCreateDevice callback /// should be released here, which generally includes all Pool.Managed resources. /// </summary> private void OnDestroyDevice(object sender, EventArgs e) { meshTextures = null; meshMaterials = null; if (fullMesh != null) { fullMesh.Dispose(); } if ((meshes != null) && (meshes.Length > 0)) { for (int i = 0; i < meshes.Length; i++) { if (meshes[i] != null) { meshes[i].Dispose(); } } } meshes = null; }
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(); }
/// <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; } }