quinta-feira, fevereiro 03, 2011

Vertex Buffer Objects

Bom dia pessoal a grande novidade agora são os Vertex Buffer Objects, para quem não conhece os VBO é uma maneiro de enviar os arrays dos vetores, indices coordenadas de textura, normais para a memória da placa de video desta maneira não é necessário chamar o glVertex* para cada vetor diminuindo drasticamento o overred do programa desta maneira você envia os arrays para a placa de video uma única vez, e depois chama o  glDrawElements ele desenha seu mesh.

a um vasto conteudo na internet sobre VBO, abaixo segue alguns links de referência:

http://www.songho.ca/opengl/gl_vbo.html
http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=45

na engine consegui colocar o terreno no VBO, tive que fazer um re-build na estrutura basicamente por causa do tipo de dados, mas como tudo aqui é experimental ainda vão haver muitas modificações, os indices funcionão corretamente, só as coordenadas de textura que me deram uma bela surra.

 Abaixo segue as respectivas classes e um exemplo de utilização:
**** VertexBufferObject.h
/**
* @brief Gera Buffer Object
**/

class VertexBufferObject
{
    public:
        unsigned int vertexBuffId; //id do buffer vertices
        unsigned int indexBuffId; //id do buffer indices
        unsigned int normalBuffId; //id do buffer de normal
        unsigned int texBuffId; //id do buffer de coordenada de textura
        unsigned int numIndices;
        float *vertices; // data dos vertices
        unsigned int *indexs; // data dos indicex
        float *normals; // data das normais
        float *texCoord; //data das coordenadas de Texturas

        VertexBufferObject();

        /**
        * @brief seta os vetices do VBO
        * @param vec3d *data ponteiro para os vertices
        * @param uint32 size tamanho do buffer
        */
        void setVertices(float *data,unsigned int size);

        /**
        * @brief seta os indices do VBO
        * @param uint32 *data ponteiro para os indices
        * @param uint32 size tamanho do buffer
        */
        void setIndexs(unsigned int *data,unsigned int size);

        /**
        * @brief seta as normais do VBO
        * @param vec3d *data ponteiro para os normais
        * @param uint32 size tamanho do buffer
        */
        void setNormals(float *data,unsigned int size);

        /**
        * @brief seta as coordenadas de textura VBO
        * @param TexCoord2 *data ponteiro para os vertices
        * @param uint32 size tamanho do buffer
        */
        void setTexCoords(float *data,unsigned int size);

        /**
        * @brief desenha o VBO
        */
        void draw();
        virtual ~VertexBufferObject();
};

***EOF***
***VertexBufferObject.cpp****

VertexBufferObject::VertexBufferObject()
{
    vertexBuffId = 0;
    indexBuffId = 0;
    normalBuffId = 0;
    texBuffId = 0;
    numIndices = 0;
    vertices = NULL;
    indexs = NULL;
    normals = NULL;
    texCoord = NULL;

}

void VertexBufferObject::setVertices(float *data,unsigned int size)
{


    glGenBuffersARB( 1, &vertexBuffId);
    glBindBufferARB( GL_ARRAY_BUFFER_ARB, vertexBuffId );

    vertices = data;

    glBufferDataARB( GL_ARRAY_BUFFER_ARB, size, data, GL_STATIC_DRAW_ARB );

}
void VertexBufferObject::setIndexs(unsigned int *data,unsigned int size)
{
    glGenBuffersARB( 1, &indexBuffId );
    glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER, indexBuffId );

    indexs = data;

    numIndices = (size/sizeof(unsigned int));
    glBufferDataARB( GL_ELEMENT_ARRAY_BUFFER, size, data, GL_STATIC_DRAW_ARB );
}

void VertexBufferObject::setNormals(float *data,unsigned int size)
{
    glGenBuffersARB( 1, &normalBuffId );
    glBindBufferARB( GL_ARRAY_BUFFER_ARB, normalBuffId );

    normals = data;

    glBufferDataARB( GL_ARRAY_BUFFER_ARB, size, data, GL_STATIC_DRAW_ARB );
}

void VertexBufferObject::setTexCoords(float *data,unsigned int size)
{
    glGenBuffersARB( 1, &texBuffId );
    glBindBufferARB( GL_ARRAY_BUFFER_ARB, texBuffId );

    texCoord = data;
    glBufferDataARB( GL_ARRAY_BUFFER_ARB, size, data, GL_STATIC_DRAW_ARB );
}

void VertexBufferObject::draw()
{

    if (vertexBuffId != 0 )
    {
        glBindBufferARB(GL_ARRAY_BUFFER_ARB, vertexBuffId);
        glEnableClientState(GL_VERTEX_ARRAY);

        glVertexPointer(3,GL_FLOAT,0,0);
    }

    if (indexBuffId != 0 )
    {
        glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, indexBuffId);
        glEnableClientState(GL_INDEX_ARRAY);
        glIndexPointer(GL_UNSIGNED_INT,0,0);
    }

    if (normalBuffId != 0)
    {
        glEnableClientState(GL_NORMAL_ARRAY);
        glNormalPointer(GL_FLOAT,0,normals);
    }

    if (texBuffId != 0)
    {
        glBindBufferARB(GL_ARRAY_BUFFER_ARB, texBuffId);
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
        glTexCoordPointer(2,GL_FLOAT,0,0);
    }

    //glDrawArrays(GL_TRIANGLES,0,3);
    glDrawElements(GL_TRIANGLES,numIndices,GL_UNSIGNED_INT,0);


    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_INDEX_ARRAY);
    glDisableClientState(GL_NORMAL_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}

VertexBufferObject::~VertexBufferObject()
{

}
***EOF***

Um exemplo da maneira que se possa utilizar segue abaixo isso vai desenhar um quadrado na tela.

// vertex coords array
GLfloat vertices[] =
{1,-1,1, 1,1,1, -1,1,1,
-1,-1,1
 };


unsigned int indices[] = {0,1,2,2,3,0};

float texCord[] = {0,1, 1,1, 1,0, 0,0, 0,1};

VertexBufferObject *vbo = NULL;
TexturePCX *tex = NULL;
...
...
...

int main(int argc,char **argv)
{
 ...
 ...
 ...

 vbo = new VertexBufferObject();
 vbo->setVertices(vertices,sizeof(vertices));
 vbo->setIndexs(indices,sizeof(indices));
tex = new TexturePCX("storage//textures//ground.bmp"); //Não era pra carregar um bmp?
}

void draw()
{
 ...
 glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
    glLoadIdentity();
    glTranslatef(0.0f,0.0f,-5.0f);
    tex->begin();
    vbo->draw();
    tex->end();
    glPopMatrix();
}

o resultado é o quadrado na tela você pode perceber que as texturas não estão aparecendo corretamente, você pode perceber tb o terreno sendo desenhado em um vbo, com o terreno coloquei um mapa de 512*512 sem sentir queda no FPS:

no gDEBugger você pode ver na placa de video como estão os dados:
Vertices:
Indices:
se você quiser ver os códigos completos da um pulo lá no svn:
https://newbie-engine.svn.sourceforge.net/svnroot/newbie-engine

segunda-feira, janeiro 17, 2011

Newbie Engine Updates

Nova versão saindo.
Os próximos passos são estudar a Fisica Aplicada a Veiculos, achei uma referencia muito boa na hexGear Engine
Vou esmiuçar esse motor

segunda-feira, outubro 04, 2010

Newbie Game Engine Updates

Olá pessoal temos uma nova versão, creio que a simulação fisica esta totalmente estável e o mesh do terreno esta colidindo corretamente com os objetos, há uma demonstração com sen x cos, ainda não re-escrevi a parte relativa ao carregamento de um HeightMap através de uma imagem pretendo usar png, pois este tem 4 camadas e da pra colocar informações por escala nas 4 camadas, uma para Grandes Morros a nivel geral, e ir dimunuindo o nivel de detalhe gradativamente, mas antes de fazer isso tenho que dividir o mapa em setores e fazer um colling para assim trabalhar com a ordem de 1024x1024.



https://sourceforge.net/projects/newbie-engine/

vou demorar um pouco pra   ataulizar o SVN mas o arquivo sf já foi atualizado

quarta-feira, julho 14, 2010

Newbie Game Engine Updates

Olá pessoal não ainda estou vivo, e fiz uma atualização no SVN com a nova estrutura do projeto creio que agora só precise do SDL para compilar (./configure && make) talvez tenha que usar o autotools também mas não fiz os tetes em outras plataformas.

uma ataualização pendente que estou pra enviar é a correção do Mesh de Terreno agora colide com o Mapa normalmente, agora tenho que dividir os mapas em partes 32x32 para fazer um cooling e texturizar.

bom pessoal por enquanto é isso, se puderem tentar compilar é uma boa.

agora vou atualizar o arquivo do sf.

o path do repositório é

svn co https://newbie-engine.svn.sourceforge.net/svnroot/newbie-engine newbie-engin

https://sourceforge.net/projects/newbie-engine/


até mais pessoal.

terça-feira, dezembro 01, 2009

Ausência

Olá pessoal, o Blog anda sem atualizações e me desculpo por, isso bom agora é fim de ano e estou descansando a medida do possivel, também estou com milhares de tarefas que estão sugando toda energia dispónivel.

Quanto a Engine fiz uma motificação na hierarquia do projeto, a ODE está integrada ao projeto (na verdade adicionei o projeto no Makefile do ODE), também separei a engine do projeto do jogo, está separado desta maneira:

- ODE / OPCODE
- Newbie Game Engine (Código da Engine)
- Lunatycs - (Projeto do Game das ultimas imagens)
- Lab - (Usado para experiências).

Só falta ativar a camera, ai faço as atualições, tb to querendo aprontar algo com Apache, MySQL e WebServices na parte Web.

Um abraço e boas festas.

quinta-feira, outubro 22, 2009

Will Code HTML For FOOD

Muito boa éssa :-)





Ai é só achar uma rede Wi-Fi:



E pronto já posso virar Rippie.

segunda-feira, outubro 19, 2009

Newbie Game Engine Updates

Olá pessoal, um final de semana chuvoso no litoral acaba sendo bem produtivo, tenho já um roteiro para um game.

Playground Lunático

Playground Lunático é um jogo 3D, onde você pode utilizar de vários veiculos como Tanques de guerra, tratores, jipes, entre diversos outros e interagir com um cenário gigante com diversos objetos interativos. o único objetivo é provocar a destruição e semear o caos.

 andei dando uma brisada no blender e modelei um veiculo:

LN 1 Carnicinha:



A Lateral (Iluminação ruim):

Como vemos temos um canhão, que terá elevação de 60º.

Topo:



A base do canhão terá angulo de 180º.

Me arriscando no blender:



Ainda vai demorar umas semanas para fazer o LN 1 Carnicinha funcionar, mais valeu o exercicio criativo.

Algum Game Design de plantã HELP-ME PLEASE.

A ultima screen-shot da engine (ainda não atualizei o sf.net)


um chão com uma textura (Grama ou Concreto)? e um Sky box vão dar um aspecto legal, a rampa vermelha é um modelo (.obj), creio que ja de para fazer cenários pequenos já que ainda não há nenhuma técnica de particionamento de espaço.

gostei deste estilo de render vou dar uma explorada nele.

Até mais pessoal

segunda-feira, outubro 12, 2009

Newbie Game Engine Veiculos.

Bom pessoal, consegui deixar a simulação fisica estável, e fiz até um cena maneirinha ora demonstrar.




Você pode fazer o download do código no SF.
só não atualizei o svn

Até mais pessoal

terça-feira, setembro 22, 2009

Operações com vetor usando SSE Parte II

Parte I

Agora segue as quatro operações com vetores usando SSE foi usando g++ e o inline assembly, mais portar para outros compiladores é uma tarefa simples


**** vec4.hpp ****
#ifndef __vec4hpp__


typedef struct vec4f

{

float x;

float y;

float z;

float w;

}

vec4f __attribute__ ((aligned(16)));

// Soma de Vetores
inline vec4f operator+(vec4f a, vec4f b)

{

vec4f r;

asm("movaps %[ina], %%xmm0 \n\t" \

"movaps %[inb], %%xmm1 \n\t" \

"addps %%xmm0, %%xmm1 \n\r" \

"movaps %%xmm1, %[o] \n\t" \

: [o] "=m"(r)

: [ina] "m"(a), [inb] "m"(b));

return r;

}

// Subtração de Vetores
inline vec4f operator-(vec4f a,vec4f b)

{

vec4f r;

asm("movaps %[ina], %%xmm0 \n\t" \

"movaps %[inb], %%xmm1 \n\t" \

"subps %%xmm1, %%xmm0 \n\r" \

"movaps %%xmm0, %[o] \n\t" \

: [o] "=m"(r)

: [ina] "m"(a), [inb] "m"(b));

return r;

}

// Multiplicação de Vetores
inline vec4f operator*(vec4f a,vec4f b)

{

vec4f r;

asm("movaps %[ina], %%xmm0 \n\t" \

"movaps %[inb], %%xmm1 \n\t" \

"mulps %%xmm0, %%xmm1 \n\r" \

"movaps %%xmm1, %[o] \n\t" \

: [o] "=m"(r)

: [ina] "m"(a), [inb] "m"(b));

return r;

}

// Divisão de Vetores
inline vec4f operator/(vec4f a,vec4f b)
{

vec4f r;

asm("movaps %[ina], %%xmm0 \n\t" \

"movaps %[inb], %%xmm1 \n\t" \

"divps %%xmm1, %%xmm0 \n\r" \

"movaps %%xmm0, %[o] \n\t" \

: [o] "=m"(r)

: [ina] "m"(a), [inb] "m"(b));

return r;

}
#endif

*** EOF ***
 
Segue um teste básico
 
*** teste_cpp.cpp ****
 
#include "vec4.hpp"


#include

void printV(vec4f v)

{

printf("x: %f y: %f z: %f w: %f\n",v.x, v.y, v.z, v.w);

}



int main(int argc,char **argv)

{

vec4f a = {10.f,10.0f,10.0f,10.0f};

vec4f b = {2.0f,2.0f,2.0f,2.0f};

vec4f c;
printf("a ");

printV(a);

printf("b ");

printV(b);

c = a + b;

printf("a + b \n");

printV(c);

c = a - b;

printf("a - b \n");

printV(c);

c = a * b;

printf("a * b \n");

printV(c);

c = a / b;

printf("a / b \n");

printV(c);

vec4f z = a*a / b;


printf("z = a*a /b \n");

printV(z);

return 0;

}
 *** EOF ***


O Resultado:
a x: 10.000000 y: 10.000000 z: 10.000000 w: 10.000000


b x: 2.000000 y: 2.000000 z: 2.000000 w: 2.000000

a + b

x: 12.000000 y: 12.000000 z: 12.000000 w: 12.000000

a - b

x: 8.000000 y: 8.000000 z: 8.000000 w: 8.000000

a * b

x: 20.000000 y: 20.000000 z: 20.000000 w: 20.000000

a / b

x: 5.000000 y: 5.000000 z: 5.000000 w: 5.000000

z = a*a /b

x: 50.000000 y: 50.000000 z: 50.000000 w: 50.000000


por equanto tudo tranquilo, o próximo passo é fazer as multiplicação por matrizes, apesar de não ser ideal fazer por SSE mas é de maneira geral um artigo interessante, então no próximo da série trataremos de multiplicação de vetores por matrizes

terça-feira, setembro 15, 2009

Newbie Game Engine Updates

Fiz algumas melhorias na Classe de Terreno e Mesh (Terreno herda de Mesh) e o Mesh que carregava wavefront virou Wavefront.h, mas o mapa ainda ta com problema precisa de diversas melhorias,
outra novidade é o build pra vs2005 (buid/vs2005).



na imagem acima a esfera não colide com o terreno, vai ser um problema desagradavél de se resolver.

atualizei o código no sf, mas ainda não fiz o commit no svn. Agora vou ouvir The Gladiators e jogar, tb tenho que terminar de instalar as dependecias do GNU Octave.

segunda-feira, setembro 14, 2009

Ánalise numérica ON-LINE

Galera achei uma interface web para o programa GNU Octave (equivalente ao Matlab), os gentis senhores do Department of Mathematics, Warsaw University. (Polonia), emprestão seus processadores para fazermos os nossos calculos on-line.

 
me divertindo um pouco criei esta plot:

x = y = -10:0.1:10;
[X,Y] = meshgrid(x,y);
mesh(X,Y,(1./X).*sin(X).*(1./Y).*sin(Y));

não há limites quanto ao tempo de computação mais esses generosos senhores pedem:

"Please do not submit codes that will run for a long time or take up a lot of memory. This service is intended for occasional, quick computations. Use "Files -> Remove all files" button to clear your workspace after you are done. All your activities are being logged. If you don't like this policy, don't use this service. "




agora quando tiver perdido em algum lugar em posse de um computador e tiver que fazer um calulo já sabe onde deve ir: http://hara.mimuw.edu.pl/weboctave/web/index.php

a interface Web é um projeto Open Source  está no Source Forge
http://sourceforge.net/projects/weboctave/

domingo, setembro 13, 2009

Deferred Load ASP.NET/JQuery


Hoje vou descrever uma técnica de como carregar o conteúdo  dinâmico após a pagina ser carregada, isso pode aumentar bastante a experiência com o usuário se você tem que exibir uma quantidade grande de dados, ou pegar algum conteúdo de um servidor externo. A técnica consiste em baixar todo o conteúdo estático, e após o documento estar pronto (ready), fazer uma requisição em AJAX para baixar o conteúdo dinâmico.






Temos dois exemplos um pegando o conteúdo de RSS e montando uma lista via javascript, no segundo caso que renderiza o HTML é um WebControl contendo um Repeater, então vamos para o código.

Antes de mais nada crie um novo projeto Web e monte o mesmo com a estrutura abaixo.




O  FeederLoader.cs representa o Proxy entre a fonte de dados e a requisição AJAX, nela usamos o WebClient para baixar um RSS e devolvemos para o navegador, e o código dela e este:


public class FeederLoader
{
    public FeederLoader()
    {
    }

    public string Load(string url)
    {
        WebClient client = new WebClient();
        byte[] buffer = client.DownloadData(url);

        return UTF8Encoding.UTF8.GetString(buffer);
    }

O método Load baixa o conteúdo da url usando o WebClient e devolve como uma String UTF-8.
Partimos agora para o Handler FeederJS.ashx


public void ProcessRequest (HttpContext context) {
        context.Response.ContentType = "text/xml";
        FeederLoader Loader = new FeederLoader();
        
       System.Threading.Thread.Sleep(1000); //só pra ficar cool

        string rss = Loader.Load("http://newbie-x11.blogspot.com/feeds/posts/default?alt=rss");
        context.Response.Write(rss);
        context.Response.End();
        
    }

No método ProcessRequest usamos o FeederLoad pra baixar o RSS deste blog :-] , e devolver para o XML navegador.
Agora a página Web, EmJavaScript.aspx


<style type="text/css">
        
        .Loading
        {
            background-image: url('images/loader.gif');
            background-repeat:no-repeat;
        }
        
    </style>

  <div id="master">
            <div id="static">
                Como as vezes tenho uma alta enorme de creatividade não vou escrever nada aqui.
            </div>
            <div id="dynamic">
            </div>
        </div>
        <div>

            <script type="text/javascript" src="js/jquery-1.3.2.min.js"></script>
            <script type="text/javascript">
            $(document).ready(function(){
            var ajaxOption = {
                        type: "GET",
                        url: "handlers/FeederJS.ashx",
                        dataType : "xml",
                        success : function(data){
                            var html = "<ul>"
                            $(data).find('item').each(function(){
                                var titulo = $(this).find('title').text();
                                html += "<li>"+titulo+"</li>";
                            });
                            
                            html += "</ul>";
                            
                            $("#dynamic").append(html);
                            $("#dynamic").attr("class","");
                        }
                    };
                    
                    $("#dynamic").attr("class","Loading");
                    
                    $.ajax(ajaxOption);
                    
            });
            
          
            </script>

        </div>

Acima antes de fazer a requisição em AJAX , mudamos o CSS do elemento que abriga o conteúdo dinâmico para a classe que contem a imagem carregando, na Requisição (success), fazemos o loop no xml e montamos uma lista, preenchemos o conteudo carregado no elemento, e removo a classe de CSS .Loading, e Badabum..

Agora se você não quer ficar montando conteudo via JavaScript demonstro abaixo com poucas modificações, fazemos a mesma coisa só que usando o um Repeater e um User Control, vamos lá crie o Controle, então adicione um novo Web User Control com o nome de Listageml.ascx, e o código dele segue abaixo.


<%@ Control Language="C#" AutoEventWireup="true" CodeFile="Listageml.ascx.cs" Inherits="controles_Listageml" %>
<div>
    <asp:Repeater ID="Repeater1" runat="server">
        <HeaderTemplate>
            <ul>
        </HeaderTemplate>
        <ItemTemplate>
            <li>
                <%# Eval("title") %>
            </li>
        </ItemTemplate>
        <FooterTemplate>
            </ul></FooterTemplate>
    </asp:Repeater>
</div>

O .cs:


protected void Page_Load(object sender, EventArgs e)
    {
        XmlTextReader reader = new XmlTextReader("http://g1.globo.com/Rss2/0,,AS0-5597,00.xml");

        DataSet ds = new DataSet();

        ds.ReadXml(reader);
        Repeater1.DataSource = ds.Tables["item"];
        Repeater1.DataBind();
    }

Creio que não seja necessário comentar o bloco acima, agora vamos ao Handler FeederASP.ashx, que tem modificações significativas:


public void ProcessRequest (HttpContext context) {
        
        Page page = new Page();
        UserControl ctl = (UserControl)page.LoadControl("~/controles/Listageml.ascx");
        StringWriter writer = new StringWriter();

        System.Threading.Thread.Sleep(1000); //só pra ficar cool
        
        page.Controls.Add(ctl);
        HttpContext.Current.Server.Execute(page, writer, false);

        context.Response.ContentType = "text/plain";
        context.Response.Write(writer.ToString());
        context.Response.End();
    }

Acima usamos estas linhas malucas para renderizar o HTML do controle, se tiver a necessidade de passar parâmetros para o controle pode usar os atributos, mas compensa dar um passeio pelo Google e ler sobe WebControls.
Passamos agora para o arquivo EmASP.aspx, a única mudança é no Java script:


<script type="text/javascript">
            $(document).ready(function(){
            var ajaxOption = {
                        type: "GET",
                        url: "handlers/FeederASP.ashx",
                        dataType : "text",
                        success : function(data){
                         
                            
                            $("#dynamic").append(data);
                            $("#dynamic").attr("class","");
                        }
                    };
                    
                    $("#dynamic").attr("class","Loading");
                    
                    $.ajax(ajaxOption);
                    
            });
</script>

Simplificou bastante, aqui só pegamos o conteúdo pronto e colocamos no elemento.
Pronto é isso, pode baixar o código fonte aqui.

domingo, agosto 30, 2009

Terreno Parte 2

Depois de algumas xícaras de café, algumas horas no parque do ipirangacom um caderno uma caneta e minha calculadora HP 9s, consegui gerar um terreno no minimo decente mais ainda fanta muita coisa, corrigi os problemas de collisão,agora os objetos colliden corretamente inclusive com o terreno.nos proximos dias estarei me divertindo montando uma classe de veiculo.





quinta-feira, agosto 27, 2009

Engine de Terreno

Olá pessoal comecei a codar o modulo de terreno na engine, o que fiz até agora
foi gerar uma malha de terreno e gerar os triangulos a partir dela, o próximo
passo é pegar todos esses vertices indexar gerar um Mesh para o ODE,
eu já podia e separar a Classe de Mesh assim o loader de wavefront,
e o mesh de terreno podem ser interpretados da mesma maneira para o ODE.



Vale apena fazer um observação sobre a elegancia da geração atual da imagem.

int offset = w*y+x;
index[offset] = offset;
grid[offset].x = x*scale;
grid[offset].z = y*scale;
grid[offset].y = sinf(x/2)*3;


Vai lá no sf e pega a última versão.
https://sourceforge.net/projects/newbie-engine/files/

sexta-feira, julho 17, 2009

Socket em *NIX

Tirei esse do fundo do báu, os dos HD's se prefirir e datado de 05/2005 e eu fiz pro grupo União Atlantica, e um código comentado que serve como tutorial, ele mostra como estabelecer conexão cliente-servidor usando sockets em *NIX creio que não funcione no windows.

****Cliente***



#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

int main(int argc,char *argv[])
{
int TSocket;
struct sockaddr_in servidor;
char msg[17] = "Uniao Atlantica\0";
//inicia o socket
//nota parametro 1 tipo familia do socke
//pode ser AF_INET (ARPA INTERNET PROTOCOLOS) "mais usada"
//"" AF_UNIX (UNIX INTERNET PROTOCOLOS)
//"" AF_ISO (ISO PROTOCOLOS)
//"" AF_NS (XEROX NETWORK SYSTEM PROTOCOLOS)

//nota parametro tipos SOCK_STREAM = TCP, SOCK_DGRAM = UDP
//terceiro parametro 0 (faleremos depois)
TSocket = socket(AF_INET,SOCK_STREAM,0);

if (TSocket < 0) //simples checagem de erro
{
printf("Erro\n");
exit(0);
}

//montando a estrutu servidor essa estrutura mas TSocket vao fazer a conecao
//entre o nosso cliente e o servidor

//estrutura sockaddr_in
//struct sockaddr_in {
//short int sin_family; { do endreco (ex: AF_INET)}
//unsignet short int sin_port; (numero da porta)
//struct sin_addr in_addr; (ip do host)
//unsignet char sin_zero[8]; (zera a estrutura)
//}

servidor.sin_family = AF_INET;
servidor.sin_port = htons(3506); //porta que vamos usar
//o htons significa host to network short
//mais info (man pages)
servidor.sin_addr.s_addr = inet_addr("127.0.0.1"); //ip destino
bzero(&(servidor.sin_zero),8); //zera o resto da estrutura

//agora a funcao connect essa funcao faz a conecao com o servidor
if (connect(TSocket,(struct sockaddr *)&servidor,sizeof(servidor)) < 0)
{
printf("erro ao fazer a conexao\n");
exit(0);
}

//agora vamos usar vamos enviar uma mesnsagem para o servidor
//usnado a funcao send();
//prototipo
//int send(int TSocket,const void *msg,int size_t len,int flags)

send(TSocket,&msg,sizeof(msg),0);

//agora fechamos nosso cliente
close(TSocket);
//bom Daniel pela experiencia que voce tem com redes acho q deu pra entender tudo ate agora
//vc manja mais de ingles que eu e esse seu debian ta lotado de man pages
//qualquer coisa psota sua msg pro grupo ou pra min que a gente resolve
//pra compilar gcc cliente.c -o cliente
//executar ./cliente
return 0;
}

****Servidor.c****


//o que tem de novo aki e sao a funcoes bind() e listen()
//a funcao bind associa um socket ao nosso servidor local (eu numca entendi isso direita mas fazer o que)
//a funcao listem faz nosso servidor esperar uma conecao faz ele escutar
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <errno.h>
#include <signal.h>

int main(int argc,char *argv[])
{
int TSocket,Clientes[5],tamanho;
struct sockaddr_in local,cliente[5];
int Count,Next =0;
char *recived_msg; //cinco strings para evitar que um dois processos filhos tentem escrever a mesmo tempo
int Atual[5]; //tb uma pra cada um
//vamos setar a estrutura local com infomacoes da nossa maquina
TSocket = socket(AF_INET,SOCK_STREAM,0);

local.sin_family = AF_INET;
local.sin_port = htons(3506);
local.sin_addr.s_addr = INADDR_ANY; //enderco local
bzero(&(local.sin_zero),8);

//usar o misterioso bind
bind(TSocket,(struct sockaddr *)&local,sizeof(struct sockaddr));

//agora a funcao listem ela e bem simple
listen(TSocket,5); //o segundo parametro 5 e o numero de conexoes que vamos esperar (max)
tamanho = sizeof(struct sockaddr_in);
while (Next < 5)
{
if ((Clientes[Next] = accept(TSocket,(struct sockaddr *)&cliente[Next],&tamanho)) < 0)
{
printf("Erro\n");
exit(0);
}
else
{
printf("Cliente se conectou numero: %d, ip:%s\n",Next,inet_ntoa(cliente[Next].sin_addr));
if (!fork())
{
int coisa = Next;
while(1)
{
if (recv(Clientes[coisa],recived_msg,20,0) < 0)
{
printf("Erro ao receber msg\n");
exit(0);
}
else
{
printf("Msg Recebida:%s\n",recived_msg);
exit(0);
}
}

}
Next++;
}
}
}
//o fork que faz o bicho pegar o resto nem e divertido
//imagine nosso servidor tendo que segurar 50 conexoes
//ai a conexao de algum kra anda bem lenta se o as nossas
//checagens ficassem todas num loop ia atrapalhar o andamento
//de todo servidor por isso criamos um novo processo com o fork
//ele se comunica com o pai claro mas a coisa nao e tao simples
//assim agora vou escrever um aplicativo interativo pra ser jogado
//entre no minimo 3 pessoas um servidor e dois clientes
////pra gente testar todas as singularidades espero
//que essa parte da trasnmissao ja lhe seja util de algo
//qualquer coisa sabe como me encontrar
//comando pra compilar $gcc servidor.c -o servidor
//mais uma coisa isso nao ta funcionando corretamente
//pois c os 5 servidores tiverem conectados ao mesmo tempo
//ele so vai ler o Next que e cinco isso e um problema com
//o fork que eu to tentando resolver eu queria uma fariavel
//que so fosse assecivel pelo processo filho atraves do PID..

particularmente prefiro o SDL_net é multiplataforma e mais simples de se usar.
nem estou pensando em multiplayer agora, só to publicando o que ta no bau.

A Quantas anda a Engine

Venho trazer noticias do que ando aprontando com a engine, primeiro tive um grande martirio tentando implementar os shaders mas bem após horas cansativas escrevendo coisas como

!!ARBvp1.0 "
PARAM mvp[4] = { state.matrix.mvp }
PARAM yellow = {1.0,1.0,0.0,0.0};
OUTPUT outPosition = result.position;
MOV result.color, vertex.color;
DP4 outPosition.x, mvp[0], vertex.position;
DP4 outPosition.y, mvp[1], vertex.position;
...

Sem debug, sem nem mesmo um analisador lexico para mostrar onde estão os erros, foram horas divertidas eu diria mas enfim estudei as equações do Dr. Phong e implementei algo deveria ser um Per Pixel Ligthing





Tambem fiz modificações no que é pra ser um Sistema de Particulas temos a representação de uma Explosão classe Explosion que é Herdeira de ParticleSystem e enfim comecei a criar a classe ParticleManager, imaginem um bombardeiro de um B-52 a cada bomba que geraria uma explosão, adicionariamos uma instancia de Explosion a ParticleManager e ela gerenciaria os sistemas.





Agora estou pensando em um terreno não tenho mais como fugir das joints do ODE e de um gameplay.

O diagrama de classe nem todas estão implementadas.






Nas próximas semanas atualizo o SVN.

quarta-feira, julho 15, 2009

AJAX + JQuery II

Olá pessoal, nesse tutorial vamos usar Ajax para consumir Web Services, no exemplo demonstrado temos uma classe de acesso a dados para fazer o cadastro e a listagem no banco de dados que é um uma database .mdf do SQL Server Express 2005, o Web Service é utilizado como Proxy com a classe de acesso a dados. Consumimos Web Services por javascript através de uma classe chamada SoapClient ela e de autoria de Matteo Casati , mas tive que dar uma pequena hackeada nela pois a mesma não funcionava no FireFox (ao menos no meu).


Agora vamos ao trabalho Crie um novo Web site, no diretório AppData adicione um SQL Database File, de o nome de Contatos.mdf. adicione a tabela abaixo.



O campo id é a chave primaria com auto increment, nome é varchar(50) e telefone varchar(15).

Adicione Tb uma procedure para cadastrar e outra para listagem, segue o código das mesmas.

Cadastro




CREATE PROCEDURE dbo.usp_insereContato

(
@nome varchar(50),
@telefone varchar(15)
)

AS
insert into Contatos (nome,telefone) values (@nome,@telefone)
RETURN

Listagem




CREATE PROCEDURE dbo.usp_listagemContatos
AS
select id,nome,telefone from Contatos
RETURN

Essas são as procedures nada de mirabolante dispensa comentários, sem seguida a classe em .cs que representa um contato





using System;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
using System.Web;
using System.Collections.Generic;
/// <summary>
/// Summary description for Contato
/// </summary>

[Serializable]
public class Contato
{
private int id;

public int Id
{
get { return id; }
set { id = value; }
}
private string nome;

public string Nome
{
get { return nome; }
set { nome = value; }
}
private string telefone;
public string Telefone
{
get { return telefone; }
set { telefone = value; }
}

public Contato(string nome, string telefone)
{
this.nome = nome;
this.telefone = telefone;
}
public Contato()
{

}
public static List<Contato> Listar()
{
List<Contato> contatos = new List<Contato>();
using (SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString))
{
SqlCommand command = new SqlCommand();
command.Connection = connection;
command.CommandType = System.Data.CommandType.StoredProcedure;
command.CommandText = "usp_listagemContatos";


connection.Open();
SqlDataReader dr = command.ExecuteReader();
while (dr.Read())
{
Contato contato = new Contato();
contato.id = Convert.ToInt32(dr["id"]);
contato.nome = Convert.ToString(dr["nome"]);
contato.telefone = Convert.ToString(dr["telefone"]);
contatos.Add(contato);
contato = null;
}

connection.Close();
}

return contatos;
}

public static bool Cadastrar(string nome, string telefone)
{
try
{
using (SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString))
{
SqlCommand command = new SqlCommand();
command.Connection = connection;
command.CommandType = System.Data.CommandType.StoredProcedure;
command.CommandText = "usp_insereContato";
command.Parameters.Add(new SqlParameter("@nome", nome));
command.Parameters.Add(new SqlParameter("@telefone", telefone));

connection.Open();
command.ExecuteNonQuery();
connection.Close();

return true;
}
}
catch
{
return false;
}
return false;
}
}

Logo acima temos propriedades com o nome e o telefone logo em seguida um método de cadastro e listagem, adicione esta classe no diretório APP_CODE com o nome Contato.cs

Passamos agora para o Web Service é a parte mais graciosa da coisa toda realmente lindo adicione um novo Web Service e batize o mesmo de wsContatos.asmx e adicione os dois métodos abaixo





[WebMethod]
public bool Cadastrar(string nome, string telefone)
{
return Contato.Cadastrar(nome, telefone);
}

[WebMethod]
public List<Contato> Listar()
{
return Contato.Listar();
}

Perceberam com os métodos são simples basicamente são uma ponte ou Proxy, para a camada de negócios (sei que não temos uma camada de negócios mais esta é a idéia), o motivo que coloquei o [Serializable], neste caso nossos atributos públicos são automaticamente convertidos para um XML válido para a resposta do Web Service a resposta gerada é esta:





<?xml version="1.0" encoding="utf-8" ?>
<ArrayOfContato xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://tempuri.org/">
<Contato>
<Id>1</Id>
<Nome>Gabriel</Nome>
<Telefone>123456</Telefone>
</Contato>
<Contato>
<Id>2</Id>
<Nome>Chuck Norris</Nome>
<Telefone>666</Telefone>
</Contato>
<Contato>
<Id>3</Id>
<Nome>Shaolin Monk</Nome>
<Telefone>999</Telefone>
</Contato>
<Contato>
<Id>4</Id>
<Nome>Grande Cã</Nome>
<Telefone>777</Telefone>
</Contato>
</ArrayOfContato>

Lindo não? Agara vamos para o aspx você vai precisar do SoapClient do italiano maluco, a versão que eu fiz uma pequena modificação se encontra aqui mas primeiro adicione os controles HTML





<div>
<label>
Nome:</label><span><input type="text" id="txtNome" /></span><br />
<label>
Telefone:</label><input type="text" id="txtTelefone" /><br />
<div>
<span>
<input type="button" id="btnCadastrar" value="Cadastrar" onclick="CadastraContato();"/>
</span><span>
<input type="button" id="btnListar" value="Listar" onclick="Listar()" /></span>
</div>
<div id="listagem">

</div>
</div>




GO Javascript:





<script type="text/javascript" src="soapclient.js"></script>

<script type="text/javascript">
function CadastraContato()
{
var nome = document.getElementById('txtNome').value;
var telefone = document.getElementById('txtTelefone').value;

var parametros = new SOAPClientParameters();
parametros.add('nome',nome);
parametros.add('telefone',telefone);

SOAPClient.invoke("wsContatos.asmx", "Cadastrar", parametros, true, function (data){

if (data == true)
{
alert('Contato Cadastrado com sucesso');
}
else
{
alert('Houve um problema ao cadastrar o contato');
}

});

}

O que cada coisa faz
var parametros = new SOAPClientParameters();
este instancia o objeto responsável de guardar a lista de parâmetros para nossa chamada
parametros.add('nome',nome);
parametros.add('telefone',telefone);
adiciona os parametos .add(nome,valor) a lista de parâmetros (nossa!)
SOAPClient.invoke("wsContatos.asmx", "Cadastrar", parametros, true, function (data){
Invoke(url,método,parâmetros,sicrono/asincrono,callback)
Eu recebo a resposta de confirmação em data o response na verdade
Passamos paro o listar








function Listar()
{
SOAPClient.invoke("wsContatos.asmx", "Listar", new SOAPClientParameters(), true, function (data){

var count = data.length;
var html = "";
for (i = 0;i < count ; i++)
{
html += "<span> Nome: "+data[i].Nome+" Telefone: "+data[i].Telefone+"</span><br/>";

}

var dv = document.getElementById('listagem');
dv.innerHTML = html;

});

}

Aqui eu Invoquei o método listar o SOAPClient me retornou uma coleção de objetos contendo os contatos, ai tem for e um HTML tosco, badabum a mágica esta pronta e é isso espero que seja útil.

Você pode fazer o download do código do tuto aqui.


quinta-feira, junho 25, 2009

Operações com vetor usando SSE

Olá pessoal depois de fuçar com o vertex_program/fragment program, descobri o SIMD
(Single Instruction, Multiple Data), o que isso siginifica.

imagine que temos o vetor a = [x,y,z,w] e b = [x,y,z,w], quando vamos fazer uma operação do tipo c = a * b o processo seria este.

c.x = a.x * b.x;
c.y = a.y * b.y;
c.z = a.z * b.z;
c.w = a.w * b.w;

o disassembly deste processo no MSVC++ 2005

c.x = a.x * b.x;
0041197E fld dword ptr [a]
00411981 fmul dword ptr [b]
00411984 fstp dword ptr [c]
c.y = a.y * b.y;
00411987 fld dword ptr [ebp+10h]
0041198A fmul dword ptr [ebp+20h]
0041198D fstp dword ptr [ebp-10h]
c.z = a.z * b.z;
00411990 fld dword ptr [ebp+14h]
00411993 fmul dword ptr [ebp+24h]
00411996 fstp dword ptr [ebp-0Ch]
c.w = a.w * b.w;
00411999 fld dword ptr [ebp+18h]
0041199C fmul dword ptr [ebp+28h]
0041199F fstp dword ptr [ebp-8]

o gcc é bem mais inteligente que isso (to no maldito windows agora)

a mesma operação usando SSE, nos dois caso eu não coloquei a parte responsável por pegar os parametros passados p/ a função e o seu retorno.
o abaixo foi escrito p/ o nasm

mov eax, [ebp+0x8] ;parametro 1 a
mov ebx, [ebp+0xc] ;parametro 2 b
mov ecx, [ebp+0x10] ;parametro 3 c

movups xmm0, [eax] ;coloca eax em xmm0
movups xmm1, [ebx] ;coloca ebx em xmm1
mulps xmm0, xmm1 ; xmm0 = xmm0 * xmm1
movups [ecx], xmm0 ;move xmm0 ecx (c)

creio que iriamos economizar alguns ciclos de processamento, então SSE é isto fazer operações com registradores de 128bits (16 bytes).

pra mais informações na comunidade tem bastante informação, os manuais da intel IA-32 2A e IA-32 2B tem o conjunto de instrução completo.

o 3DNow da amd e o altiVec do PowerPC tem o mesmo propósito, até o ARM tem um conjunto de instruções vetorias, você pode ser bem criativo ao usar esse conjunto de instruções, por exemplo o memcpy copia 4 bytes de cada vez (ao menos no header que eu vi), usando registradores de 128bits poderiamos mover 16bytes por vez, interessante não.

coloquei exemplos no link : http://www.mediafire.com/?sharekey=75c36d37bd6d2c0a391d7d881749d3a7e04e75f6e8ebb871

matematica.zip -> VC++ 2005
vectors.zip -> GCC + nasm

uma curiosiade é que este é o segredo do PS3 (CELL/B.E) ele tem um porcessador PowerPC (PPE) e 6 processadores (SPE), atualmente o Top 1 da top500.org o RoadRunner tem alguns milhares deste (CELL/B.E).

se eu falei alguma besteira favor me corrigir.

veja a Parte II.

Obrigado.

quarta-feira, junho 03, 2009

Pato Life Style

O jaca a um tempo atrás foi a um parque e Curitiba, e tirou uma foto muito singular de um pato na lagoa, o pato estava tranquilo fintando uma HB na lagoa, depois da foto do pato gerar muita polemica nas nossas discussões por e-mail percebemos toda filosofia em volta daquele pato pense bem na paz e tranquilidade do pato em sua lagoa fintando a duck HB, é esse tipo de coisa que quero pra minha vida a partir dai surgiu a filosofia do PATO Life Style. olhe a imagem e pense um pouco sobre isso.





só tenho a recomendar pratique o PATO Life Style.

terça-feira, junho 02, 2009

Newbie Game Engine o que ta no forno

Pessoal boas novas consegui dar Suporte a ARB_vertex_program e ARB_fragment_program
e os dois funcionarão no linux (w32 sucks), agora vou fazer o tão famoso Cel Shading e deixar minha CPU livre pro ODE fazer o trabalho dele.>/p>


Vou começar também o estudo de mapas vou seguir essa técnica

só depois tenho que pensar na parte de Texturas mesmo se for toon shading ainda vai precisar, tenho que organizar o código padronizar algumas coisas e acho que ja é hora de dividir em namespaces mais isso são contos futuros. A parte de física ta meio abandonada e vai ficar por um tempo vou me concentrar na parte gráfica.

Até mais.