Android Open Source - TicTacToe3D T T T3d View Selector






From Project

Back to project page TicTacToe3D.

License

The source code is released under:

MIT License

If you think the Android project TicTacToe3D listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/**
 * Classe que desenha as posi??es do jogo da velha 3D
 *  com cores diferentes para viabilizar a 
 *  sele??o pelo mouse.// w ww  .j a va2s  .  c  o  m
 *  
 *  Tamb?m possibilita a visuliza??o durante a sele??o
 * 
 */
package com.unibh.dcet.ccc.android.tictactoe3d.view;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import javax.microedition.khronos.opengles.GL10;

import com.unibh.dcet.ccc.android.tictactoe3d.ai.DotAI;
import com.unibh.dcet.ccc.android.tictactoe3d.ai.Environment;
import com.unibh.dcet.ccc.android.tictactoe3d.ai.Line;

/**
 * Classe que faz a transforma??o entre um ponto na tela (VIEW)
 * e uma posi??o do tabuleiro (MODEL)
 * 
 *  Tamb?m faz o desenho do destaque durante a sele??o.
 * 
 */
public class TTT3dViewSelector {

  private FloatBuffer vertexBuffer;  // Buffer for vertex-array
  private int nVertices;
  private int dimensao;
  private float unidade;
  private float unidadeY;
  // margem de erro na convers?o de cores (infelizmente, valor emp?rico)
  static final private int margemErroCor = 10;
  // M?xima dimens?o baseada na identifica??o de cores
  static final public int maxDim = (255 / (margemErroCor * 2));

  // mostra linhas diagonais
  private boolean showDiagonalLines = false;
  
  /**
   * 
   */
  public TTT3dViewSelector(int dimension, float unit, float unitY) {
    this.dimensao = dimension;
    this.unidade = unit;
    this.unidadeY = unitY;
    // 
    nVertices = 4*3;
    float[] vertices;
    vertices = new float[nVertices];

    float u = unidade;
    
    vertices[0] = 0; vertices[1]  = 0; vertices[2]  = 0;
    vertices[3] = u; vertices[4]  = 0; vertices[5]  = 0;
    vertices[6] = 0; vertices[7]  = 0; vertices[8]  = u;
    vertices[9] = u; vertices[10] = 0; vertices[11] = u;
    
    
    // Setup vertex array buffer. Vertices in float. A float has 4 bytes
    ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);
    vbb.order(ByteOrder.nativeOrder()); // Use native byte order
    vertexBuffer = vbb.asFloatBuffer(); // Convert from byte to float
    vertexBuffer.put(vertices);         // Copy data into buffer
    vertexBuffer.position(0);           // Rewind  

  }
  
  public void setShowDiagonalLines(boolean showDiagonalLines) {
    this.showDiagonalLines = showDiagonalLines;
  }

  /**
   * Seleciona uma posi??o do modelo na proje??o da imagem 
   */
  public int[] pick(GL10 gl, int pX, int pY, int screenHeight) {

    // transforma a coordenada do buffer na coordenada da tela
    // pois a imagem do buffer openGL come?a (posi??o 0,0) 
    // pelo lado inferior e a tela come?a pelo lado superior
    pY = (int)(screenHeight - pY);
  
    // garante as configura??es do OpenGL 
    // deve ativar a profundidade para evitar sobreposi??o de cores
    gl.glEnable(GL10.GL_DEPTH_TEST);
    gl.glClearDepthf(1.0f);          //Depth Buffer Setup
    gl.glDepthFunc(GL10.GL_LEQUAL);  //The Type Of Depth Testing To Do
    
        gl.glDisable(GL10.GL_BLEND);
        gl.glDisable(GL10.GL_DITHER);                   
        gl.glDisable(GL10.GL_FOG);
        gl.glDisable(GL10.GL_LIGHTING);                         
        gl.glDisable(GL10.GL_TEXTURE_2D);               
        gl.glShadeModel(GL10.GL_FLAT);

        gl.glDisable(GL10.GL_CULL_FACE);
        gl.glDisable(GL10.GL_COLOR_MATERIAL);
        
        // limpa o buffer
        gl.glClearColor(0.0f,0.0f,0.0f,0.0f);
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
        // Enable vertex-array and define its buffer
    gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
    // inicia a trasnferencia dos buffers
    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
        // prepara as vari?veis
    float red, green, blue;
    int dx, dy, dz;
    int fator = (int)(255f/(float)dimensao);
    for (dx = 0; dx < dimensao; dx++) {
      for (dz = 0; dz < dimensao; dz++) {
        for (dy = 0; dy < dimensao; dy++) {
          // calcula a cor para identifica??o ?nica
          /*
          //int fatorBinario = 0xFFFF/dimensao;
          gl.glColor4x((dx+1) * fatorBinario, 
                   (dy+1) * fatorBinario, 
                   (dz+1) * fatorBinario, 0xFFFF);
          */
          red   = ((float)(dx+1) / (float)dimensao);
          green = ((float)(dy+1) / (float)dimensao);
          blue  = ((float)(dz+1) / (float)dimensao);
          gl.glColor4f(red, green, blue, 1f);
          // desenha a posi??o na cor de identifica??o
          drawAt(gl, dx, dy, dz);
        }
      }
    }
    gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
    // aloca o buffer para receber os dados das cores (apenas um pixel RGBA)
    ByteBuffer pixel = ByteBuffer.allocateDirect(4);
    pixel.order(ByteOrder.nativeOrder());
    // l? o buffer
    gl.glReadPixels((int)pX, (int)pY, 1, 1, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, pixel);
    // tansfere para um vetor de bytes
    byte[] b = new byte[4];
    pixel.get(b);
      // faz a convers?o para inteiro
    int[] pos = new int[3];
      int i;
      for (i = 0; i < 3; i++ ) {
        // transforma byte para inteiro garantindo apenas os 8 primeros bits
        pos[i] = (int)b[i] & 0xff;
        // se o n?mero for negativo, gera uma rodada de bits
        if (pos[i] < 0) pos[i] += 256;
        // retira a imprecis?o das cores geradas (float->int)
        pos[i] -= margemErroCor;
      }
      // converte para os ?ndices de cores originais (?ndice -1 significa sem cor)
      for (i = 0; i < 3; i++ ) {
        // se a cor ? zero ou menor
        if (pos[i] <= 0) {
          // n?o est? no tabuleiro
          pos[i] = -1; 
        } else {
          // obt?m o ?ndice da cor
            pos[i] = (pos[i]/fator);
            // se passou do limite, ? a m?xima dimens?o
            if (pos[i] >= dimensao)
              pos[i] = (dimensao - 1);
        }
      }
    // limpa o buffer atual (usado apenas para sele??o)
    gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
    return pos;
  }

  
  /**
   * Desenha uma posi??o do tabuleiro 
   */
  private void drawAt(GL10 gl, int x, int y, int z) {
        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
    // salva as matrizes do openGL
    gl.glPushMatrix();  
    // translada para o ponto inicial do plano
    gl.glTranslatef((x * unidade), (y * unidadeY), (z * unidade));
    // Draw the primitives from the vertex-array directly
    gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, nVertices / 3);
    // restaura as matrizes
    gl.glPopMatrix();
        gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
  }

  
  /**
   * desenha uma diaginal no meio 
   */
  public void drawDiaginalMeio(GL10 gl, int cx, int cz) {
    int dz = (cz == 1 ? 0: dimensao - 1);
    int dx = (cx == 1 ? 0: dimensao - 1);
    for (int dy = 0; dy < dimensao; dy++) {
      drawAt(gl, dx, dy, dz);
      dz += cz;
      dx += cx;
    }
  }
  
  /**
   * desenha um destaque na posi??o do modelo com todas as poss?veis linhas de vit?ria
   */
  public void previewVictoryLines(GL10 gl, int[] pos, float[] color, boolean previewLines, Environment env) {
        // define o buffer de v?ertices
    gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
    // desenha ambos os lados
    gl.glDisable(GL10.GL_CULL_FACE);
    // define a fun??o de transpar?ncia
    gl.glEnable(GL10.GL_BLEND);
    gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
    // define a cor com o fator alfa de transpar?ncia
    gl.glColor4f(color[0],color[1],color[2],0.5f);
    // se deve desenhar linhas de destaque
    if (previewLines) {
      gl.glColor4f(0,1,0,0.5f);
      DotAI dotBase = env.getDotAI(pos[1], pos[2], pos[0]);
      for (Line l: dotBase.getPossibleLines()) {
        for (DotAI dot: l.getLines()) {
          drawAt(gl, dot.getCol(), dot.getPlane(), dot.getLin());
        }
      }
    } else {
      // ou sen?o, detaca apenas a posi??o selecionada
      drawAt(gl, pos[0], pos[1], pos[2]);
    }
    
    // restaura a fun??o de transpar?ncia
    gl.glBlendFunc(GL10.GL_ONE, GL10.GL_ZERO);
  }
  
  /**
   * desenha um destaque na linha informada
   */
  public void previewLine(GL10 gl, float[] color, Line line) {
        // define o buffer de v?ertices
    gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
    // desenha ambos os lados
    gl.glDisable(GL10.GL_CULL_FACE);
    // define a fun??o de transpar?ncia
    gl.glEnable(GL10.GL_BLEND);
    gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
    // define a cor com o fator alfa de transpar?ncia
    gl.glColor4f(color[0],color[1],color[2],0.5f);
    // se deve desenhar linhas de destaque
    for (DotAI dot: line.getLines()) {
      drawAt(gl, dot.getCol(), dot.getPlane(), dot.getLin());
    }
    // restaura a fun??o de transpar?ncia
    gl.glBlendFunc(GL10.GL_ONE, GL10.GL_ZERO);
  }

  /**
   * desenha um destaque na posi??o do modelo 
   */
  public void preview(GL10 gl, int[] pos, float[] color, boolean previewLines) {
        // define o buffer de v?ertices
    gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
    // desenha ambos os lados
    gl.glDisable(GL10.GL_CULL_FACE);
    // define a fun??o de transpar?ncia
    gl.glEnable(GL10.GL_BLEND);
    gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
    // define a cor com o fator alfa de transpar?ncia
    gl.glColor4f(color[0],color[1],color[2],0.5f);
    // se deve desenhar linhas de destaque
    if (previewLines) {
      // varre as colunas da posi??o selecionada
      int dx;
      for (dx = 0; dx < dimensao; dx++) {
        drawAt(gl, dx, pos[1], pos[2]);
      }
      // varre as linhas da posi??o selecionada
      int dz;
      for (dz = 0; dz < dimensao; dz++) {
        drawAt(gl, pos[0], pos[1], dz);
      }
      // varre as camadas da posi??o selecionada
      int dy;
      for (dy = 0; dy < dimensao; dy++) {
        drawAt(gl, pos[0], dy, pos[2]);
      }
      if (showDiagonalLines) {
        // verifica as diagonais 
        int c = pos[0];
        int p = pos[1];
        int l = pos[2];
        boolean diagColCre = (p == l);
        boolean diagColDec = ((p + l) == (dimensao - 1));
        //boolean diagCol = diagColCre || diagColDec;
        boolean diagLinCre = (p == c);
        boolean diagLinDec = ((p + c) == (dimensao - 1));
        //boolean diagLin = diagLinCre || diagLinDec;
        boolean diagPlaCre = (l == c);
        boolean diagPlaDec = ((l + c)  == (dimensao - 1));
        //boolean diagPla = (diagPlaCre || diagPlaDec);
        boolean diagMeio1 = (diagLinCre && diagPlaCre); 
        boolean diagMeio2 = (diagLinCre && diagColDec); 
        boolean diagMeio3 = (diagLinDec && diagColCre); 
        boolean diagMeio4 = (diagColDec && diagPlaCre); 
        // desenhar eventual diagonal de coluna
        int d;
        gl.glColor4f(0,1,0,0.5f);
        if (diagColDec) {
          dz = dimensao;
          for (dy = 0; dy < dimensao; dy++) {
            dz--;
            drawAt(gl, pos[0], dy, dz);
          }
        }
        if (diagColCre) {
          for (d = 0; d < dimensao; d++) {
            drawAt(gl, pos[0], d, d);
          }
        }
        // verifica as diagonais de linha
        if (diagLinDec) {
          dx = dimensao;
          for (dy = 0; dy < dimensao; dy++) {
            dx--;
            drawAt(gl, dx, dy, pos[2]);
          }
        }
        if (diagLinCre) {
          for (d = 0; d < dimensao; d++) {
            drawAt(gl, d, d, pos[2]);
          }
        }
        // verifica as diagonais de plano
        if (diagPlaDec) {
          dx = dimensao;
          for (dz = 0; dz < dimensao; dz++) {
            dx--;
            drawAt(gl, dx, pos[1], dz);
          }
        }
        if (diagPlaCre) {
          for (d = 0; d < dimensao; d++) {
            drawAt(gl, d, pos[1], d);
          }
        }
        // verifica as diagonais de centro
        gl.glColor4f(0,1,0,0.5f);
        if (diagMeio1 && diagMeio2 && diagMeio3 && diagMeio4) {
          drawDiaginalMeio(gl,  1,  1);
          drawDiaginalMeio(gl, -1,  1);
          drawDiaginalMeio(gl,  1, -1);
          drawDiaginalMeio(gl, -1, -1);
        } else {
          if (diagMeio1 || diagMeio2 || diagMeio3 || diagMeio4) {
            int cz = (diagMeio1 || diagMeio3? 1: -1);
            int cx = (diagMeio1 || diagMeio2? 1: -1);
            dz = (cz == 1 ? 0: dimensao - 1);
            dx = (cx == 1 ? 0: dimensao - 1);
            for (dy = 0; dy < dimensao; dy++) {
              drawAt(gl, dx, dy, dz);
              dz += cz;
              dx += cx;
            }
          }
        }
      }
    } else {
      // ou sen?o, detaca apenas a posi??o selecionada
      drawAt(gl, pos[0], pos[1], pos[2]);
    }
    
    // restaura a fun??o de transpar?ncia
    gl.glBlendFunc(GL10.GL_ONE, GL10.GL_ZERO);
  }
  
  /**
   * Informa os angulos de rota??o para o seletor
   * 
   * Em testes, n?o usar em produ??o.
   *  
   */
  public void setAngles (GL10 gl, float aX, float aY) {
      /* O clipping por CULL_FACE, na maioria das circunst?ncias,
       *  otimiza o processamento gr?fico. Esse teste depende do vetor normal
       *  do plano (face) que pode ser informado ou calculado.
       *  Se for calculado, seu vaor depender? da orienta??o dos 
       *  v?rtices, se em dire??o hor?ria (CW) ou anti hor?ria (CCW). 
       * O teste desse m?todo ? experimental.
       *  Ele verifica a orienta??o do vetor normal das faces para 
       *  o caso do CULL_FACE estiver acionado quando for desenhar as 
       *  superf?cies de sele??o.
       * O problema ? que glIsEnabled n?o est? implementada 
       * no SDK vers?o 2.3.3! 
       * Assim, se este m?todo for chamado, ele ir? definir
       *  glFrontFace independente do GL_CULL_FACE estar ativado ou n?o.
       * N?o retire os coment?rios relacionados com GL11!!!
       */
      //if (gl instanceof GL11) {
      //  GL11 gl11 = (GL11)gl;
      //  if (gl11.glIsEnabled(GL10.GL_CULL_FACE))  {
          aX = (aX % 360f);
          aY = (aY % 360f);
          if (aX < 0) aX += 360;
          if (aY < 0) aY += 360;
          boolean faceXFrente = ((aX >=   0) && (aX <  90)) || 
                            ((aX >= 270) && (aX < 360));
          boolean faceYFrente = ((aY >= 0) && (aY < 180));
          if (( faceXFrente &&  faceYFrente) || 
            (!faceXFrente && !faceYFrente)) {
            gl.glFrontFace(GL10.GL_CCW);
          } else {
            gl.glFrontFace(GL10.GL_CW);
          }
        //}
      //}
  }
  
}




Java Source Code List

com.unibh.dcet.ccc.android.tictactoe3d.TTT3dActivity.java
com.unibh.dcet.ccc.android.tictactoe3d.TTT3dController.java
com.unibh.dcet.ccc.android.tictactoe3d.TTT3dModel.java
com.unibh.dcet.ccc.android.tictactoe3d.TTT3dView.java
com.unibh.dcet.ccc.android.tictactoe3d.ai.ArtificialInteligence.java
com.unibh.dcet.ccc.android.tictactoe3d.ai.DotAI.java
com.unibh.dcet.ccc.android.tictactoe3d.ai.Dot.java
com.unibh.dcet.ccc.android.tictactoe3d.ai.Environment.java
com.unibh.dcet.ccc.android.tictactoe3d.ai.Line.java
com.unibh.dcet.ccc.android.tictactoe3d.view.Circle.java
com.unibh.dcet.ccc.android.tictactoe3d.view.Cylinder.java
com.unibh.dcet.ccc.android.tictactoe3d.view.Grid.java
com.unibh.dcet.ccc.android.tictactoe3d.view.TTT3dBoard.java
com.unibh.dcet.ccc.android.tictactoe3d.view.TTT3dDrawable.java
com.unibh.dcet.ccc.android.tictactoe3d.view.TTT3dGridShape.java
com.unibh.dcet.ccc.android.tictactoe3d.view.TTT3dLine.java
com.unibh.dcet.ccc.android.tictactoe3d.view.TTT3dOShape.java
com.unibh.dcet.ccc.android.tictactoe3d.view.TTT3dSquareShape.java
com.unibh.dcet.ccc.android.tictactoe3d.view.TTT3dViewSelector.java
com.unibh.dcet.ccc.android.tictactoe3d.view.TTT3dXShape.java
com.unibh.dcet.ccc.android.tictactoe3d.view.obsolete.Sphere.java
com.unibh.dcet.ccc.android.tictactoe3d.view.obsolete.TTT3dOShape.java
com.unibh.dcet.ccc.android.tictactoe3d.view.obsolete.TTT3dXShape2.java
com.unibh.dcet.ccc.android.tictactoe3d.view.obsolete.TTT3dXShape.java