Projeto Virtual Worlds

Computação Gráfica 3D em C

Arquivos Mensais: julho 2011

Problema de resolução (complicada?!)

Uma das coisas que tenho visto em códigos-exemplo usando OpenGL é que não há quaisquer preocupações com o aspect ratio do monitor. Isto é, pouca atenção é dada ao fato do monitor ser wide screen ou letter box. A diferença entre os dois formatos é muito grande.

Letter box sobre Wide screen

Wide screen sobre Letter box


Num monitor com geometria letter box, o pixel é quadrado para o formato letter box. Mas, um formato wide screen embutido numa geometria letter box causa uma deformação nos pixels, achatando-os no sentido horizontal… Isso porque, no formato wide screen, o pixel é quadrado para a geometria wide screen, mas, no formato letter box, embutido, o pixel fica mais “alto” do que largo.

As figuras assumem que os pixels serão quadrados em ambas as geometrias e formatos, mas, para isso, parte da área útil do monitor é “perdida”. Você já deve ter visto esse efeito quando assiste DVDs numa TV com geometria letter box e o filme é wide screen (causando o que é mostrado na segunda figura) ou quando assiste canais de TV aberta, não HD, numa TV wide screen (causando o que é mostrado na primeira figura).

O Virtual Worlds tentará, sempre que possível, usar o formato da segunda figura – isso porque, neste caso, a “perda” da área é menor que no primeiro caso… No segundo caso (Wide screen over Letter Box), há uma perda de 25% da área e este caso é mais familiar para o usuário do que o primeiro. No primeiro caso, a perda chega próxima à 33% da tela (repare na barra escura mais “grossa” – as figuras estão em escala!).

A rotina, em pseudo-código, ficaria assim:

Obtém o aspect-ratio da geometria do monitor;
Se é Wide screen, usa a tela toda;
Se é Letter box, usa 75% da tela, como mostrado na segunda figura.

Para manter o código portável, teremos 3 rotinas diferentes para determinar a geometria do monitor: Uma para o Linux, uma para o Windows e outra para o OS/X (supondo que o BSD use método diferente do Linux).

Além disso, dois métodos podem ser usados para desenhar, quando a geometria for Letter Box: Uma é usando valores apropriados para a rotina glViewport; Outra é usando o stencil buffer, mascarando as áreas superior e inferior da tela.

Assim que eu tiver essas rotinas up and running, posto aqui pra vocês verem…

Anúncios

What’s the plan, doc?

Um plano é definido, na geometria, como uma superfície que contém todos os pontos definidos pela equação:

Ax + By + Cz - D = 0

Os coeficientes A, B e C correspondem ao vetor normal do plano (o vetor unitário perpendicular ao plano). E o coeficiente D corresponde à distância do plano em relação à origem do sistema de coordenadas, projetada sobre o vetor normal.

Calcular os coeficientes do plano é bem simples se vocẽ tiver 3 pontos definidos sobre ele (um triângulo, por exemplo):

vn'(A',B',C') = (v2 - v1) × (v3 - v2) 
vn = (A, B, C) = vn' / |vn'|
D = vn · v1

A primeira equação assume que os pontos v1, v2 e v3 sejam definidos de forma ordenada. Lembre-se que o produto vetorial depende da ordem com que os vetores sejam usados. Na equação acima os pontos que compõem o triângulo, acima, têm que ser definidos no sentido anti-horário! Para entender isso, basta usarmos a regra da mão direita, mostrada no último post:

Desconstruindo um triângulo

Onde v21 é o vetor calculado pelos pontos (v2 – v1) e v32 é (v3 – v2). Os pontos v1 até v3 foram nomeados assim depois que eu já tinha preparado a figura acima. Minha intenção era nomeá-los p1 até p3 (hehe)…

A idéia dos vetores formados pelos pontos no sentido anti-horário resolve alguns problemas em computação gráfica: Podemos, seguramente, garantir que o vetor normal da “frente” do polígono aponta para o observador e, se isso não acontece, quer dizer que o polígono está voltado para o lado contrário da câmera, ficando invisível.

Voltando à equação do plano, os primeiros 3 coefientes correspondem às coordenadas do vetor normal do triângulo que está sobre o plano. Por isso usamos o produto vetorial (vn’) e depois dividimos o resultado pelo comprimento do vetor encontrado (vn). De posse desse vetor normal (que indica a direção em que está a “frente” do plano) podemos usar qualquer ponto que se encontra sobre o plano para calcular o tamanho da projeção deste ponto sobre o vetor normal, calculando assim, a menor distância entre o plano e a origem do sistema de coordenadas.

Parece complicado, mas, de fato, é bem simples: Os 3 pontos que definem o nosso triângulo estão, necessariamente, sobre o plano, mas o tamanho do vetor determinado por um desses pontos e a origem do sistema de coordenadas não é, necessariamente, a menor distância entre o plano e a origem. A única maneira de obtermos essa menor distância é projetando o vetor correspondente a qualquer um dos pontos do triângulo sobre o vetor normal (continua complicado, né?).

Ok, já temos a nossa equação do plano onde está o nosso polígono. O que fazer com isso? Com essa equação podemos calcular a distância entre um ponto e o plano simplesmente substituindo os valores de x, y e z, na equação. Se tivéssemos uma equação assim:

z - 3 = 0

Ou seja, o vetor normal do plano é (0,0,1) e o plano encontra-se à 3 unidades longe da origem. Se quisermos saber a distância entre o plano e o ponto (1,2,3), basta substituir o z na equação e teremos uma distância de zero! Quer dizer, o ponto (1,2,3) está sobre o plano (de fato, qualquer ponto com z=3 estará, não é óbvio?).

Mas, se o ponto estiver em (2,4,5), então ele estará “na frente” do plano à uma distância de 2 unidades (está “na frente” porque a distância deu positiva!).

Um exemplo mais completo seria com um vetor normal mais “completo”. Por exemplo: (0.5774, 0.05774, 0.5774) e a distância do plano à origem de 3 unidades, por exemplo… A equação ficaria:

0.5774x + 0.5774y + 0.5774z - 3 = 0

Calculei o vetor normal a partir de um vetor de coordenadas (1,1,1). O valor 0.5774 é uma aproximação grosseira, mas dá pra ilustrar uma equação mais completa. Se os 3 componentes forem, por exemplo, √3, o ponto estará sobre o plano. A mesma coisa acontece se x = y = 0 e z = 3√3. Aliás, este é o ponto o nde o plano toca cada um dos eixos (3√3, 0, 0); (0, 3√3, 0) e (0, 0, 3√3)…

Muito bonito tudo isso, mas a aplicação prática virá bem mais tarde, quando surgir a necessidade de falarmos de particionamento espacial (veja um resumo neste artigo, no Bit Is Myth).

typedef float plane_t[4];

void planeFromTriangle(plane_t p, 
                       const vec3_t p1, const vec3_t p2, const vec3_t p3)
{
  vec3_t vn;
  vec3_t v21, v32;
  float d;

  vector3Subtract(v21. p2, p1);
  vector3Subtract(v32, p3, p2);
  vector3Cross(vn, v21, v32);
  vector3Normalize(vn, vn);
  d = -vector3Dot(vn, p1);

  p[0] = vn[0];
  p[1] = vn[1];
  p[2] = vn[2];
  p[3] = d;
}

float planeDistanceFromPoint(const plane_t p, vec3_t v)
{
  return (p[0]*v[0]) +
         (p[1]*v[1]) +
         (p[2]*v[2]) +
         p[3]; 
}

Pontos (e vetores) de vista

Não vou insultar a inteligência e a experiência de vocês explicando o que é um ponto, uma reta, um segmento de reta… Mas vou mostrar alguns detalhes que podem ter escapado a atenção: Por exemplo, um vetor não é um segmento de reta no sentido em que ele tenha um ponto de origem e um de destino. Um vetor é todos os segmentos de reta possíveis, no espaço, que tenha um tamanho e uma direção específicos.

Muitos de nós aprendemos sobre vetores com um gráfico como este:

Um segmento de reta e um vetor…

A segunda representação mostra somente como calcular um vetor. Mas não significa que ele tenha a origem no ponto b e o seu destino no ponto a. Um vetor é definido da mesma maneira que um ponto no espaço: Por 3 números, correspondendo aos tamanhos projetados nos 3 eixos do sistema de coordenadas (x, y, z). Assim, um vetor v com “coordenadas” (0,0,1) não nos diz nada sobre sua origem e seu destino, mas nos diz sobre o seu tamanho e direção. Esse vetor tem tamanho de uma unidade e está alinhado ao sentido positivo do eixo z (lembra dos sistemas de coordenadas descritos no post anterior?).

Vocês já viram como calcular o tamanho de um vetor no espaço bidimensional, basta usar o teorema de Pitágoras. No espaço tridimensional é a mesma coisa, basta adicionar mais uma coordenada:

\displaystyle length=\sqrt{x^2+y^2+z^2}

Onde x, y e z são os tamanhos das projeções do vetor nos eixos x, y e z, do sistema de coordenadas!

Cálculo com vetores também é muito fácil:

Adição e subtração:

\displaystyle (x',y',z')=(x_2,y_2,z_2)+(x_1,y_1,z_1)=(x_2+x_1,y_2+y_1,z_2+z_1)
\displaystyle (x',y',z')=(x_2,y_2,z_2)-(x_1,y_1,z_1)=(x_2-x_1,y_2-y_1,z_2-z_1)

Multiplicação por constante (ou “escalonamento”):

\displaystyle (x',y',z')=c(x,y,z)=(cx,cy,cz)

A coisa complica (e fica mais interessante) quando chegamos à multiplicação entre vetores. Existem, basicamente, duas maneiras de multiplicação de vetores:

a) O produto escalar

Conhecido, em inglês, como dot product. A idéia é obter o cosseno do ângulo entre dois vetores, de acordo com a equação abaixo:

\displaystyle \cos\theta=\frac{\vec{a}\cdot\vec{b}}{|\vec{a}||\vec{b}|}

Ou seja:

\displaystyle \vec{a}\cdot\vec{b}=|\vec{a}||\vec{b}|\cos\theta

Se um dos vetores é unitário, tenha tamanho igual a 1, o produto escalar te dará o tamanho da projeção de um vetor qualquer sobre o vetor unitário:

A projeção de ‘a’ sobre ‘b (unitário)’ é o produto escalar

Existe uma forma mais fácil de calcular o produto escalar que não envolve o cosseno:

\displaystyle \vec{a}\cdot\vec{b}=x_ax_b+y_ay_b+z_az_b

Como veremos em outros artigos, existem aplicações bem práticas para o produto escalar, como o cálculo de distância entre um ponto e um plano.

b) O Produto vetorial

Diferente do produto escalar, o resultado do produto vetorial (conhecido como cross product, em inglês) é um vetor. O produto vetorial é usado para calcular duas coisas. O vetor perpendicular aos dois vetores da operação e a área delineada pelos vetores:

a x b é o vetor resultante do produto vetorial.

Estamos particularmente interessados no cálculo do vetor perpendicular… Esse vetor (perpendicular a dois outros), quando tem tamanho unitário (igual a 1) é conhecido como vetor normal do plano contendo os vetores originais (\vec{a} e \vec{b}, acima. E \vec{a}\times\vec{b} seria o vetor normal se for unitário). Quanto ao cálculo da área delineada pelos vetores \vec{a} e \vec{b}, basta dar uma olhada na área do paralelogramo definido pelos vetores:

\displaystyle |\vec{a}\times\vec{b}|=|\vec{a}||\vec{b}|\sin\theta

No entanto, essa área não nos interessa, por enquanto…

A ordem com que os vetores \vec{a}\vec{b} são considerados na operação é importante, de fato, \vec{b}\times\vec{a}=-\vec{a}\times\vec{b}, ou seja, se inverter a ordem da operação você obterá um vetor de mesmo tamanho, mas em sentido contrário. E aqui entra a famosa regra da mão direita. Para determinar o sentido do vetor resultante:

O produto vetorial de x e y será z, apontando na direção do dedão!

Repare que os dedos que “abraçam” o vetor z “passam” primeiro por x e depois por y, indicando tanto o sentido do vetor resultante, quanto o sentido do produto de x por y. Se você mudar o sentido do “abraço” (de y para x) verá que o seu dedão apontará para baixo.

O produto vetorial pode ser calculado através da determinante:

\displaystyle \vec{a}\times\vec{b}=\det\begin{bmatrix}\vec{i}&\vec{j}&\vec{k}\\x_a&y_a&z_a\\x_b&y_b&z_b\end{bmatrix}

Onde \vec{i}\vec{j}\vec{k} são vetores unitários alinhados com os eixos x, y e z. Ou, de uma forma mais procedural:

\vec{a}\times\vec{b}=(y_az_b-y_bz_a, z_ax_b-z_bx_a, x_ay_b - x_by_a)

O produto vetorial é um dos motivos pelos quais usamos triângulos como construções geométricas primitivas para montar objetos, já que três pontos estão, garantidamente, no mesmo plano e dois vetores podem ser calculados a partir de três pontos.

Colocando tudo em rotinas…

#ifndef VECTOR3_H
#define VECTOR3_H
/* vector3.h */

typedef float vec3_t[3];
typedef float (*vec3_p)[3];

void  vector3Add(vec3_t result, const vec3_t v1, const vec3_t v2);
void  vector3Subtract(vec3_t result, const vec3_t v1, const vec3_t v2);
void  vector3Scale(vec3_t result, const vec3_t v, float scale);
void  vector3Invert(vec3_t result, const vec3_t v);
float vector3Length(const vec3_t v);
void  vector3Normalize(vec3_t result, const vec3_t v);
float vector3Dot(const vec3_t v1, const vec3_t v2)
void  vector3Cross(vec3_t result, const vec3_t v1, const vec3_t v2)

#endif
/* vector3.c */
#include <math.h>
#include "vector3.h" 

void vector3Add(vec3_t result, const vec3_t v1, const vec3_t v2)
{
  result[0] = v1[0] + v2[0];
  result[1] = v1[1] + v2[1];
  result[2] = v1[2] + v2[2];
}

void  vector3Subtract(vec3_t result, const vec3_t v1, const vec3_t v2)
{
  result[0] = v1[0] - v2[0];
  result[1] = v1[1] - v2[1];
  result[2] = v1[2] - v2[2];
}

void vector3Scale(vec3_t result, const vec3_t v, float scale)
{
  result[0] = v[0] * scale;
  result[1] = v[1] * scale;
  result[2] = v[2] * scale;
}

void  vector3Invert(vec3_t result, const vec3_t v)
{
  result[0] = -v[0];
  result[1] = -v[1];
  result[2] = -v[2];
}

float vector3Length(const vec3_t v)
{
  return sqrtf(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
}

/* Calcula o vetor unitário com base em um vetor qualquer. */
void vector3Normalize(vec3_t result, const vec3_t v)
{
  float len = vector3Length(v);

  /* Neste ponto seria mais correto fazer:
       if (fabs(len) > FLT_EPSILON) */
  if (len != 0.0f)
  {
    len = 1.0f / len;

    result[0] = v[0] * len;
    result[1] = v[1] * len;
    result[2] = v[2] * len;
  }
}

/* Calcula o produto escalar */
float vector3Dot(const vec3_t v1, const vec3_t v2)
{
  return ((v1[0]*v2[0]) +
          (v1[1]*v2[1]) +
          (v1[2]*v2[2]));
}

/* Calcula o produto vetorial */
void vector3Cross(vec3_t result, const vec3_t v1, const vec3_t v2)
{
  result[0] = v1[1]*v2[2] - v1[2]*v2[1];
  result[1] = v1[2]*v2[0] - v1[0]*v2[2];
  result[2] = v1[0]*v2[1] - v1[1]*v2[0]; 
}

O espaço… a fronteira final…

A primeira coisa que temos que entender quando estamos falando de geometria é sobre os sistemas de coordenadas. Todos estamos familiarizados com o sistema cartesiano de coordenadas bidimensional:

Sistema cartesiano.

Os valores da dimensão x estão todos no sentido horizontal e os da dimensão y, no vertical. Os números em algarismos romanos I, II, III e IV indicam os quadrantes do sistema. Esse é um dos sistemas de coordenadas usados em computação gráfica… O outro, adiciona uma linha, perpendicular as duas outras. É o componente z do sistema cartesiano tridimensional:

Adicionando o eixo z no sistema de coordenadas 2D, tornando-o 3D.

Este é o outro sistema de coordenadas, dessa vez, tridimensional. Qualquer ponto neste sistema é definido por três valores: A ordenada x, a absissa y e a coordenada z. Podemos escrever isso na forma (x,y,z).

Nada mais simples… Só repare que o sentido positivo de cada um dos eixos é determinado por convenções. O x não precisa, necessariamente, crescer para a direita. Assim como o y não precisa crescer, necessariamente, para cima e o z, na direção de quem vê (imagine o plano formado pelos eixos x e y como sendo o plano do seu monitor de vídeo). Acontece que, por padrão, OpenGL assume essa configuração. O ponto de origem (0, 0) no plano da tela (portanto, bidimensional) está no canto inferior esquerdo e, como veremos mais tarde, ao desenhar um objeto com o seu centro num ponto z negativo, este parecerá estar mais longe do observador.

Esas convenções podem ser mudadas e veremos como fazer isso num outro post, mas vou me ater ao padrão por motivos de simplicidade.

OpenGL usa esses dois sistemas de coordenadas, mas usa espaços diferentes. Existe o espaço do objeto (ou do modelo, chamado de object coordinates)), o espaço do mundo (eye coordinates) — que pode ser entendido como o espaço do universo — ambos são 3D, mas também existe o espaço do recorte (clip coordinates) e outro espaço que é 2D (o da “janela” ou window coordinates) que corresponde ao plano da tela, onde os objetos serão projetados.

Espaços e transformações geométricas

O motivo por haverem vários espaços tridimensionais é que os objetos são definidos como tendo seus centros na origem do sistema de coordenadas (3D). Isso quer dizer que todos os pontos (vértices) de um objeto são definidos em relação ao ponto (0,0,0). Quando o objeto for colocado no mundo (ou no “universo”, no espaço do “olho”), o centro será movido (e os vértices que definem o objetos são “arrastados” junto com ele!). Então, parece lógico que exista um sistema de coordenadas próprio para a definição dos objetos e outro sistema diferente que colocarmos os objetos nele…

Depois que todos os objetos (definidos no espaço dos objetos) forem movidos (transladados), rotacionados, escalonados, ou seja, transformados no espaço do universo, será preciso projetá-los no plano do vídeo (que é 2D) e, portanto, este espaço (o do recorte) é diferente do espaço universo…

Existem outros “epaços”, no OpenGL… Espaço de texturas, por exemplo, mas você não tem que se preocupar com isso ainda. Acostume-se à idéia de que existem espaços diferentes para definir os objetos, que é diferente do espaço onde eles serão colocados e que existe outro espaço onde os objetos do mundo (ou universo) serão projetados, para dar a ilusão de 3D:

  • Object or Model Space (3D): Onde os objetos são definidos;
  • World, Universe ou Eye Space (3D): Onde os objetos serão colocados e transformados;
  • Clipping Space (2D): Onde os objetos do “mundo” serão “recortados” e apenas suas partes visíveis são aproveitadas;
  • Window ou Viewport space:  Onde os objetos são projetados no plano da tela.

A maneira de converter um ponto (ou vértice) de um espaço para outro é através do uso de matrizes, no OpenGL. Para transformar os vértices do espaço do objeto para o espaço do universo (ou “do olho”), multiplica-se as coordenadas do vértice pela matriz Model/View. Para transformar os vértices do espaço do universo para o espaço de recorte, multiplica-se pela matriz de projeção…

Notem que eu não falei nada sobre o espaço “Normalizado”, no desenho acima. Isso fica pra depois…

À seguir: Pontos, segmentos-de-reta e vetores.

Primeiras decisões

O projeto surgiu com a idéia de desenvolver um ambiente 3D onde eu pudesse modelar o “mundo real” e vender um “jogo” baseado neste modelo. Uso a palavra jogo aqui como ponto de entendimento comum do que o sistema fará. Quer dizer, o usuário poderá passear pelos mundos virtuais (daí o nome do projeto), interagindo como se estivesse num jogo de tiro em primeira pessoa (FPS).

Inicialmente o engine não tem suporte para web. Na medida que HTML5 vai amadurecendo e o WebGL for sendo suportado, poderei pensar em maneiras de portar a engine. A decisão inicial é esta: A engine funcionará como um jogo, sem suporte para web.

A segunda decisão importante é o ambiente o desenvolvimento do sistema será feito. Há anos venho tentando encontrar um ambiente que possa ser altamente portável. Java e outras linguagens gerenciáveis não me atraem (lembrem-se que sou um HPJ – High Performance Junkie), embora pudesse ser uma escolha óbvia do ponto de vista da portabilidade. Também não me sinto atraído pelo ambiente de janelas da Microsoft ou seus compiladores porque seria uma maneira de manter o produto final restrito a um único ambiente, indo contra a corrente de minha intenção.

O ambiente Linux (especialemnte o Ubuntu, derivado da distribuição Debian) me permite desenvolver para as três maiores plataformas atuais: Linux, Windows e OS/X, através de um conjunto de ferramentas que foram originalmente desenvolvidas para um port do Unix chamado GNU/Hurd e que foi adotado pelo Linux com perfeição. Sendo assim, a segunda decisão é óbvia: O ambiente de desenvolvimento será o Linux, por causa do projeto GNU, especialmente do compilador GCC (que é multiplataforma!).

Meu ambiente de software para o desenvolvimento do projeto é bem singelo e pode ser usado por qualquer pessoa:

  • Linux (Ubuntu);
  • GCC 4.5.2 ou superior;
  •  GDB 7.2 ou superior;
  • Placa de vídeo nVidia série 8 ou superior (com suporte, pelo menos, ao OpenGL 2.1);
  • Editor: VIM 7,3 iy superior;

Neste início de projeto usarei apenas uma biblioteca auxiliar para o gerenciamento de contextos do OpenGL e de janelas. Trata-se do GLFW (GL FrameWork), que é bem mais simples do que o SDL, pode ser linkado estaticamente e apresenta algumas rotinas simples para o manuseio de janelas (ou seja, do framebuffer), teclado, mouse e joystick. Na minha opinião o SDL é muito lento e tem alguns bugs esquisitos com o Linux. Exceto por essa interface simples com o hardware, toda a interação gráfica entre o engine e a placa de vídeo será feita via OpenGL.

Outras bibliotecas serão usadas no projeto: ZLib, libpng, libjpeg, libxml2, … Mas, à medida que forem sendo usadas, apresentarei os requisitos mínimos e as alternativas no Windows e no OS/X (quando possível).

Outra coisa: Este não é um projeto de curta duração. Existe muita estrada para trilhar. A intenção é, como em qualquer projeto complexo, começar simples e ir adicionando grandes features na medida que eu for andando, mas isso leva tempo, esforço e estudos. E uma dose cavalar de paciência também. Sem contar que este é, até o momento, um projeto de um homem só (eu!). Tenho que lidar com um monte de coisas ao mesmo tempo só para este projeto: Aprender a modelar objetos (no Blender 2.5), dissecar códigos feitos por outros (que é uma excelente maneira de aprender), rever disciplinas como Algebra Linear, Geometria Analítica, Equações diferenciais (alguns efeitos interessantes, em 3D, precisam dessa base), rever/reaprender algorítimos clássicos como árvores binárias (e seus diversos tipos)… Dá pra dar uma canseira!

Em que ponto do projeto estou?! Ainda no início… por isso ainda não “soltei” nenhum código-fonte ainda (ahhhh…. sim… pretendo que o projeto seja Open Source!). No momento preciso arrumar um jeito de importar uma cena, usando o Blender, agregando os planos divisores e portais numa BSP Tree. Estou estudando modelamento de objetos e ainda decidindo sobre o padrão que usarei para exportar as cenas (Collada? X3D? Quake MAP? ou será proprietário?!).

Nos próximos posts falarei do embasamento matemático necessário para você começar a pensar em 3D. Um pouquinho de algebra vetorial…

A new begining…

Com o encerramento das atividades do Lost in the e-Jungle começo um novo projeto, bem mais técnico e menos filosófico. Há algum tempo venho estudando e criando módulos para um projeto que chamei pelo codinome Virtual Worlds — ênfase no codinome porque não quero ferir os direitos autorais de ninguém, caso um projeto como este já exista — trata-se de um engine 3D para criação de “jogos” totalmente escrito em C e, eventualmente, com algumas pequenas partes em assembly.

É claro que existem diversos engines por ai que são bastante robustos. Só que esses engines pecam em dois aspectos que são muito importantes para mim:

  1. Documentação pobre;
  2. São feitos em C++ ou alguma linguagem com recursos de orientação à objetos

Tentei mesmo usar ferramentas como o Crystal Space, Ogre 3D e outros, mas sempre esbarro no problema (1), acima. Quanto ao fato de serem desenvolvidos em C++, não existem grandes problemas com relação a isso, exceto que eu sou uma espécie de high performance junkie.

Este é um blog de acompanhamento do projeto e de coisas que eu for assimilando no caminho para o desenvolvimento do projeto. Para aqueles que estão acompanhando os textos publicados no Bit Is Myth, saibam que continuarei escrevendo por lá. Aqui a minha dedicação é ao meu projeto…

Como é de se esperar, dada as características de um projeto deste tamanho, passarei algum tempo estudando antes de criar algum post importante. Esperem um delay grande entre posts, ok?

[]s
Frederico Lamberti Pissarra