コード例 #1
0
        /// <summary>
        /// Expands the declaration of a mesh to include tangent and binormal information
        /// </summary>
        /// <param name="device">The <see cref="Device"/> containing the mesh</param>
        /// <param name="mesh">The mesh to be manipulated</param>
        /// <param name="hadNormals">Did the original declaration already contain normals?</param>
        /// <param name="hadTangents">Did the original declaration already contain tangents?</param>
        /// <returns><c>true</c> if the mesh declaration was expanded, <c>false</c> if the declaration didn't need to be changed</returns>
        private static bool ExpandDeclaration(Device device, ref Mesh mesh, out bool hadNormals, out bool hadTangents)
        {
            #region Sanity checks
            if (device == null)
            {
                throw new ArgumentNullException(nameof(device));
            }
            if (mesh == null)
            {
                throw new ArgumentNullException(nameof(mesh));
            }
            #endregion

            // Check if vertex declaration of mesh already is already ok
            var decl = mesh.GetDeclaration();
            if (CompareDecl(PositionNormalBinormalTangentTextured.GetVertexElements(), decl) ||
                CompareDecl(PositionNormalMultiTextured.GetVertexElements(), decl))
            {
                hadNormals  = true;
                hadTangents = true;
                return(false);
            }

            #region Find existing info
            hadNormals  = false;
            hadTangents = false;

            for (int i = 0; i < 6 && i < decl.Length; i++)
            {
                if (decl[i].Usage == DeclarationUsage.Normal)
                {
                    hadNormals = true;
                    break;
                }
                if (decl[i].Usage == DeclarationUsage.Tangent)
                {
                    hadTangents = true;
                    break;
                }
            }
            #endregion

            // Select the appropriate new vertex format
            decl = CompareDecl(PositionMultiTextured.GetVertexElements(), decl) ?
                   PositionNormalMultiTextured.GetVertexElements() : PositionNormalBinormalTangentTextured.GetVertexElements();

            // Clone the mesh to change the vertex format
            Mesh tempMesh = mesh.Clone(device, mesh.CreationOptions, decl);
            mesh.Dispose();
            mesh = tempMesh;

            return(true);
        }
コード例 #2
0
ファイル: GeoMipmap.cs プロジェクト: miquik/leviatan-game
		// Terrainblocks erzeugen (GeoMipMapping)
		// 0: True  1: False
		private int CreateTerrainBlocks()
		{
			try
			{
				// Deklarationen
				int startVertex = 0;
				int counter1 = 0;
				int counter2 = 0;
				PositionNormalMultiTextured[] verts = new PositionNormalMultiTextured[289];

				// Initialisierung
				tBlocks = new TerrainBlock[(((Width-1)/16))*((Depth-1)/16)];

				for (int x=0; x<Width-1; x+=16)
				{
					for (int z=0; z<Depth-1; z+=16)
					{
						startVertex = z+x*Depth;
						counter1 = 0;

						for (int u=0; u<17; u++)
						{
							for (int v=0; v<17; v++)
							{
								verts[counter1] = Vertices[startVertex+v+u*(Depth)];
								counter1 ++;
							}
						}

						tBlocks[counter2] = new TerrainBlock(dev,verts,3);
						counter2 ++;
					}
				}

				return 0;
			}
			catch
			{
				return 1;
			}
		}
コード例 #3
0
ファイル: GeoMipmap.cs プロジェクト: miquik/leviatan-game
		// Vertexliste erzeugen
		// 0: True  1: False (Vertexberechnung)  2: False (Normalenberechnung)  3: False (Vertexbuffer)
		private int CreateVertices()
		{
			// Deklarationen
			short[,] VertexPosition = {{0,0},{1,-1},{1,0},{1,1},{0,1},{-1,1},{-1,0},{-1,-1,},{0,-1}};
			short[,] Faces = {{0,1,8},{0,2,1},{0,4,2},{4,3,2},{0,5,4},{0,6,5},{0,8,6},{8,7,6}};

			Vector3[] TempVertices = new Vector3[9];
			Vector3[] Normals      = new Vector3[8];

			try
			{
				// Vertexberechnung
				NumberOfVertices = Width * Depth;

				Vertices = new PositionNormalMultiTextured[NumberOfVertices];

				for (int x=0; x<Width; x++)
				{
					for (int z=0; z<Depth; z++)
					{
						Vertices[z+x*Depth] = new PositionNormalMultiTextured(x*XScale,Heightmap[x,z]*YScale,z*ZScale,0.0f,1.0f,0.0f,1.0f/Width*x,1.0f/Depth*z,1.0f/Width*x,1.0f/Depth*z,x/20.0f,z/20.0f);
					}
				}
			}
			catch
			{
				return 1;
			}

			try
			{
				// Normalenberechnung
				for (int x=0; x<Width; x++)
				{
					for (int z=0; z<Depth; z++)
					{
						// Vertices
						for (int a=0; a<9; a++)
						{	
							try
							{
								TempVertices[a].X = XScale*(x + VertexPosition[a,0]);
								TempVertices[a].Z = ZScale*(z + VertexPosition[a,1]);
								TempVertices[a].Y = YScale*(Heightmap[x + VertexPosition[a,0],z + VertexPosition[a,1]]);
							}
							catch 
							{
								TempVertices[a].X = 0;
								TempVertices[a].Y = 0;
								TempVertices[a].Z = 0;
							}
						}

						// Normalen
						for (int a=0; a<8; a++)
						{
							Normals[a] = Vector3.Cross(Vector3.Normalize(Vector3.Subtract(TempVertices[Faces[a,0]],TempVertices[Faces[a,1]])),
								         Vector3.Normalize(Vector3.Subtract(TempVertices[Faces[a,1]],TempVertices[Faces[a,2]])));
							Normals[a] = Vector3.Normalize(Normals[a]);
						}

						// Vertexnormale
						for (int a=1; a<8; a++)
						{
							Normals[0] = Vector3.Add(Normals[0],Normals[a]);
						}

						Vertices[z+x*Depth].Normal.X = Normals[0].X;
						Vertices[z+x*Depth].Normal.Y = Normals[0].Y;
						Vertices[z+x*Depth].Normal.Z = Normals[0].Z;
					}
				}
			}
			catch
			{
				return 2;
			}

			// Vertexbuffer erzeugen
			if (CreateVertexBuffer() == 1) return 3;

			return 0;
		}
コード例 #4
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);
        }