Tutorial Processing+NyARToolkit

1 – Preparar o Processing.

– Caso não possua, instale a última versão estável do processing (versão 1.5). A versão 2.0, no sistema operativo windows, produz alguns error de compilação nos exemplos fornecidos com a biblioteca NYar.

– Descarregue a última versão do NyARTOOLKIT disponível na página do projecto:
http://sourceforge.jp/projects/nyartoolkit/releases/?package_id=8920

– No windows, localize o directório onde são instaladas as bibliotecas do Processing.
C:\Users\USERNAME\Documents\Processing\libraries\

– Copie a pasta nyar4psg para o interior do directório libraries. Atenção, não esquecer de remover o número da versão do nome da pasta.

– Instale também, no directório libraries, a biblioteca para aquisição de vídeo gsvideo a partir da página do projecto:
http://gsvideo.sourceforge.net/
Esta biblioteca vídeo, no sistema operativo windows, é bastante mais estável do que a nativa do processing.

– O vídeo do processing basea-se na tecnologia Quicktime, que não é suportada por alguns fabricantes de webcams no windows, pelo que, pode ser necessário instalar um programa adicional.
Veja mais sobre este assunto no seguinte tópico.
Em alguns casos poderá ter de instalar a versão 101 do programa winVidig em lugar da mais recente.


 

2- Instalar o paternMaker

A biblioteca NyART contém uma pasta com exemplos (examples), uma com documentação em língua japonesa (reference) e outra com os dois fiduciais usados nos exemplos (data). Alguns tutoriais com alguma documentação em lingua inglesa estão disponíveis online:
Dr. J.B. Hayet

Ao abrir a pasta data encontramos cada um dos fiduciais em dois formatatos distintos:
   – em PDF, que é usado para imprimir em papel a imagem do fiducial
      pattHiro.pdf
      pattKanji.pdf
   – em formato patt que são recohecidos pelo código no processing
      patt.hiro
      patt.kanji

Apesar dos exemplos fornecidos pela biblioteca NyART usarem apenas este dois fiduciais, a maior parte dos projectos de Realidade Aumentada envolvem ceários em que têm que estar presentes vários fiduciais em simultâneo. Por essa razão é aconselhada a instalação do pacote PaternMaker que oferece um conjunto de ferramentas e recursos para gerir e criar dezenas de fiduciais.

– Descarregue o paternMaker
http://www.cs.utah.edu/gdc/projects/augmentedreality/

– O paternMaker consiste numa pasta que deverá ser copiada para a raíz da biblioteca NyART que se encontra na localização das libraries do processing.

Dentro do directório PaternMaker/examples encontrará um conjunto de recursos que permitem explorar todas as vantagens de cenários que envolvem a interacção com vários fiduciais simultaneamente. A pasta gif contém 100 ficheiros de imagem numerados já prontas para impressão. Para cada ficheiro de imagem gif existe um ficheiro corresondente em formato patt na pasta ARToolkit_Paterns. Este últimos são necessários para incorporar no código, uma vez que o processing e a biblioteca NyART recorrem a este tipo de ficheiros implementar os algoritmos de visão por computador resposáveis pelo reconhecimento dos fiduciais.


 

3- imprimir os fiduciais

– Recorte uma cartolina ou cartão com cerca de 30x10cm.

– Dobre ao meio.

– Imprima os dois fiduciais com as seguinte medidas que se encontram na pasta data.
      pattHiro.pdf 3cm
      pattKanji.pdf 5cm

– Cole cada um dos fiduciais em cada uma das páginasda cartolina dobrada ao meio.

– Execute e explore os exemplos fornecidos pela biblioteca:
File->Examples->Contributed Libraries->nyar4psg


 

4- exemplo de um globo interactivo

O próximo exemplo implementa uma animação do globo terrestre (fiducial hiro) em que a sua velocidade de rotação pode ser controlada a partir do botão (fiducial kanji)

– Crie um novo projecto no Processing, grave e atribua-lhe o nome Globo.

– Na pasta data uma copie os ficheiros patt.hiro, patt.kanji e camera_para.dat (estes ficheiro estão disponiveis na pasta data de um qualquer exemplo disponivel na pasta de exemplos da biblioteca).

– Copie ainda, para a pasta data, o ficheiro da textura do globo. Certifique-se que é gravado com o nome world32k.jpg.

– Copie e execute o seguinte código no Processing. Sempre que pressionar o fiducial kanji o globo irá rodar a lata velocidade.


import codeanticode.gsvideo.*; // the GSVideo library
//import processing.video.*;
import jp.nyatla.nyar4psg.*;
import processing.opengl.*;

boolean bt=false;
boolean oldbt=false;

PFont font=createFont("FFScala", 32);
GSCapture cam;
MultiMarker nya;

void setup() {
  size(640,480,P3D);
    texmap = loadImage("world32k.jpg");    
  initializeSphere(sDetail);
  
  //colorMode(RGB, 255);
  cam=new GSCapture(this,width,height);
    cam.start(); // start capturing
  nya=new MultiMarker(this,width,height,"camera_para.dat",new NyAR4PsgConfig(NyAR4PsgConfig.CS_RIGHT_HAND,NyAR4PsgConfig.TM_NYARTK));
  nya.setARClipping(100,1000);
  nya.setConfidenceThreshold(0.4);
  nya.addARMarker("patt.hiro",80);
  nya.addARMarker("patt.kanji",80);
  nya.addNyIdMarker(31,80);
  println(nya.VERSION); //バージョンの表示
}
int c=0;
void draw() {
  c++;
  if (cam.available() !=true) {
    return;
  }
  background(255);
  cam.read();

  nya.drawBackground(cam);
  nya.detect(cam);
  
  
  
  if(nya.isExistMarker(0)){
    nya.beginTransform(0);
    {
      drawBox(0,0,0);
      //drawMarkerXYPos(0);
      renderGlobe(); 
    }
    nya.endTransform();  
    //drawMarkerPatt(0);
    //drawVertex(0);

    PVector p=nya.marker2ScreenCoordSystem(0,0,0,0);
    noFill();
    ellipse(p.x,p.y,200,200);
  }
  
  println("----" + c + "---" + bt);
  if(nya.isExistMarker(1)){
    if (!bt) {
      velocityY = 150;
    };
    bt=true;


    nya.beginTransform(1);
    {
      //drawBox(255,255,0);
      //drawMarkerXYPos(1);
    }
    nya.endTransform(); 
    //drawMarkerPatt(1);
    drawVertex(1);
  }else{
   bt=false; 
  }
  
}
void drawBox(int ir,int ig,int ib)
{
  pushMatrix();
  //drawgrid();
  
  fill(ir,ig,ib);
  stroke(100,100,0);
  translate(0,0,20);
  //box(40);
  
  stroke(200,200,0);
  noFill();
    fill(0,0,0);
  translate(0,0,-20);
  rect(-40,-40,80,80); 
  popMatrix();
}


void drawMarkerPatt(int id)
{
  PImage p=nya.pickupMarkerImage(id,
    40,40,
    -40,40,
    -40,-40,
    40,-40,
    100,100);
//  PImage p=nya.pickupRectMarkerImage(id,-40,-40,80,80,100,100);
  image(p,id*100,0);
}


void drawMarkerXYPos(int id)
{
  pushMatrix();
    PVector pos=nya.screen2MarkerCoordSystem(id,mouseX,mouseY);
    translate(pos.x,pos.y,0);
    noFill();
    stroke(0,0,100);
    ellipse(0,0,20-c%20,20-c%20);
  popMatrix();
}

void drawVertex(int id)
{
  PVector[] i_v=nya.getMarkerVertex2D(id);
  textFont(font,10.0);
  stroke(100,0,0);
  for(int i=0;i<4;i++){
    fill(100,0,0);
    ellipse(i_v[i].x,i_v[i].y,6,6);
    fill(0,0,0);
    text("("+i_v[i].x+","+i_v[i].y+")",i_v[i].x,i_v[i].y);
  }
}

void drawgrid()
{
  pushMatrix();
  stroke(0);
  strokeWeight(2);
  line(0,0,0,100,0,0);
  textFont(font,20.0); text("X",100,0,0);
  line(0,0,0,0,100,0);
  textFont(font,20.0); text("Y",0,100,0);
  line(0,0,0,0,0,100);
  textFont(font,20.0); text("Z",0,0,100);
  popMatrix();
}


PImage bg;
PImage texmap;

int sDetail = 30;  // Sphere detail setting
float rotationX = 90;
float rotationY = 0;
float velocityX = 0;
float velocityY = 150;
float globeRadius = 130;
float pushBack = 70;

float[] cx, cz, sphereX, sphereY, sphereZ;
float sinLUT[];
float cosLUT[];
float SINCOS_PRECISION = 0.5;
int SINCOS_LENGTH = int(360.0 / SINCOS_PRECISION);


void renderGlobe() {
  pushMatrix();
  translate(0, 0, pushBack);
  scale(0.5);
  pushMatrix();
  noFill();
  stroke(255,200);
  strokeWeight(0);
  smooth();
  popMatrix();
  //lights();    
  pushMatrix();
  rotateX( radians(-rotationX) );  
  rotateY( radians(270 - rotationY) );
  fill(200);
  noStroke();
  textureMode(IMAGE);  
  texturedSphere(globeRadius, texmap);
  popMatrix();  
  popMatrix();
  rotationX += velocityX;
  rotationY += velocityY;
  velocityX *= 0.95;
  velocityY *= 0.95;
  
  // Implements mouse control (interaction will be inverse when sphere is  upside down)
  if(mousePressed){
    velocityX += (mouseY-pmouseY) * 0.01;
    velocityY -= (mouseX-pmouseX) * 0.01;
  }
}

void initializeSphere(int res)
{
  sinLUT = new float[SINCOS_LENGTH];
  cosLUT = new float[SINCOS_LENGTH];

  for (int i = 0; i < SINCOS_LENGTH; i++) {
    sinLUT[i] = (float) Math.sin(i * DEG_TO_RAD * SINCOS_PRECISION);
    cosLUT[i] = (float) Math.cos(i * DEG_TO_RAD * SINCOS_PRECISION);
  }

  float delta = (float)SINCOS_LENGTH/res;
  float[] cx = new float[res];
  float[] cz = new float[res];
  
  // Calc unit circle in XZ plane
  for (int i = 0; i < res; i++) {
    cx[i] = -cosLUT[(int) (i*delta) % SINCOS_LENGTH];
    cz[i] = sinLUT[(int) (i*delta) % SINCOS_LENGTH];
  }
  
  // Computing vertexlist vertexlist starts at south pole
  int vertCount = res * (res-1) + 2;
  int currVert = 0;
  
  // Re-init arrays to store vertices
  sphereX = new float[vertCount];
  sphereY = new float[vertCount];
  sphereZ = new float[vertCount];
  float angle_step = (SINCOS_LENGTH*0.5f)/res;
  float angle = angle_step;
  
  // Step along Y axis
  for (int i = 1; i < res; i++) {
    float curradius = sinLUT[(int) angle % SINCOS_LENGTH];
    float currY = -cosLUT[(int) angle % SINCOS_LENGTH];
    for (int j = 0; j < res; j++) {
      sphereX[currVert] = cx[j] * curradius;
      sphereY[currVert] = currY;
      sphereZ[currVert++] = cz[j] * curradius;
    }
    angle += angle_step;
  }
  sDetail = res;
}

// Generic routine to draw textured sphere
void texturedSphere(float r, PImage t) 
{
  int v1,v11,v2;
  r = (r + 240 ) * 0.33;
  beginShape(TRIANGLE_STRIP);
  texture(t);
  float iu=(float)(t.width-1)/(sDetail);
  float iv=(float)(t.height-1)/(sDetail);
  float u=0,v=iv;
  for (int i = 0; i < sDetail; i++) {
    vertex(0, -r, 0,u,0);
    vertex(sphereX[i]*r, sphereY[i]*r, sphereZ[i]*r, u, v);
    u+=iu;
  }
  vertex(0, -r, 0,u,0);
  vertex(sphereX[0]*r, sphereY[0]*r, sphereZ[0]*r, u, v);
  endShape();   
  
  // Middle rings
  int voff = 0;
  for(int i = 2; i < sDetail; i++) {
    v1=v11=voff;
    voff += sDetail;
    v2=voff;
    u=0;
    beginShape(TRIANGLE_STRIP);
    texture(t);
    for (int j = 0; j < sDetail; j++) {
      vertex(sphereX[v1]*r, sphereY[v1]*r, sphereZ[v1++]*r, u, v);
      vertex(sphereX[v2]*r, sphereY[v2]*r, sphereZ[v2++]*r, u, v+iv);
      u+=iu;
    }
  
    // Close each ring
    v1=v11;
    v2=voff;
    vertex(sphereX[v1]*r, sphereY[v1]*r, sphereZ[v1]*r, u, v);
    vertex(sphereX[v2]*r, sphereY[v2]*r, sphereZ[v2]*r, u, v+iv);
    endShape();
    v+=iv;
  }
  u=0;
  
  // Add the northern cap
  beginShape(TRIANGLE_STRIP);
  texture(t);
  for (int i = 0; i < sDetail; i++) {
    v2 = voff + i;
    vertex(sphereX[v2]*r, sphereY[v2]*r, sphereZ[v2]*r, u, v);
    vertex(0, r, 0,u,v+iv);    
    u+=iu;
  }
  vertex(sphereX[voff]*r, sphereY[voff]*r, sphereZ[voff]*r, u, v);
  endShape();
  
}


 
 
 

Anúncios