2011-09-04 78 views
0

我正在制作(另一个)MineCraft克隆,我遇到了一个有趣的问题。我有一个公共枚举,它列出了一个特定立方体可以存在的所有立方体类型,并且我有一个包含立方体的3d数组。每个立方体都有一个特定的类型,我遍历这个数组以获得每个立方体的顶点,然后将这些顶点传递给为特定立方体类型指定的顶点缓冲区。当我创建一个随机数组的多维数据集或单个多维数据集,并告诉它它应该是什么样的纹理都按预期绘制。我现在试图弄清楚如何绘制草立方体的随机“表面”,并用灰尘立方体填充y轴以下的所有东西。最奇怪的事情发生了,最顶级的立方体是泥土,它用草立方体填充所有底部的立方体!当我禁用循环以填充地下污垢时,最顶端的立方体正按预期显示草。XNA正在拖动错误的纹理?

这是我认为是代码的相关部分。这里是立方体类型设置:

  // Create a random surface level 
     Perlin perlin = new Perlin(); 

     for (int x = 0; x < Game.ChunkWidth_X; x++) 
     { 
      for (int z = 0; z < Game.ChunkDepth_Z; z++) 
      { 
       double XVal = Convert.ToDouble(x) * 1.1; 
       double ZVal = Convert.ToDouble(z) * 1.1; 
       double YVal = Game.ChunkHeight_Y/2 * 1.1; 

       double PerlinValue = perlin.GetValue(XVal, YVal, ZVal); 
       int YVal_new = Convert.ToInt32(YVal + (PerlinValue * 10)); 
       if (YVal_new > Game.ChunkHeight_Y - 1) { YVal_new = Game.ChunkHeight_Y - 1; } 
       if (YVal_new < 0) { YVal_new = 0; } 

       // Set the grass cube 
       Cube NewCube = new Cube(new Vector3(0.5f, 0.5f, 0.5f), new Vector3(x, YVal_new, z)); 
       NewCube.cubeType = CubeType.Grass; 
       CubeGrid[x, YVal_new, z] = NewCube; 

       // Fill below it with dirt 
       for (int y = YVal_new - 1; y >= 0; y--) 
       { 
        Cube NewCube2 = new Cube(new Vector3(0.5f, 0.5f, 0.5f), new Vector3(x, y, z)); 
        NewCube2.cubeType = CubeType.Dirt; 
        CubeGrid[x, y, z] = NewCube2; 
       } 

       // Fill above it with air 
       for (int y = YVal_new + 1; y < Game.ChunkHeight_Y; y++) 
       { 
        Cube NewCube2 = new Cube(new Vector3(0.5f, 0.5f, 0.5f), new Vector3(x, y, z)); 
        NewCube2.cubeType = CubeType.Air; 
        CubeGrid[x, y, z] = NewCube2; 
       } 

      } 
     } 

这是我拉来放入适当的缓冲顶点:

  Dictionary<CubeType, List<VertexPositionNormalTexture>> DrawableVertices = new Dictionary<CubeType, List<VertexPositionNormalTexture>>(); 

     // Get the proper vertices for each cube type and put in the appropriate dictionary 
     for (int x = 0; x < Game.ChunkWidth_X; x++) 
     { 
      for (int z = 0; z < Game.ChunkDepth_Z; z++) 
      { 
       for (int y = 0; y < Game.ChunkHeight_Y; y++) 
       { 
        CubeGrid[x,y,z].CreateVertices(); 
        string test = CubeGrid[x, y, z].cubeType.ToString(); 

        foreach (VertexPositionNormalTexture TargetVertex in CubeGrid[x, y, z].DisplayableVertices) 
        { 
         if (!DrawableVertices.ContainsKey(CubeGrid[x, y, z].cubeType)) 
         { 
          List<VertexPositionNormalTexture> NewList = new List<VertexPositionNormalTexture>(); 
          NewList.Add(TargetVertex); 
          DrawableVertices.Add(CubeGrid[x, y, z].cubeType, NewList); 
         } 
         else 
         { 
          DrawableVertices[CubeGrid[x, y, z].cubeType].Add(TargetVertex); 
         } 
        } 
       } 
      } 
     } 

这里是它的第二部分:

  foreach (KeyValuePair<CubeType, List<VertexPositionNormalTexture>> KVP in DrawableVertices) 
     { 
      VertexBuffer cubeBuffer = new VertexBuffer(device, typeof(VertexPositionNormalTexture), KVP.Value.Count, BufferUsage.WriteOnly); 
      cubeBuffer.SetData(KVP.Value.ToArray()); 

      // Update our collection of vertex buffers 
      CubeType_VertexBuffers[KVP.Key] = cubeBuffer; 

      // Get the triangle count for the buffer 
      CubeType_TriangleCount[KVP.Key] = KVP.Value.Count/3; 

     } 

最后,这里是我的画:

  // Go through each vertex buffer we have created, and draw it. 
     foreach (KeyValuePair<CubeType, VertexBuffer> KVP in CubeType_VertexBuffers) 
     { 
      foreach (EffectPass pass in testEffect.CurrentTechnique.Passes) 
      { 
       if (CubeType_TriangleCount[KVP.Key] > 0) // if this buffer has triangles, draw it. 
       { 
        pass.Apply(); 
        testEffect.View = camera.ViewMatrix; 
        testEffect.TextureEnabled = true; 
        testEffect.Projection = camera.ProjectionMatrix; 
        testEffect.World = worldMatrix; 
        testEffect.Texture = CubeType_Texture[KVP.Key]; 

        device.SetVertexBuffer(KVP.Value); 
        device.DrawPrimitives(PrimitiveType.TriangleList, 0, CubeType_TriangleCount[KVP.Key]); 
       } 
      } 
     } 


     base.Draw(gameTime); 

最奇怪的是,当我手动设置多维数据集类型时,所有内容都按照预期绘制出适当的纹理。我应该尝试解决哪些其他问题?我试图对每个立方体类型做出特定的效果都无济于事。

回答

1

在绝望中尝试了一堆随机的东西后,我找到了一个解决方案。事实证明,如果对不同的纹理使用相同的BasicEffect,它只会使用分配给它的最后一个纹理。我遍历VertexBuffers列表并为每个纹理分配不同的纹理。当所有事情都交给视频卡时,只有最后使用的纹理被渲染,或者看起来如此。

解决方案是为我需要的每个纹理创建一个单独的BasicEffect,并仅将需要的VertexBuffers分配给特定的BasicEffect。