Как нарисовать только видимые данные XNA Мой метод не работает
У меня есть 10*10 кубов плоскости. Я хочу рисовать только видимые кубы, поэтому я использую Bounding frustum. Проблема заключается в том, что когда первый куб из сетки (в позиции 0,0) выходит из усеченного конуса, все кубы исчезают.
Вот мой код в Cube.cs
:
public class Cube
{
Vector3 scale;
float textureScale;
GraphicsDevice device;
Effect effect;
VertexBuffer vertexBuffer;
Texture2D texture;
public Vector3 GlobalPosition = new Vector3(0, 0, 0);
public Vector3[] vertices = new Vector3[36];
public Cube(Vector3 scale, float textureScale, Effect effect, Texture2D texture, GraphicsDevice device)
{
this.scale = scale;
this.textureScale = textureScale;
this.device = device;
this.effect = effect;
this.texture = texture;
vertices[0] = new Vector3(-1, 1, -1);
vertices[1] = new Vector3(-1, -1, -1);
vertices[2] = new Vector3(1, -1, -1);
vertices[3] = new Vector3(1, -1, -1);
vertices[4] = new Vector3(1, 1, -1);
vertices[5] = new Vector3(-1, 1, -1);
//Front
vertices[6] = new Vector3(1, -1, 1);
vertices[7] = new Vector3(-1, -1, 1);
vertices[8] = new Vector3(-1, 1, 1);
vertices[9] = new Vector3(-1, 1, 1);
vertices[10] = new Vector3(1, 1, 1);
vertices[11] = new Vector3(1, -1, 1);
//Bottom
vertices[12] = new Vector3(-1, -1, -1);
vertices[13] = new Vector3(-1, -1, 1);
vertices[14] = new Vector3(1, -1, -1);
vertices[15] = new Vector3(1, -1, 1);
vertices[16] = new Vector3(1, -1, -1);
vertices[17] = new Vector3(-1, -1, 1);
//Top
vertices[18] = new Vector3(1, 1, -1);
vertices[19] = new Vector3(-1, 1, 1);
vertices[20] = new Vector3(-1, 1, -1);
vertices[21] = new Vector3(-1, 1, 1);
vertices[22] = new Vector3(1, 1, -1);
vertices[23] = new Vector3(1, 1, 1);
//Left
vertices[24] = new Vector3(-1, -1, 1);
vertices[25] = new Vector3(-1, -1, -1);
vertices[26] = new Vector3(-1, 1, -1);
vertices[27] = new Vector3(-1, 1, -1);
vertices[28] = new Vector3(-1, 1, 1);
vertices[29] = new Vector3(-1, -1, 1);
//Right
vertices[30] = new Vector3(1, -1, -1);
vertices[31] = new Vector3(1, -1, 1);
vertices[32] = new Vector3(1, 1, -1);
vertices[33] = new Vector3(1, -1, 1);
vertices[34] = new Vector3(1, 1, 1);
vertices[35] = new Vector3(1, 1, -1);
for (int i = 0; i < 36; i++)
{
vertices[i] = vertices[i] * scale + GlobalPosition;
}
VertexPositionNormalTexture[] verticesList = GetVPNT();
vertexBuffer = new VertexBuffer(device, VertexPositionNormalTexture.VertexDeclaration, verticesList.Length, BufferUsage.WriteOnly);
vertexBuffer.SetData<VertexPositionNormalTexture>(verticesList.ToArray());
}
public void Draw(Matrix View, Matrix Projection, Vector3 pos)
{
effect.CurrentTechnique = effect.Techniques["Textured"];
effect.Parameters["xWorld"].SetValue(Matrix.Identity * Matrix.CreateTranslation(pos));
effect.Parameters["xView"].SetValue(View);
effect.Parameters["xProjection"].SetValue(Projection);
effect.Parameters["xTexture"].SetValue(texture);
effect.Parameters["xEnableLighting"].SetValue(true);
effect.Parameters["xLightDirection"].SetValue(new Vector3(30, 30, 30));
effect.Parameters["xAmbient"].SetValue(0.5f);
foreach (EffectPass pass in effect.CurrentTechnique.Passes)
{
pass.Apply();
device.SetVertexBuffer(vertexBuffer);
device.DrawPrimitives(PrimitiveType.TriangleList, 0, vertexBuffer.VertexCount / 3);
}
}
public VertexPositionNormalTexture[] GetVPNT()
{
VertexPositionNormalTexture[] vpnt = new VertexPositionNormalTexture[36];
Vector2[] texCoords = CalculateTexCoords(vertices, "tile");
for (int i = 0; i < 36; i++)
{
vpnt[i] = new VertexPositionNormalTexture(vertices[i], new Vector3(0, 0, 1), texCoords[i]);
}
return vpnt;
}
public Vector2[] CalculateTexCoords(Vector3[] vec, string type)
{
List<Vector2> texCoords = new List<Vector2>();
for (int i = 0; i < 12; i++)
{
if (AllEqual<float>(vertices[i * 3 + 0].X, vertices[i * 3 + 1].X, vertices[i * 3 + 2].X))
{
Vector2[] normvec = new Vector2[3];
normvec[0] = TexNorm(new Vector2(vertices[i * 3 + 0].Z, vertices[i * 3 + 0].Y), type);
normvec[1] = TexNorm(new Vector2(vertices[i * 3 + 1].Z, vertices[i * 3 + 1].Y), type);
normvec[2] = TexNorm(new Vector2(vertices[i * 3 + 2].Z, vertices[i * 3 + 2].Y), type);
texCoords.AddRange(normvec);
}
if (AllEqual<float>(vertices[i * 3 + 0].Y, vertices[i * 3 + 1].Y, vertices[i * 3 + 2].Y))
{
Vector2[] normvec = new Vector2[3];
normvec[0] = TexNorm(new Vector2(vertices[i * 3 + 0].X, vertices[i * 3 + 0].Z), type);
normvec[1] = TexNorm(new Vector2(vertices[i * 3 + 1].X, vertices[i * 3 + 1].Z), type);
normvec[2] = TexNorm(new Vector2(vertices[i * 3 + 2].X, vertices[i * 3 + 2].Z), type);
texCoords.AddRange(normvec);
}
if (AllEqual<float>(vertices[i * 3 + 0].Z, vertices[i * 3 + 1].Z, vertices[i * 3 + 2].Z))
{
Vector2[] normvec = new Vector2[3];
normvec[0] = TexNorm(new Vector2(vertices[i * 3 + 0].X, vertices[i * 3 + 0].Y), type);
normvec[1] = TexNorm(new Vector2(vertices[i * 3 + 1].X, vertices[i * 3 + 1].Y), type);
normvec[2] = TexNorm(new Vector2(vertices[i * 3 + 2].X, vertices[i * 3 + 2].Y), type);
texCoords.AddRange(normvec);
}
}
return texCoords.ToArray();
}
public bool AllEqual<T>(params T[] values)
{
if (values == null || values.Length == 0)
return true;
return values.All(v => v.Equals(values[0]));
}
public Vector2 TexNorm(Vector2 vecIn, string type)
{
Vector2 vec = new Vector2();
//Remove negative coordinates
if (vecIn.Y < 0)
vec.Y = 0;
if (vecIn.X < 0)
vec.X = 0;
switch (type)
{
case "stretch":
{
if (vecIn.X > 0)
vec.X = 1;
if (vecIn.Y > 0)
vec.Y = 1;
break;
}
case "tile":
{
if (vecIn.X > 0)
vec.X = textureScale;
if (vecIn.Y > 0)
vec.Y = textureScale;
break;
}
}
return vec;
}
public bool IsVisible(Matrix VP)
{
BoundingFrustum bf = new BoundingFrustum(VP);
bool isVis = true;
//Check weather at least one vertices are out of the frustum
for (int i = 0; i < 36; i++)
{
if (bf.Contains(vertices[i]) != ContainmentType.Contains)
{
isVis = false;
break;
}
}
return isVis;
}
}
Draw()
метод в Main.cs
:
for (int i = 0; i < 10; i++)
{
for (int k = 0; k < 10; k++)
{
Cube cube = new Cube(Vector3.One, 1, effect, woodTexture, device);
if (cube.IsVisible(View * Projection))
{
cube.Draw(View, Projection, new Vector3(2 * i, 0, 2 * k));
}
}
}
Я также хотел бы, если вы можете дать мне ссылку на учебник / образец текстурирования атласа, спасибо!
1 ответ
Ваш метод cube.IsVisible(...) не учитывает последнее преобразование, которое вы применяете при рисовании куба, т.е. вы всегда проверяете исходный куб, а не преобразованный.
Пожалуйста, обратитесь к этому ответу, так как он касается как вашей проблемы выбраковки (frustum-box), так и инстанциирования.