/// <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); }
private static PositionMultiTextured[] GenerateVertexes(Size size, float stretchH, float stretchV, ByteGrid heightMap, NibbleGrid textureMap, ByteVector4Grid occlusionIntervalMap) { var vertexes = new PositionMultiTextured[size.Width * size.Height]; #if NETFX4 Parallel.For(0, size.Width, x => #else for (int x = 0; x < size.Width; x++) #endif { for (int y = 0; y < size.Height; y++) { #region Texture blending var texWeights = new float[16]; // Perform integer division (texture map has 1/3 of height map accuracy) but keep remainders int xRemainder; int xCoord = Math.DivRem(x, 3, out xRemainder); int yRemainder; int yCoord = Math.DivRem(y, 3, out yRemainder); // Use remainders to determine intermediate blending levels for vertexes switch (xRemainder) { case 0: TextureBlendHelper(textureMap, xCoord, yCoord, texWeights, 0.25f); TextureBlendHelper(textureMap, xCoord - 1, yCoord, texWeights, 0.25f); break; case 1: TextureBlendHelper(textureMap, xCoord, yCoord, texWeights, 0.5f); break; case 2: TextureBlendHelper(textureMap, xCoord, yCoord, texWeights, 0.25f); TextureBlendHelper(textureMap, xCoord + 1, yCoord, texWeights, 0.25f); break; } switch (yRemainder) { case 0: TextureBlendHelper(textureMap, xCoord, yCoord, texWeights, 0.25f); TextureBlendHelper(textureMap, xCoord, yCoord - 1, texWeights, 0.25f); break; case 1: TextureBlendHelper(textureMap, xCoord, yCoord, texWeights, 0.5f); break; case 2: TextureBlendHelper(textureMap, xCoord, yCoord, texWeights, 0.25f); TextureBlendHelper(textureMap, xCoord, yCoord + 1, texWeights, 0.25f); break; } #endregion var occlusionIntervals = occlusionIntervalMap?[x, y] ?? new ByteVector4(0, 255, 255, 255); // Generate vertex using 2D coords, stretch factors (and tex-coords based on them) // Map X = Engine +X // Map Y = Engine -Z // Map height = Engine +Y vertexes[x + size.Width * y] = new PositionMultiTextured( new Vector3(x * stretchH, heightMap[x, y] * stretchV, -y * stretchH), x * stretchH / 500f, y * stretchH / 500f, occlusionIntervals.ByteToAngle(), texWeights, Color.White); } }