コード例 #1
0
ファイル: ExtrusionMesh.cs プロジェクト: IanusInferus/cmdt
        ////////////////////////////////////////////////////////////////////////////////////
        #region 根据顶点集及其面索引创建Mesh,并优化之
        public void CreateExtrusionMesh(Device device)
        {
            int totalf = idxbuf.Length / 3;             //总三角面数
            int totalv = vexbuf.Length;                 //总顶点数

            //创建网格对象
            mesh = new Mesh(totalf, totalv, MeshFlags.Dynamic, CustomVertex.PositionNormalColored.Format, device);

            //设置mesh
            mesh.SetVertexBufferData(vexbuf, LockFlags.None);
            mesh.SetIndexBufferData(idxbuf, LockFlags.None);
            DEBUG_PrintMeshInfo("[Mesh] 没有优化");

            //优化顶点数量,删除多余顶点,只有几乎绝对重复的点才删除
            WeldEpsilons epsilon = new WeldEpsilons();

            epsilon.Diffuse  = 0.01F;
            epsilon.Position = 0.01F;
            epsilon.Normal   = 0.01F;
            mesh.WeldVertices(WeldEpsilonsFlags.WeldPartialMatches, epsilon, null, null);
            DEBUG_PrintMeshInfo("[Mesh] 顶点优化");

            //优化mesh,并由OptimizeInPlace自动计算SubSet个数
            int[] adjacency = new int[mesh.NumberFaces * 3];
            mesh.GenerateAdjacency(0.01F, adjacency);
            mesh.OptimizeInPlace(MeshFlags.OptimizeVertexCache | MeshFlags.OptimizeCompact, adjacency);

            //将mesh变成是writeonly的,加快效率!
            Mesh m = mesh.Clone(MeshFlags.WriteOnly, CustomVertex.PositionNormalColored.Format, device);

            mesh.Dispose();
            mesh = m;
        }
コード例 #2
0
        /// <summary>
        /// Vytvoreni progressive meshe
        /// </summary>
        /// <param name="rootFrame">rootframe animace</param>
        /// <returns>vztvoreni progressive mesh</returns>
        private ProgressiveMesh GetMesh(AnimationRootFrame rootFrame)
        {
            ProgressiveMesh      pm     = null;
            Frame                rf     = rootFrame.FrameHierarchy;
            List <MeshContainer> meshes = new List <MeshContainer>();

            getAnimationMesh(rf, meshes);
            anim.AnimationMeshContainer container = meshes[0] as anim.AnimationMeshContainer;

            int            use32Bit  = (int)(container.MeshData.Mesh.Options.Value & MeshFlags.Use32Bit);
            GraphicsStream adjacency = container.GetAdjacencyStream();//container.adjency;

            using (Mesh currentmesh = Mesh.Clean(CleanType.Simplification, container.MeshData.Mesh, adjacency, adjacency))
            {
                WeldEpsilons epsilons = new WeldEpsilons();
                currentmesh.WeldVertices(0, epsilons, adjacency, adjacency);
                currentmesh.Validate(adjacency);

                Mesh newmesh = currentmesh.Optimize(MeshFlags.OptimizeStripeReorder | MeshFlags.OptimizeAttributeSort, adjacency);
                using (newmesh = currentmesh.Clone(MeshFlags.Managed | (MeshFlags)use32Bit, GeneralObject.GeneralVertex.vertexElements, container.MeshData.Mesh.Device))
                {
                    newmesh.ComputeNormals();

                    pm = new ProgressiveMesh(newmesh, adjacency, null, 1, MeshFlags.SimplifyFace);
                }
            }

            return(pm);
        }
コード例 #3
0
ファイル: WallMesh.cs プロジェクト: IanusInferus/cmdt
        ////////////////////////////////////////////////////////////////////////////////////
        public void CreateWallMesh(Device device)
        {
            if (vexbuf == null)
            {
                Debug.WriteLine("[WallMesh] 空数据");                 //此时根本无需存在任何垂直面需要绘制
                mesh = null;
                return;
            }

            int totalf = vexbuf.Length / 4 * 2;             //三角面总数
            int totalv = vexbuf.Length;                     //顶点总数

            //创建网格对象
            mesh = new Mesh(totalf, totalv, MeshFlags.Dynamic, CustomVertex.PositionNormalColored.Format, device);

            //设置mesh
            mesh.SetVertexBufferData(vexbuf, LockFlags.None);
            mesh.SetIndexBufferData(idxbuf, LockFlags.None);
            DEBUG_PrintMeshInfo("[WallMesh] 没有优化");

            //优化顶点数量,删除多余顶点,只有几乎绝对重复的顶点才进行融接
            WeldEpsilons epsilon = new WeldEpsilons();

            epsilon.Diffuse  = 0.01F;
            epsilon.Position = 0.01F;
            epsilon.Normal   = 0.01F;
            mesh.WeldVertices(WeldEpsilonsFlags.WeldPartialMatches, epsilon, null, null);
            DEBUG_PrintMeshInfo("[WallMesh] 顶点优化");

            //针对cache命中率进行优化排序
            int[] adjacency = new int[mesh.NumberFaces * 3];
            mesh.GenerateAdjacency(0.01F, adjacency);
            mesh.OptimizeInPlace(MeshFlags.OptimizeVertexCache | MeshFlags.OptimizeCompact, adjacency);

            //将mesh变成是writeonly的,加快效率!
            Mesh m = mesh.Clone(MeshFlags.WriteOnly, CustomVertex.PositionNormalColored.Format, device);

            mesh.Dispose();
            mesh = m;
        }
コード例 #4
0
ファイル: Tela.cs プロジェクト: jairxpereira/gameprog
        } // initGfx()

        // ---]
        // [---
        private void gerarModeloSimplificado()
        {
            // Primeiro o objeto original é clonado
            mesh_simplificado = objeto3D.Clone(objeto3D.Options.Value,
                                               objeto3D.VertexFormat | VertexFormats.Normal, device);

            // Este conjunto de flags, WeldEpsilonsFlags, define opções de
            // soldagem. WeldPartialMatches solda os vértices que estão
            // dentro dos valores de tolerância definidos pela estrutura
            // WeldEpsilons; WeldAll solda os vértices se houver sobreposição
            // indicada pela informação de adjacências.
            WeldEpsilonsFlags wy_flags;

            wy_flags = WeldEpsilonsFlags.WeldPartialMatches | WeldEpsilonsFlags.WeldAll;

            // Produzimos uma estrutura WeldEpsilons que já é configurada
            // com valores de tolerâncias aceitáveis para os diversos
            // atributos do objeto 3d para o processo de soldagem.
            WeldEpsilons wy_tolerancias = new WeldEpsilons();

            mesh_simplificado.WeldVertices(wy_flags, wy_tolerancias, null, null);
        } // gerarModeloSimplificado()
コード例 #5
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);
        }
コード例 #6
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;
            }
        }
コード例 #7
0
ファイル: Lighting.cs プロジェクト: sjk7/DX90SDK
        /// <summary>
        /// The device exists, but may have just been Reset().  Resources in
        /// Pool.Default and any other device state that persists during
        /// rendering should be set here.  Render states, matrices, textures,
        /// etc., that don't change during rendering can be set once here to
        /// avoid redundant state setting during Render() or FrameMove().
        /// </summary>
        protected override void RestoreDeviceObjects(System.Object sender, System.EventArgs e)
        {
            MyVertex[] v;
            Mesh       pWallMeshTemp = null;

            // Create a square grid numberVertsX*numberVertsZ for rendering the wall
            pWallMeshTemp = new Mesh(numTriangles, numTriangles * 3,
                                     0, MyVertex.Format, device);

            // Fill in the grid vertex data
            v = (MyVertex[])pWallMeshTemp.LockVertexBuffer(typeof(MyVertex), 0, numTriangles * 3);
            float dX = 1.0f / (numberVertsX - 1);
            float dZ = 1.0f / (numberVertsZ - 1);
            uint  k  = 0;

            for (uint z = 0; z < (numberVertsZ - 1); z++)
            {
                for (uint x = 0; x < (numberVertsX - 1); x++)
                {
                    v[k].p = new Vector3(10 * x * dX, 0.0f, 10 * z * dZ);
                    v[k].n = new Vector3(0.0f, 1.0f, 0.0f);
                    k++;
                    v[k].p = new Vector3(10 * x * dX, 0.0f, 10 * (z + 1) * dZ);
                    v[k].n = new Vector3(0.0f, 1.0f, 0.0f);
                    k++;
                    v[k].p = new Vector3(10 * (x + 1) * dX, 0.0f, 10 * (z + 1) * dZ);
                    v[k].n = new Vector3(0.0f, 1.0f, 0.0f);
                    k++;
                    v[k].p = new Vector3(10 * x * dX, 0.0f, 10 * z * dZ);
                    v[k].n = new Vector3(0.0f, 1.0f, 0.0f);
                    k++;
                    v[k].p = new Vector3(10 * (x + 1) * dX, 0.0f, 10 * (z + 1) * dZ);
                    v[k].n = new Vector3(0.0f, 1.0f, 0.0f);
                    k++;
                    v[k].p = new Vector3(10 * (x + 1) * dX, 0.0f, 10 * z * dZ);
                    v[k].n = new Vector3(0.0f, 1.0f, 0.0f);
                    k++;
                }
            }
            pWallMeshTemp.UnlockVertexBuffer();

            // Fill in index data
            ushort[] pIndex;
            pIndex = (ushort[])pWallMeshTemp.LockIndexBuffer(typeof(ushort), 0, numTriangles * 3);
            for (ushort iIndex = 0; iIndex < numTriangles * 3; iIndex++)
            {
                pIndex[iIndex] = iIndex;
            }
            pWallMeshTemp.UnlockIndexBuffer();

            // Eliminate redundant vertices
            int[]        pdwAdjacency = new int[3 * numTriangles];
            WeldEpsilons we           = new WeldEpsilons();

            pWallMeshTemp.GenerateAdjacency(0.01f, pdwAdjacency);
            pWallMeshTemp.WeldVertices(WeldEpsilonsFlags.WeldAll, we, pdwAdjacency);

            // Optimize the mesh
            wallMesh = pWallMeshTemp.Optimize(MeshFlags.OptimizeCompact | MeshFlags.OptimizeVertexCache |
                                              MeshFlags.VbDynamic | MeshFlags.VbWriteOnly, pdwAdjacency);

            pWallMeshTemp = null;
            pdwAdjacency  = null;

            // Create sphere and cone meshes to represent the lights
            sphereMesh = Mesh.Sphere(device, 0.25f, 20, 20);
            coneMesh   = Mesh.Cylinder(device, 0.0f, 0.25f, 0.5f, 20, 20);

            // Set up a material
            Microsoft.DirectX.Direct3D.Material mtrl = GraphicsUtility.InitMaterial(System.Drawing.Color.White);
            device.Material = mtrl;

            // Set miscellaneous render states
            device.RenderState.DitherEnable   = false;
            device.RenderState.SpecularEnable = false;

            // Set the world matrix
            Matrix matIdentity = Matrix.Identity;

            device.SetTransform(TransformType.World, matIdentity);

            // Set the view matrix.
            Matrix  matView;
            Vector3 vFromPt   = new Vector3(-10, 10, -10);
            Vector3 vLookatPt = new Vector3(0.0f, 0.0f, 0.0f);
            Vector3 vUpVec    = new Vector3(0.0f, 1.0f, 0.0f);

            matView = Matrix.LookAtLH(vFromPt, vLookatPt, vUpVec);
            device.SetTransform(TransformType.View, matView);

            // Set the projection matrix
            Matrix matProj;
            float  fAspect = ((float)device.PresentationParameters.BackBufferWidth) / device.PresentationParameters.BackBufferHeight;

            matProj = Matrix.PerspectiveFovLH((float)Math.PI / 4, fAspect, 1.0f, 100.0f);
            device.SetTransform(TransformType.Projection, matProj);

            // Turn on lighting.
            device.RenderState.Lighting = true;

            // Enable ambient lighting to a dim, grey light, so objects that
            // are not lit by the other lights are not completely black
            device.RenderState.Ambient = System.Drawing.Color.Gray;

            // Set light #0 to be a simple, faint grey directional light so
            // the walls and floor are slightly different shades of grey
            device.Lights[0].Type      = LightType.Directional;
            device.Lights[0].Direction = new Vector3(0.3f, -0.5f, 0.2f);
            device.Lights[0].Diffuse   = System.Drawing.Color.FromArgb(64, 64, 64);
            device.Lights[0].Commit();

            // Set light #1 to be a simple, bright directional light to use
            // on the mesh representing light #2
            device.Lights[1].Type      = LightType.Directional;
            device.Lights[1].Direction = new Vector3(0.5f, -0.5f, 0.5f);
            device.Lights[1].Diffuse   = System.Drawing.Color.White;
            device.Lights[1].Commit();

            // Light #2 will be the light used to light the floor and walls.  It will
            // be set up in FrameMove() since it changes every frame.
        }
コード例 #8
0
        /// <summary>
        /// Generate normals and tangents if not present and convert into TangentVertex format for shaders.
        /// </summary>
        /// <param name="device">The <see cref="Device"/> containing the mesh</param>
        /// <param name="mesh">The mesh to be manipulated</param>
        /// <param name="weldVertexes">Weld vertexes before generating tangents.
        /// Useful for organic objects, stones, trees, etc. (anything with a lot of round surfaces).
        /// If a lot of single faces are not connected on the texture (e.g. rockets, buildings, etc.) do not use.</param>
        public static void GenerateNormalsAndTangents(Device device, ref Mesh mesh, bool weldVertexes)
        {
            #region Sanity checks
            if (device == null)
            {
                throw new ArgumentNullException(nameof(device));
            }
            if (mesh == null)
            {
                throw new ArgumentNullException(nameof(mesh));
            }
            #endregion

            bool hadNormals, hadTangents;
            if (!ExpandDeclaration(device, ref mesh, out hadNormals, out hadTangents))
            {
                return;
            }
            var decl = mesh.GetDeclaration();

            #region Check existing info
            bool gotMilkErmTexCoords = false;
            bool gotValidNormals     = true;
            bool gotValidTangents    = true;
            var  vertexes            = BufferHelper.ReadVertexBuffer <PositionNormalBinormalTangentTextured>(mesh);

            // Check all vertexes
            for (int num = 0; num < vertexes.Length; num++)
            {
                // We need at least 1 texture coordinate different from (0, 0)
                if (vertexes[num].Tu != 0.0f ||
                    vertexes[num].Tv != 0.0f)
                {
                    gotMilkErmTexCoords = true;
                }

                // All normals and tangents must be valid, otherwise generate them below
                if (vertexes[num].Normal == default(Vector3))
                {
                    gotValidNormals = false;
                }
                if (vertexes[num].Tangent == default(Vector3))
                {
                    gotValidTangents = false;
                }

                // If we found valid texture coordinates and no normals or tangents,
                // there isn't anything left to check here
                if (gotMilkErmTexCoords && !gotValidNormals && !gotValidTangents)
                {
                    break;
                }
            }

            // If declaration had normals, but we found no valid normals,
            // set hadNormals to false and generate valid normals (see below)
            if (!gotValidNormals)
            {
                hadNormals = false;
            }
            // Same check for tangents
            if (!gotValidTangents)
            {
                hadTangents = false;
            }

            // Generate dummy texture coordinates
            if (!gotMilkErmTexCoords)
            {
                for (int num = 0; num < vertexes.Length; num++)
                {
                    vertexes[num].Tu = -0.75f + vertexes[num].Position.X / 2.0f;
                    vertexes[num].Tv = +0.75f - vertexes[num].Position.Y / 2.0f;
                }
            }
            BufferHelper.WriteVertexBuffer(mesh, vertexes);
            #endregion

            if (!hadNormals)
            {
                using (new TimedLogEvent("Computed normals"))
                    mesh.ComputeNormals();
            }

            if (weldVertexes)
            {
                // Reduce amount of vertexes
                var weldEpsilons = new WeldEpsilons {
                    Position = 0.0001f, Normal = 0.0001f
                };
                mesh.WeldVertices(WeldFlags.WeldPartialMatches, weldEpsilons);

                if (!hadTangents)
                {
                    #region Compute tangents
                    using (new TimedLogEvent("Computed tangents"))
                    {
                        // If the vertexes for a smoothend point exist several times the
                        // DirectX ComputeTangent method is not able to treat them all the
                        // same way.
                        // To circumvent this, we collapse all vertexes in a cloned mesh
                        // even if the texture coordinates don't fit. Then we copy the
                        // generated tangents back to the original mesh vertexes (duplicating
                        // the tangents for vertexes at the same point with the same normals
                        // if required). This happens usually with models exported from 3DSMax.

                        // Clone mesh just for tangent generation
                        Mesh dummyTangentGenerationMesh = mesh.Clone(device, mesh.CreationOptions, decl);

                        // Reuse weldEpsilons, just change the TextureCoordinates, which we don't care about anymore
                        weldEpsilons.TextureCoordinate1 = 1;
                        weldEpsilons.TextureCoordinate2 = 1;
                        weldEpsilons.TextureCoordinate3 = 1;
                        weldEpsilons.TextureCoordinate4 = 1;
                        weldEpsilons.TextureCoordinate5 = 1;
                        weldEpsilons.TextureCoordinate6 = 1;
                        weldEpsilons.TextureCoordinate7 = 1;
                        weldEpsilons.TextureCoordinate8 = 1;
                        // Rest of the weldEpsilons values can stay 0, we don't use them
                        dummyTangentGenerationMesh.WeldVertices(WeldFlags.WeldPartialMatches, weldEpsilons);

                        // Compute tangents
                        if (!CompareDecl(PositionNormalMultiTextured.GetVertexElements(), decl))
                        {
                            dummyTangentGenerationMesh.ComputeTangent(0, 0, 0, false);
                        }
                        var tangentVertexes = BufferHelper.ReadVertexBuffer <PositionNormalBinormalTangentTextured>(dummyTangentGenerationMesh);
                        dummyTangentGenerationMesh.Dispose();

                        // Copy generated tangents back
                        vertexes = BufferHelper.ReadVertexBuffer <PositionNormalBinormalTangentTextured>(mesh);
                        for (int num = 0; num < vertexes.Length; num++)
                        {
                            // Search for tangent vertex with the exact same position and normal.
                            for (int tangentVertexNum = 0; tangentVertexNum < tangentVertexes.Length; tangentVertexNum++)
                            {
                                if (vertexes[num].Position == tangentVertexes[tangentVertexNum].Position && vertexes[num].Normal == tangentVertexes[tangentVertexNum].Normal)
                                {
                                    // Copy the tangent over
                                    vertexes[num].Tangent = tangentVertexes[tangentVertexNum].Tangent;
                                    // No more checks required, proceed with next vertex
                                    break;
                                }
                            }
                        }
                        BufferHelper.WriteVertexBuffer(mesh, vertexes);
                    }
                    #endregion
                }
            }
            else
            {
                if (!hadTangents && CompareDecl(PositionNormalMultiTextured.GetVertexElements(), decl))
                {
                    using (new TimedLogEvent("Computed tangents"))
                        mesh.ComputeTangent(0, 0, D3DX.Default, false);
                }
            }

            Optimize(mesh);
        }
コード例 #9
0
        public Model(string name, string meshFile, Vector3 offset, Attitude adjust) : base(name)
        {
            Mesh         pTempMesh = null;
            WeldEpsilons Epsilons  = new WeldEpsilons();

            Vector3 objectCenter;                    // Center of bounding sphere of object

            m_vOffset        = offset;
            m_AttitudeOffset = adjust;
            m_vPosition.X    = 100.0f;
            m_vPosition.Z    = 100.0f;
            ExtendedMaterial[] materials = null;

            try
            {
                // Load the m_mesh from the specified file
                m_mesh = Mesh.FromFile(meshFile, MeshFlags.SystemMemory, CGameEngine.Device3D, out m_adj, out materials);
                // Lock the vertex buffer to generate a simple bounding sphere
                VertexBuffer   vb         = m_mesh.VertexBuffer;
                GraphicsStream vertexData = vb.Lock(0, 0, LockFlags.NoSystemLock);
                m_fRadius = Geometry.ComputeBoundingSphere(vertexData, m_mesh.NumberVertices, m_mesh.VertexFormat, out objectCenter);
                Geometry.ComputeBoundingBox(vertexData, m_mesh.NumberVertices, m_mesh.VertexFormat, out m_NegativeExtents, out m_PositiveExtents);
                vb.Unlock();
                vb.Dispose();

                m_vOffset.Y = -m_NegativeExtents.Y;

                m_Corners[0].X = m_NegativeExtents.X;
                m_Corners[0].Y = m_NegativeExtents.Y + m_vOffset.Y;
                m_Corners[0].Z = m_NegativeExtents.Z;

                m_Corners[1].X = m_PositiveExtents.X;
                m_Corners[1].Y = m_NegativeExtents.Y + m_vOffset.Y;
                m_Corners[1].Z = m_NegativeExtents.Z;

                m_Corners[2].X = m_NegativeExtents.X;
                m_Corners[2].Y = m_PositiveExtents.Y + m_vOffset.Y;
                m_Corners[2].Z = m_NegativeExtents.Z;

                m_Corners[3].X = m_PositiveExtents.X;
                m_Corners[3].Y = m_PositiveExtents.Y + m_vOffset.Y;
                m_Corners[3].Z = m_NegativeExtents.Z;

                m_Corners[4].X = m_NegativeExtents.X;
                m_Corners[4].Y = m_NegativeExtents.Y + m_vOffset.Y;
                m_Corners[4].Z = m_PositiveExtents.Z;

                m_Corners[5].X = m_PositiveExtents.X;
                m_Corners[5].Y = m_NegativeExtents.Y + m_vOffset.Y;
                m_Corners[5].Z = m_PositiveExtents.Z;

                m_Corners[6].X = m_PositiveExtents.X;
                m_Corners[6].Y = m_PositiveExtents.Y + m_vOffset.Y;
                m_Corners[6].Z = m_PositiveExtents.Z;

                m_Corners[7].X = m_PositiveExtents.X;
                m_Corners[7].Y = m_PositiveExtents.Y + m_vOffset.Y;
                m_Corners[7].Z = m_PositiveExtents.Z;

//					Console.AddLine("Max extents " + m_PositiveExtents);
//					Console.AddLine("Min extents " + m_NegativeExtents);


                // perform simple cleansing operations on m_mesh
                pTempMesh = Mesh.Clean(m_mesh, m_adj, m_adj);
                m_mesh.Dispose();

                m_mesh = 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 m_mesh using all epsilons of 0.0f.  A small epsilon like 1e-6 works well too
                m_mesh.WeldVertices(0, Epsilons, m_adj, m_adj);
                // verify validity of m_mesh for simplification
                m_mesh.Validate(m_adj);

                CreateLod();
            }
            catch (DirectXException d3de)
            {
                Console.AddLine("Unable to load mesh " + meshFile);
                Console.AddLine(d3de.ErrorString);
            }
            catch (Exception e)
            {
                Console.AddLine("Unable to load mesh " + meshFile);
                Console.AddLine(e.Message);
            }

            if (m_meshTextures == null && materials != null)
            {
                // We need to extract the material properties and texture names
                m_meshTextures  = new Texture[materials.Length];
                m_meshMaterials = new Material[materials.Length];
                for (int i = 0; i < materials.Length; i++)
                {
                    m_meshMaterials[i] = materials[i].Material3D;
                    // Set the ambient color for the material (D3DX does not do this)
                    m_meshMaterials[i].Ambient = m_meshMaterials[i].Diffuse;

                    // Create the texture
                    try
                    {
                        if (materials[i].TextureFilename != null)
                        {
                            m_meshTextures[i] = TextureLoader.FromFile(CGameEngine.Device3D, @"..\..\Resources\" + materials[i].TextureFilename);
                        }
                    }
                    catch (DirectXException d3de)
                    {
                        Console.AddLine("Unable to load texture " + materials[i].TextureFilename);
                        Console.AddLine(d3de.ErrorString);
                    }
                    catch (Exception e)
                    {
                        Console.AddLine("Unable to load texture " + materials[i].TextureFilename);
                        Console.AddLine(e.Message);
                    }
                }
            }
        }
コード例 #10
0
        public MeshObject(string fileName, Vector3 offset, Attitude adjust) : base()
        {
            _levelsOfDetail        = 1;
            _maxLevelOfDetailRange = 1.0f;
            _positiveExtents       = new Vector3(-1.0f, -1.0f, -1.0f);
            _negativeExtents       = new Vector3(1.0f, 1.0f, 1.0f);
            _corners = new Vector3[8];

            Mesh         tempMesh = null;
            WeldEpsilons epsilons = new WeldEpsilons();

            Vector3 center;

            _offset         = offset;
            _attitudeOffset = adjust;
            Position        = new Vector3(100.0f, 100.0f, 0.0f);

            MaterialList materials = null;

            _mesh = new Mesh(GameEngine.Device, fileName, MeshFlags.SystemMemory,
                             _adjacency, materials, new EffectInstanceList());

            VertexBuffer vertexBuffer = _mesh.VertexBuffer;

            GraphicsBuffer vertexData = vertexBuffer.Lock(0, 0, LockFlags.NoSystemLock);

            BoundingRadius = Geometry.ComputeBoundingSphere(vertexData,
                                                            _mesh.NumberVertices, _mesh.VertexFormat).Radius;

            BoundingBox box = Geometry.ComputeBoundingBox(vertexData, _mesh.NumberVertices, _mesh.VertexFormat);


            vertexBuffer.Unlock();
            vertexBuffer.Dispose();

            //calculate the corners of the bounding box based on the extents obtained
            //from the mesh.
            _offset.Y = -_negativeExtents.Y;

            _corners[0].X = _negativeExtents.X;
            _corners[0].Y = _negativeExtents.Y + _offset.Y;
            _corners[0].Z = _negativeExtents.Z;

            _corners[1].X = _positiveExtents.X;
            _corners[1].Y = _negativeExtents.Y + _offset.Y;
            _corners[1].Z = _negativeExtents.Z;

            _corners[2].X = _negativeExtents.X;
            _corners[2].Y = _positiveExtents.Y + _offset.Y;
            _corners[2].Z = _negativeExtents.Z;

            _corners[3].X = _positiveExtents.X;
            _corners[3].Y = _positiveExtents.Y + _offset.Y;
            _corners[3].Z = _negativeExtents.Z;

            _corners[4].X = _negativeExtents.X;
            _corners[4].Y = _negativeExtents.Y;
            _corners[4].Z = _positiveExtents.Z;

            _corners[5].X = _positiveExtents.X;
            _corners[5].Y = _negativeExtents.Y + _offset.Y;
            _corners[5].Z = _positiveExtents.Z;

            _corners[6].X = _positiveExtents.X;
            _corners[6].Y = _positiveExtents.Y + _offset.Y;
            _corners[6].Z = _positiveExtents.Z;

            //TODO: IS THIS CORRECT?
            _corners[7].X = _positiveExtents.X;
            _corners[7].Y = _positiveExtents.Y + _offset.Y;
            _corners[7].Z = _positiveExtents.Z;

            tempMesh = Mesh.Clean(CleanType.BackFacing, _mesh, _adjacency, _adjacency);
            _mesh.Dispose();
            _mesh = tempMesh;

            _mesh.WeldVertices(0, epsilons, _adjacency);
            _mesh.Validate(_adjacency);

            //CreateLevelOfDetail();

            if (_meshTextures == null && materials != null)
            {
                _meshTextures  = new Texture[materials.Count];
                _meshMaterials = new Material[materials.Count];

                for (int i = 0; i < materials.Count; i++)
                {
                    _meshMaterials[i] = materials[i].Material;
                    _meshMaterials[i].AmbientColor = _meshMaterials[i].DiffuseColor;

                    if (materials[i].TextureFileName != null)
                    {
                        _meshTextures[i] = new Texture(GameEngine.Device, materials[i].TextureFileName);
                    }
                }
            }
        }
コード例 #11
0
        /// <summary>
        /// Nacteni meshe a textur a vytvoreni progressive meshe
        /// </summary>
        /// <param name="loaded">Entita do ktere chceme pridat mesh a texturz</param>
        /// <param name="data">pole obsahujuci nazev meshe a textur</param>
        /// <param name="name">nazev objektu</param>
        /// <returns>Entita s meshem a texturami</returns>
        private Entity LoadMeshFromFile(Entity loaded, string[] data, string name)
        {
            string[] textureUrl;

            string objectUrl = data[0];
            int    p         = FindMesh(objectUrl);

            if (p != -1)
            {
                loaded.AddParametr(new Parametr("Objekt[]", data[1], meshInf[p].textures));
                loaded.AddParametr(new Parametr("Microsoft.DirectX.Direct3D.ProgressiveMesh", name, meshInf[p].pMesh));
                loaded.AddParametr(new Parametr("Objekt[]", "SpecialTextureUrl", meshInf[p].texturesUrl));
                return(loaded);
            }
            if (data.Length < 2)
            {
                throw new Exception("Chyba pri nacitani nespravny pocet parametru");
            }

            Texture[]       textures;
            ProgressiveMesh currentLoadedMesh;

            Matrix localTransformation = Matrix.Identity;

            GraphicsStream adjency = null;

            ExtendedMaterial[] mat = null;

            using (Mesh mesh = Mesh.FromFile(objectUrl, MeshFlags.Managed, dev, out adjency, out mat))
            {
                #region Texture Loading

                textures   = new Texture[mat.Length];
                textureUrl = new string[mat.Length];

                string pathname = Path.GetDirectoryName(objectUrl) + @"\";

                for (int i = 0; i < mat.Length; i++)
                {
                    if (mat[i].TextureFilename == null)
                    {
                        continue;
                    }



                    string abspath = (pathname + mat[i].TextureFilename);
                    textureUrl[i] = abspath;
                    string path = mat[i].TextureFilename;

                    bool createtexture = true;
                    for (int t = 0; t < i; t++)
                    {
                        if (mat[t].TextureFilename == mat[i].TextureFilename)
                        {
                            textures[i]   = textures[t];
                            createtexture = false;
                            break;
                        }
                    }

                    if (createtexture)
                    {
                        if (File.Exists(path))
                        {
                            textures[i] = TextureLoader.FromFile(dev, path, 0, 0, 0, Usage.None, Format.R8G8B8, Pool.Managed, Filter.Linear, Filter.Linear, 0);
                        }
                        else if (File.Exists(abspath))
                        {
                            textures[i] = TextureLoader.FromFile(dev, abspath, 0, 0, 0, Usage.None, Format.R8G8B8, Pool.Managed, Filter.Linear, Filter.Linear, 0);
                        }
                    }
                }

                loaded.AddParametr(new Parametr("Objekt[]", "SpecialTextureUrl", textureUrl));
                #endregion


                #region Mesh clean, optimize and compute normals/tangents

                int use32Bit = (int)(mesh.Options.Value & MeshFlags.Use32Bit);

                using (Mesh currentmesh = Mesh.Clean(CleanType.Simplification, mesh, adjency, adjency))
                {
                    WeldEpsilons epsilons = new WeldEpsilons();
                    currentmesh.WeldVertices(0, epsilons, adjency, adjency);
                    currentmesh.Validate(adjency);

                    Mesh newmesh = currentmesh.Optimize(MeshFlags.OptimizeStripeReorder | MeshFlags.OptimizeAttributeSort, adjency);
                    using (newmesh = currentmesh.Clone(MeshFlags.Managed | (MeshFlags)use32Bit, GeneralObject.GeneralVertex.vertexElements, dev))
                    {
                        newmesh.ComputeNormals();

                        ProgressiveMesh pm = new ProgressiveMesh(newmesh, adjency, null, 1, MeshFlags.SimplifyFace);

                        currentLoadedMesh             = pm;
                        currentLoadedMesh.NumberFaces = currentLoadedMesh.MaxFaces;
                    }
                }
                #endregion
            }
            meshInf.Add(new MeshInformation(currentLoadedMesh, objectUrl, textures, textureUrl));

            loaded.AddParametr(new Parametr("Objekt[]", data[1], textures));
            loaded.AddParametr(new Parametr("Microsoft.DirectX.Direct3D.ProgressiveMesh", name, currentLoadedMesh));



            return(loaded);
        }