quarta-feira, 30 de abril de 2014

mygl.h (Trabalho II)

#ifndef _MYGL_H_
#define _MYGL_H_
//#define RAND_MAX 0xFF

#include "definitions.h"
#include "math.h"
#include "stdio.h"
#include "iostream"
using namespace std;

//*****************************************************************************
// Defina aqui as suas funções gráficas
//*****************************************************************************

//*************************************

struct scor {
  short R = 255 , G = 255, B = 255, A = 255;
};

//*************************************

struct sponto{
  short x, y;
  scor cor;
};

//*************************************

struct slinha{
  sponto p1, p2;
};

//*************************************

struct striang{
  sponto p1, p2, p3;
};

//*************************************
//*************************************
//*************************************

class cVetor{
private:
 
public:
  float m[4][1] = {{0},{0},{0},{0}};

  //cria um vetor4x1.
  // chamado sem parametros gera um vetor de zeros
  // com 3 parametros gera um vetor homogeneo

//--------------------------------------

  cVetor(){
  };

//--------------------------------------

  cVetor(float x, float y, float z){
      m[0][0] = x;
      m[0][1] = y;
      m[0][2] = z;
      m[0][3] = 1;
  };
};

//*************************************

class TMatriz{
private:
  char tipo; // identificador do tipo de matriz
  short lin, col; //define dimensoes da matrix
  float m[4][4] = {{0, 0, 0, 0 },{0, 0, 0, 0},{0, 0, 0, 0 },{0, 0, 0, 1}};
 
public:
  //cria uma matriz 4x4. Tipo define se a matriz eh 's', 't', 'z' ou 'i'
  // t - translacao
  // s - scale
  // i - identidade
  // z - zeros

//--------------------------------------

  TMatriz(float x, float y, float z, char tipo ){
    if(tipo == 's'){
      m[0][0] = x;
      m[1][1] = y;
      m[2][2] = z;
    }
    else if(tipo == 't'){
      m[0][0] = 1;
      m[1][1] = 1;
      m[2][2] = 1;
      m[0][3] = x;
      m[1][3] = y;
      m[2][3] = z;
    }
    else if(tipo == 'i'){
      m[0][0] = 1;
      m[1][1] = 1;
      m[2][2] = 1;
      m[3][3] = 1;
    }
    else if(tipo == 'z'){
      m[3][3] = 0;
    }
    else{
      cout << "Tipo de matriz invalido. Abortando a execucao.";
      exit(0);
    }
    this->tipo = tipo;     
  };

//--------------------------------------

  char getTipo(){
    return tipo;
  };

//--------------------------------------

  TMatriz vezes(TMatriz m2){
    // multiplica a matriz atual por outra informada
    TMatriz MResultado(0,0,0,'z');
   
    for(short i = 0; i < 4; i++){
      for(short j = 0; j < 4; j++){
    for(short n = 0; n < 4; n++) 
     MResultado.m[i][j] = MResultado.m[i][j] + this->m[i][n] * m2.m[n][j];
      }
    }
    return MResultado;
  };

//--------------------------------------

  cVetor vezes(cVetor m2){
    // multiplica a matriz atual por outra informada
    cVetor MResultado;
   
    for(short i = 0; i < 4; i++){
      for(short n = 0; n < 4; n++) 
    MResultado.m[i][0] = MResultado.m[i][0] + this->m[i][n] * m2.m[n][0];
    }
    return MResultado;
  };
};

//*************************************

class cponto{
  //cria um ponto canonico
private:
  float x, y, z;
  scor cor;

//--------------------------------------

  void valida( void){
    // valida x, y , e z e cor
    // faz, mas no final os valores são substituidos por algo aleatorio
   
    if(x < -1.0f || x > 1.0f){
      cout << "Coordenadas canonicas devem estar entre -1 e 1. \n Ajustado x para 0.\n";
      x = 0.0f;
    }

    if(y < -1.0f || y > 1.0f){
      cout << "Coordenadas canonicas devem estar entre -1 e 1. \n Ajustado y para 0.\n";
      y = 0.0f;
    }
   
    if(z < -1.0f || z > 1.0f){
      cout << "Coordenadas canonicas devem estar entre -1 e 1. \n Ajustado z para 0.\n";
      z = 0.0f;
    }
     
    if(cor.R < 0 || cor.R > 255){
      cout << "Valores de cor devem estar entre 0 e 255. \n Ajustando R para 255\n";
      cor.R = 255;
    }
    if(cor.G < 0 || cor.G > 255){
      cout << "Valores de cor devem estar entre 0 e 255. \n Ajustando G para 255\n";
      cor.G = 255;
    }
    if(cor.B < 0 || cor.B > 255){
      cout << "Valores de cor devem estar entre 0 e 255. \n Ajustando B para 255\n";
      cor.B = 255;
    }
     cor.A = 0;
   }
 
public:

//--------------------------------------

  cponto(){
    //construtor sem parametros
    cout << "Digite as coordenadas e cor do ponto: \n    x:";
    cin >> x;
    cout << "    y:";
    cin >> y;
    cout << "    z:";
    cin >> z;
    cout << "    R:";
    cin >> cor.R;
    cout << "    G:";
    cin >> cor.G;
    cout << "    B:";
    cin >> cor.B;
    cor.A = 255;
    valida();
  };

//--------------------------------------

  cponto(float x, float y){
    //construtor com parametros x e y. z recebe 0 e cor será branco
    z = 0;
    cor.R = 255;
    cor.G = 255;
    cor.B = 255;
    cor.A = 255;
    valida();
  };

//--------------------------------------

  cponto(float x, float y, float z){
    //construtor com parametros x e y. z recebe 0 e cor será branco
    cor.R = 255;
    cor.G = 255;
    cor.B = 255;
    cor.A = 255;
    valida();
  };

//--------------------------------------

  cponto(float x1, float y1, float z1, short R, short G, short B){
    //construtor com todos os parametros de coordenada e cor
    cor.R = R;
    cor.G = G;
    cor.B = B;
    cor.A = 255;
    this->x = x1;
    this->y = y1;
    this->z = z1;
    valida();
  };

//--------------------------------------

  void setPoint(float x1, float y1, float z1, short R, short G, short B){
    this->x = x1;
    this->y = y1;
    this->z = z1;
    cor.R = R;
    cor.G = G;
    cor.B = B;
  }

//--------------------------------------

  sponto getTpoint(){
    sponto ponto;
   
    TMatriz mTrans(256, 256, 0, 't'); // matriz de translacao de 0 para 256 para x e y

    TMatriz mTemp(0, 0, 0, 'z'); // cria uma matriz auxiliar para armazenamento de resultados
   
    TMatriz mScale(256, 256, 1,'s'); //matriz que amplia a figura nos eixos x e y
   
    TMatriz mFlip(1, -1, 1, 's'); //cria uma matriz de escala que mantem x e inverte y
   
    mTemp = mScale.vezes(mFlip);
    mTemp = mTrans.vezes(mTemp);
   
    cVetor cCanon(x,y,z);
    cVetor cTela = mTemp.vezes(cCanon);

    ponto.x = (int)cTela.m[0][0];
    ponto.y = (int)cTela.m[0][1];
    ponto.cor.R = cor.R;
    ponto.cor.G = cor.G;
    ponto.cor.B = cor.B;
   
    return(ponto);
  }; 
};

//*************************************
//*************************************
//*************************************

  sponto GeraPonto(void){
  char title[50];
  sponto ponto;

  ponto.cor.R = rand() &  0x00FF; //gera proporcao de red com os 8 bits menos significativos de rand
  ponto.cor.G = rand() &  0x00FF; //gera proporcao de green
  ponto.cor.B = rand() &  0x00FF; //gera proporcao de blue
  ponto.cor.A = 255; //gera proporcao de alpha

  ponto.x = rand() & 0x01FF ; //gera coordenada x do ponto entre 0 e tamanho da tela openGL
 
  ponto.y = rand() & 0x01FF; //gera coordenada y do ponto entre 0 e tamanho da tela openGL

  //Gera texto do titulo com o proximo ponto a ser plotado
  sprintf(title, "Proximo ponto: %d x %d  Cor: %x%x%x", ponto.x, ponto.y, ponto.cor.R, ponto.cor.G, ponto.cor.B);

  glutSetWindowTitle(title);  // Apresenta o texto na barra de titulo da janela
 
  return ponto;
}

//*************************************

slinha GeraLinha(void){
  char title[50];
  slinha linha;

  linha.p1 = GeraPonto(); //gera o primeiro ponto da linha
  linha.p2 = GeraPonto(); //gera o segundo ponto da linha
 
  //Gera texto do titulo com o proximo ponto a ser plotado
  sprintf(title, "Proxima linha: %d x %d  a  %d x %d", linha.p1.x, linha.p1.y, linha.p2.x, linha.p2.y);

  glutSetWindowTitle(title);  // Apresenta o texto na barra de titulo da janela
 
  return linha;
}

//*************************************

striang GeraTriang(void){
  char title[50];
  striang triang;

  triang.p1 = GeraPonto(); //gera o primeiro ponto do triang
  triang.p2 = GeraPonto(); //gera o segundo ponto
  triang.p3 = GeraPonto(); //gera o terceiro ponto
 
  //Gera texto do titulo com o proximo ponto a ser plotado
  sprintf(title, "Proximo triangulo: %d x %d, %d x %d,  %d x %d", triang.p1.x, triang.p1.y, triang.p2.x, triang.p2.y, triang.p3.x, triang.p3.y);

  glutSetWindowTitle(title);  // Apresenta o texto na barra de titulo da janela
 
  return triang;
}

//*************************************

void PutPixel(sponto ponto){

    FBptr[(ponto.y * IMAGE_WIDTH * 4) + 4 * ponto.x +  0]  = ponto.cor.R;
    FBptr[(ponto.y * IMAGE_WIDTH * 4) + 4 * ponto.x +  1]  = ponto.cor.G;
    FBptr[(ponto.y * IMAGE_WIDTH * 4) + 4 * ponto.x +  2]  = ponto.cor.B;
    FBptr[(ponto.y * IMAGE_WIDTH * 4) + 4 * ponto.x +  3]  = ponto.cor.A;
}
 
//*************************************

void DrawLine(slinha linha)
{
  sponto pAux;
  short inc_n, inc_ne, inc_e, inc_se, inc_s, inc_y, d, dx, dy,  quadrante;
  float m, inc_r, inc_g, inc_b, R, G, B;

  //Se o x do ponto inicial for menor que o x do ponto final, inverte os pontos
  //e reduz os casos para apenas 2 quadrantes
  if (linha.p1.x > linha.p2.x)
  {
      pAux = linha.p2;
      linha.p2 = linha.p1;
      linha.p1 = pAux;
  }       
  dx = linha.p2.x - linha.p1.x;
 
  //resolve o problema de dx = 0
  if(dx == 0){
    short i, ini, fim;
    if(linha.p1.y > linha.p2.y){
      ini = linha.p2.y;
      fim = linha.p1.y;
    }
    else{
      ini = linha.p1.y;
      fim = linha.p2.y;
    }
    for(i = ini; i <= fim; i++){
      pAux.x = linha.p1.x;
      pAux.y = i;
      pAux.cor.R = linha.p1.cor.R;
      pAux.cor.G = linha.p1.cor.G;
      pAux.cor.B = linha.p1.cor.B;
      PutPixel(pAux);

    }
   
    return;
  }
 
  dy = linha.p2.y - linha.p1.y;
   
  m = dy / dx; // 0.0001 evita divisão por 0

  if(m < -1)
    quadrante = 7;
  else if (-1 <= m && m < 0)
    quadrante = 8;
  else if ( 0 <= m && m <= 1)
    quadrante = 1;
  else
      quadrante = 2;
     
  if(dy > 0)
    inc_y = 1;
  else
  {  inc_y = -1;
    dy = -dy;
  }

  d = 2 * dy - dx;
 
  inc_n = 2 * (-dx);
  inc_ne = 2 * (dy - dx);
  inc_e = 2 * dy;
 
  // incremento de cor
  if(dx != 0){
    inc_r = (float)(linha.p2.cor.R - linha.p1.cor.R)/(dx);
    inc_g = (float)(linha.p2.cor.G - linha.p1.cor.G)/(dx);
    inc_b = (float)(linha.p2.cor.B - linha.p1.cor.B)/(dx);
  }
  else{
    inc_r = 0;
    inc_g = 0;
    inc_b = 0;
  }

  // plota o primeiro ponto
  pAux.x = linha.p1.x;
  pAux.y = linha.p1.y;
  R = linha.p1.cor.R;
  G = linha.p1.cor.G;
  B = linha.p1.cor.B;
 
  PutPixel(pAux);
//  cout << quadrante << "\n";

    short cont, lim;
    while( pAux.x <= linha.p2.x)
    {
      if (d <= 0)
      {
    switch (quadrante)
    {
      case 1 :
        d += inc_e;
        pAux.x ++;
        R += inc_r;
        G += inc_g;
        B += inc_b;
        break;
      case 2 :
        d += inc_ne;
        pAux.x ++;
        pAux.y += inc_y;
        R += inc_r;
        G += inc_g;
        B += inc_b;
        break;
      case 7 :
        d -= inc_n;
        pAux.y += inc_y;
        //pAux.x ++;
        break;
      case 8 :
        d -= inc_ne;
        pAux.x ++;
        pAux.y += inc_y;
        R += inc_r;
        G += inc_g;
        B += inc_b;
        break;
    }
      }
      else
      {
    switch (quadrante)
    {
      case 1 :
        d += inc_ne;
        pAux.x ++;
        pAux.y += inc_y;
        R += inc_r;
        G += inc_g;
        B += inc_b;
        break;
      case 2 :
        d += inc_n;
        pAux.y += inc_y;
        //pAux.x ++;
        break;
      case 7 :
        d -= inc_ne;
        pAux.x ++;
        pAux.y += inc_y;
        R += inc_r;
        G += inc_g;
        B += inc_b;
        break;
      case 8 :
        d -= inc_e;
        pAux.x ++;
        R += inc_r;
        G += inc_g;
        B += inc_b;
        break;
    }
      }
      pAux.cor.R = R;
      pAux.cor.G = G;
      pAux.cor.B = B;
      PutPixel(pAux);
    }
}

//*************************************

void DrawTriangle(striang triang)
{
  slinha linha;
 
  linha.p1 = triang.p1;
  linha.p2 = triang.p2;
  DrawLine(linha);
 
  linha.p1 = triang.p2;
  linha.p2 = triang.p3;
  DrawLine(linha);
 
  linha.p1 = triang.p1;
  linha.p2 = triang.p3;
  DrawLine(linha);
}

//*************************************

void FillTriang(striang triang)
{
  sponto pFix, pAux;
  slinha linha, fill;
  short inc_n, inc_ne, inc_e, inc_se, inc_s, inc_y, d, dx, dy,  quadrante;
  float m, inc_r, inc_g, inc_b, R, G, B;
 
  linha.p1 = triang.p1;
  linha.p2 = triang.p2;
  pFix = triang.p3;
 
  //Se o x do ponto inicial for menor que o x do ponto final, inverte os pontos
  //e reduz os casos para apenas 2 quadrantes
  if (linha.p1.x > linha.p2.x)
  {
      pAux = linha.p2;
      linha.p2 = linha.p1;
      linha.p1 = pAux;
  }       
  dx = linha.p2.x - linha.p1.x;
  dy = linha.p2.y - linha.p1.y;

  m = dy / (dx + 0.0001); // 0.0001 evita divisão por 0
 
  if(m < -1)
    quadrante = 7;
  else if (-1 <= m && m < 0)
    quadrante = 8;
  else if ( 0 <= m && m <= 1)
    quadrante = 1;
  else
      quadrante = 2;
     
  if(dy > 0)
    inc_y = 1;
  else
  {  inc_y = -1;
    dy = -dy;
  }

  d = 2 * dy - dx;
 
  inc_n = 2 * (-dx);
  inc_ne = 2 * (dy - dx);
  inc_e = 2 * dy;
   
  // incremento de cor
  inc_r = (float)(linha.p2.cor.R - linha.p1.cor.R)/dx;
  inc_g = (float)(linha.p2.cor.G - linha.p1.cor.G)/dx;
  inc_b = (float)(linha.p2.cor.B - linha.p1.cor.B)/dx;

  // plota o primeiro ponto
  pAux.x = linha.p1.x;
  pAux.y = linha.p1.y;
  R = linha.p1.cor.R;
  G = linha.p1.cor.G;
  B = linha.p1.cor.B;
 
//  PutPixel(pAux);

    short cont, lim;
    while( pAux.x <= linha.p2.x)
    {
      if (d <= 0)
      {
    switch (quadrante)
    {
      case 1 :
        d += inc_e;
        pAux.x ++;
        R += inc_r;
        G += inc_g;
        B += inc_b;
        break;
      case 2 :
        d += inc_ne;
        pAux.x ++;
        pAux.y += inc_y;
        R += inc_r;
        G += inc_g;
        B += inc_b;
        break;
      case 7 :
        d -= inc_n;
        pAux.y += inc_y;
        break;
      case 8 :
        d -= inc_ne;
        pAux.x ++;
        pAux.y += inc_y;
        R += inc_r;
        G += inc_g;
        B += inc_b;
        break;
    }
      }
      else
      {
    switch (quadrante)
    {
      case 1 :
        d += inc_ne;
        pAux.x ++;
        pAux.y += inc_y;
        R += inc_r;
        G += inc_g;
        B += inc_b;
        break;
      case 2 :
        d += inc_n;
        pAux.y += inc_y;
        break;
      case 7 :
        d -= inc_ne;
        pAux.x ++;
        pAux.y += inc_y;
        R += inc_r;
        G += inc_g;
        B += inc_b;
        break;
      case 8 :
        d -= inc_e;
        pAux.x ++;
        R += inc_r;
        G += inc_g;
        B += inc_b;
        break;
    }
      }
      pAux.cor.R = R;
      pAux.cor.G = G;
      pAux.cor.B = B;

      fill.p1 = pFix;
      fill.p2 = pAux;
     
      DrawLine(fill);
    }
}

//*************************************


#endif // _MYGL_H_

Nenhum comentário:

Postar um comentário