Feb 14 2007
MD3DM: Como desenhar um triângulo usando o Smartphone Emulator
Ps: este post é um complemento do anterior intitulado .NET: Helloworld usando o Managed Direct3D Mobile.
Já estava quase chutando balde quando descobri a solução para o meu problema. Vamos por partes.
O problema
Depois do hello world apresentado no post anterior, nada mais comum do que ir em frente. Logo, como naquele exemplo o foco era o DirectX para Desktop, neste foi para dispositivos móveis, em particular para os Smartphones.
Com base naquele código, tentei desenhar um triangulo usando o Managed Direct3D Mobile. As coisas não foram fáceis, pois para um leigo como eu no assunto, qualquer probleminha leva horas para ser resolvido.
Ta, mas e o problema? É o seguinte: depois que reescrevi parte do código com o intuito de desenhar um triângulo no Smartphone, percebi que nada acontecia. O resultado era exatamente o apresentado no post de ontem: uma tela com o fundo vermelho.
Ué, mas por quê? Se eu estou enviando comandos para que o dispositivo desenhe um maldito triangulo na tela, por que ele não o faz?
A solução
Depois de prostituir a mãe de uns dez funcionários da Microsoft, resolvi reler mais uma vez o capítulo 3 do livro Managed DirectX 9 Kick Start: Graphics and Game Programming. Lá estava claro o erro que cometi. Veja:
Even this simple demonstration of drawing a triangle with a vertex buffer shows approximately a 10% increase in performance based on frame rate. We will get into measuring performance and frame rates in later chapters. However, there is still a problem with this application that makes itself readily apparent when you attempt to resize your window. The triangle simply disappears as soon as your window is resized.
There are a few things going on here that are causing this behavior, and two of them have been mentioned briefly already. Remembering back to the previous chapter, we know that when our window is resized, our device is automatically reset. However, when a resource is created in the default memory pool (such as our vertex buffer), it is automatically disposed when the device is reset. So while our window is being resized, our device is being reset, and our vertex buffer disposed. One of the nifty features of Managed DirectX is that it will automatically re-create your vertex buffer for you after the device has been reset. However, there will be no data in the buffer, so the next time it’s time to draw, nothing is shown.
Fiz questão de colar o texto na integra para que você mesmo tire suas conclusões.
O que o autor diz é o seguinte: o triângulo desaparecerá quando você redimensionar a janela. Isso ocorre, pois quando ela muda de tamanho o dispositivo é reiniciado e o VertexBuffer é desalocado. A solução para isto é fazer uso do recurso que recria o buffer assim que o dispositivo é reiniciado. No entanto, depois de criado, ele estará vazio, então deve-se carregá-lo.
Em outras palavras, crie o seguinte método:
1 private void OnVertexBufferCreate(object sender, EventArgs e) 2 { 3 VertexBuffer buffer = (VertexBuffer)sender; 4 5 CustomVertex.TransformedColored[] verts = new 6 CustomVertex.TransformedColored[3]; 7 8 verts[0] = new CustomVertex.TransformedColored( 9 this.Width / 2, 10 this.Height / 4, 11 0.5F, 12 1, 13 Color.Blue.ToArgb()); 14 15 verts[1] = new CustomVertex.TransformedColored( 16 this.Width * 3 / 4, 17 this.Height * 3 / 4, 18 0.5F, 19 1, 20 Color.Green.ToArgb()); 21 22 verts[2] = new CustomVertex.TransformedColored( 23 this.Width / 4, 24 this.Height * 3 / 4, 25 0.5F, 26 1, 27 Color.Red.ToArgb()); 28 29 buffer.SetData(verts, 0, LockFlags.None); 30 }
Neste método é que o VertexBuffer será carregado para ser desenhado posteriormente. Com isso, é garantido que toda vez que for preciso redesenhar o buffer ele estará lá. Para que isso entre em funcionamento, a criação do VertexBuffer deve ficar assim:
1 private void InitializeGraphics() 2 { 3 try 4 { 5 PresentParameters presentParams = 6 new PresentParameters(); 7 8 presentParams.Windowed = true; 9 presentParams.SwapEffect = 10 SwapEffect.Discard; 11 12 _device = new Device(0, 13 DeviceType.Default, 14 this, 15 CreateFlags.None, 16 presentParams); 17 18 // Create the vertex buffer 19 _vertexBuffer = new VertexBuffer( 20 typeof(CustomVertex.TransformedColored), 21 3, 22 _device, 23 0, 24 CustomVertex.TransformedColored.Format, 25 Pool.SystemMemory); 26 27 _vertexBuffer.Created += 28 new EventHandler(OnVertexBufferCreate); 29 30 OnVertexBufferCreate(_vertexBuffer, null); 31 } 32 catch (Exception ex) 33 { 34 MessageBox.Show("Erro na inicialização: " + 35 ex.Message); 36 } 37 }
Após a criação do Device é que deve ser criado o VertexBuffer, pois o segundo depende do primeiro. Quando o buffer é criado, é atribuído a ele o evento Created. Este evento é que será executado sempre que for preciso recarregar o conteúdo do buffer.
Na hora de desenhar esse buffer, faça o seguinte:
1 private void Render() 2 { 3 // Clear the device 4 _device.Clear(ClearFlags.Target, Color.Bisque, 1.0f, 0); 5 6 // Render de scene 7 _device.BeginScene(); 8 9 _device.SetStreamSource(0, _vertexBuffer, 0); 10 _device.DrawPrimitives(PrimitiveType.TriangleList, 0, 1); 11 12 _device.EndScene(); 13 _device.Present(); 14 }
Claro, não esqueça de criar a variável privada _vertexBuffer do tipo VertexBuffer.
O resultado
Veja:

É isso ae. Até +. ![]()







