Package nu3a.render.software

Source Code of nu3a.render.software.N3SoftwareRenderContext$N3InternalTexture

/*
*  Copyright (c) 2003 Jorge García, Unai Aguilera
*
*  This file is part of Nu3A.
*
*   Nu3A is free software: you can redistribute it and/or modify
*   it under the terms of the GNU General Public License as published by
*   the Free Software Foundation, either version 3 of the License, or
*   (at your option) any later version.

*   Nu3A is distributed in the hope that it will be useful,
*   but WITHOUT ANY WARRANTY; without even the implied warranty of
*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*   GNU General Public License for more details.
*
*   You should have received a copy of the GNU General Public License
*   along with Nu3A.  If not, see <http://www.gnu.org/licenses/>.
*
*
*  Authors: Jorge García <bardok@gmail.com>, Unai Aguilera <gkalgan@gmail.com>
*/

package nu3a.render.software;

import java.awt.Component;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.image.ColorModel;
import java.awt.image.DirectColorModel;
import java.awt.image.ImageConsumer;
import java.awt.image.ImageProducer;
import java.util.Vector;

import nu3a.geometry.N3Point3D;
import nu3a.material.color.N3ColorRGBA;
import nu3a.material.texture.N3TexCoord2D;

/**
* Clase que proporciona el contexto de dibujado para renderizar la escena a
* trav�s de una interfaz de renderizado software. Crea el contexto para un
* determinado componente, y lo bloquea, permitiendo dibujar en �ste a la
* librer�a Nu3A a trav�s del API que proporciona.
*/
public class N3SoftwareRenderContext implements ImageProducer {

  private class N3InternalTexture {
    byte[] data;
    int dataFormat;
    int dataType;
    int width;
    int height;
  }

  private static final int N3_SWR_STATUS_INIT = 0;

  private static final int N3_SWR_STATUS_DRAW_VERTEXES = 1;
  private static final int N3_SWR_STATUS_DRAW_LINES = 2;
  private static final int N3_SWR_STATUS_DRAW_TRIANGLES = 3;
  private static final int N3_SWR_STATUS_DRAW_POLYGON = 4;

  public static final int N3_POINTS = 100;
  public static final int N3_LINES = 101;
  public static final int N3_TRIANGLES = 102;
  public static final int N3_POLYGON = 103;

  public static final int N3_SWR_REPLACE = 200;
  public static final int N3_SWR_MODULATE = 201;

  public static final int N3_RGBA = 21;
  public static final int N3_RGB = 22;

  /**
   * Componente para el que se proporciona el contexto de renderizado.
   */
  protected Component component;

  /**
   * Indica si el dibujado se realiza a trav�s de un doble buffer.
   */
  protected boolean doubleBuffer;

  /**
   * Pixels del contexto de redibujado.
   */
  protected int[] pixels;

  /**
   * Z Buffer, para determiterminar si un p�xel debe o no dibujarse en
   * pantalla
   */
  protected float[] zBuffer;

  /**
   * Im�gen en la que se dibujar� el contenido renderizado.
   */
  protected Image image;

  /**
   * Anchura del contexto de dibujado.
   */
  protected int height;

  /**
   * Altura del contexto de dibujado.
   */
  protected int width;

  /**
   * Tama�o en p�xels del contexto de dibujado.
   */
  protected int size;

  /**
   * �ltimo color asignado.
   */
  private N3ColorRGBA lastColor;

  /**
   * �ltima coordenada de textura asignada.
   */
  private N3TexCoord2D lastUV;

  /**
   * �ltimo v�rtice asignado.
   */
  private N3Point3D lastVertex;

  /**
   * Almac�n de vertices no dibujados
   */
  protected N3Point3D[] vertexPool;

  /**
   * Almac�n de los colores de los v�rtices no dibujados
   */
  protected N3ColorRGBA[] colorPool;

  /**
   * Almac�n de las coordenadas de textura de los v�rtices no dibujados
   */
  protected N3TexCoord2D[] uvPool;

  /**
   * N�mero de v�rtices asignados
   */
  private int nVertex;

  /**
   * Indica si es necesario hacer una actualizaci�n de la im�gen antes del
   * repintado.
   */
  private boolean needUpdate;

  /**
   * Establece si para dibujar se utilizar� el test de profundidad.
   */
  protected boolean depthtest;

  /**
   * Establece si para dibujar se utilizar�n texturas
   */
  protected boolean texturing;

  /**
   * �ndice de la textura activa
   */
  protected int selectedTexture;

  /**
   * �ndice de la textura activa
   */
  protected int textureMode;

  /**
   * Modelo de color utilizado para indicar al sistema el modelo de color que
   * se est� utilizando. Los colores se guardar�n en formato RGBA en enteros
   * de 32 bits, de modo que los 2 bytes de menor peso corresponden al color
   * rojo, los dos siguientes al verde, los siguientes a al az�l, y los de
   * mayor peso al canal Alpha.
   */
  protected ColorModel colormodel;

  /**
   * Consumidor de los p�xels de la im�gen. Ser� a traves de este objeto
   * mediante el que se actualizar� la im�gen interna del contexto. Este
   * contexto es creado y asignado internamente por el sistema, y manejado a
   * trav�s de los m�todos de la interfaz ImageProducer.
   */
  private ImageConsumer consumer;

  /**
   * Estado en el que se encuentra el contexto.
   */
  private int status;

  /**
   * Vector de texturas para este contexto
   */
  protected Vector textures;

  /**
   * Crea un contexto de renderizado para el componente. Si se especifica, el
   * dibujado se realizar� a trav�s de un doble-buffer para evitar parpadeos
   * en el dibujado.
   *
   * @param c
   *            Component sobre el que se construir� el contexto
   * @param dBuffer
   *            Indica si se utilizar� o no Doble Buffer
   */
  public N3SoftwareRenderContext(Component c, boolean dBuffer) {
    component = c;
    component.setIgnoreRepaint(true);
    width = component.getWidth();
    height = component.getHeight();
    size = width * height;
    pixels = new int[size];
    zBuffer = new float[size];
    image = Toolkit.getDefaultToolkit().createImage(this);
    colormodel = new DirectColorModel(32, 0x000000FF, 0x0000FF00,
        0x00FF0000, 0xFF000000);
    consumer = null;
    lastColor = new N3ColorRGBA(1, 1, 1);
    lastUV = new N3TexCoord2D(0, 0);
    lastVertex = null;
    status = N3_SWR_STATUS_INIT;
    needUpdate = true;
    depthtest = false;
    textures = new Vector(0, 1);
    selectedTexture = -1;
    textureMode = N3_SWR_REPLACE;
  }

  /**
   * Obtiene la anchura del contexto.
   *
   * @return Anchura del contexto
   */
  public int getWidth() {
    return width;
  }

  /**
   * Obtiene la altura del contexto.
   *
   * @return Altura del contexto
   */
  public int getHeight() {
    return height;
  }

  /**
   * Establece las caracter�sticas del render seg�n su estado.
   */
  protected void stablishStatusEnvironment() {
    switch (status) {
    case (N3_SWR_STATUS_DRAW_VERTEXES):
      break;
    case (N3_SWR_STATUS_DRAW_LINES):
      nVertex = 0;
      vertexPool = new N3Point3D[2];
      colorPool = new N3ColorRGBA[2];
      uvPool = new N3TexCoord2D[2];
      break;
    case (N3_SWR_STATUS_DRAW_TRIANGLES):
    case (N3_SWR_STATUS_DRAW_POLYGON):
      nVertex = 0;
      vertexPool = new N3Point3D[3];
      colorPool = new N3ColorRGBA[3];
      uvPool = new N3TexCoord2D[3];
      break;
    }
  }

  /**
   * Actualiza el contenido del componente con la im�gen creada en el contexto
   * de renderizado.
   */
  public synchronized void paint() {
    if (needUpdate)
      update();
    component.getGraphics().drawImage(image, 0, 0, null);
  }

  /**
   * Actualiza la im�gen interna con los datos actuales.
   */
  public synchronized void update() {
    if (consumer != null) {
      consumer.setPixels(0, 0, width, height, colormodel, (int[]) pixels,
          0, width);
      consumer.imageComplete(ImageConsumer.SINGLEFRAMEDONE);
      needUpdate = false;
    } else
      needUpdate = true;
  }

  /**
   * Establece el modo de dibujado (puntos, l�neas, tri�ngulos).
   */
  public void beginDrawingMode(int drawMode) {
    switch (status) {
    case (N3_SWR_STATUS_INIT):
      switch (drawMode) {
      case (N3_POINTS):
        status = N3_SWR_STATUS_DRAW_VERTEXES;
        stablishStatusEnvironment();
        break;
      case (N3_LINES):
        status = N3_SWR_STATUS_DRAW_LINES;
        stablishStatusEnvironment();
        break;
      case (N3_TRIANGLES):
        status = N3_SWR_STATUS_DRAW_TRIANGLES;
        stablishStatusEnvironment();
        break;
      case (N3_POLYGON):
        status = N3_SWR_STATUS_DRAW_POLYGON;
        stablishStatusEnvironment();
        break;
      }
      break;
    default:
      break;
    }
  }

  public void endDrawingMode() {
    switch (status) {
    case (N3_SWR_STATUS_DRAW_VERTEXES):
    case (N3_SWR_STATUS_DRAW_LINES):
    case (N3_SWR_STATUS_DRAW_TRIANGLES):
    case (N3_SWR_STATUS_DRAW_POLYGON):
      status = N3_SWR_STATUS_INIT;
      break;
    }
  }

  /**
   * Procesa el �ltimo v�rtice, teniendo en cuenta el estado, y el n�mero de
   * v�rtices asignados anteriormente. Si procede, dibujar� los �ltimos
   * v�rtices a�adidos al render.
   */
  protected void processVertex() {
    switch (status) {
    case (N3_SWR_STATUS_DRAW_VERTEXES):
      drawFlatVertex();
      break;
    case (N3_SWR_STATUS_DRAW_LINES):
      vertexPool[nVertex] = lastVertex;
      colorPool[nVertex] = lastColor;
      nVertex++;
      if (nVertex == 2) {
        /* dibujado de la l�nea con el pool */
        int color1 = colorPool[0].getPackedValue();
        int color2 = colorPool[1].getPackedValue();
        int y1 = (int) vertexPool[0].y;
        int y2 = (int) vertexPool[1].y;
        if (color1 == color2) {
          if (y1 == y2)
            drawFlatHorizontalLine();
          else {
            int x1 = (int) vertexPool[0].x;
            int x2 = (int) vertexPool[1].x;
            if (x1 == x2)
              drawFlatVerticalLine();
            else {
              int dx = x2 - x1;
              int dy = y2 - y1;
              dx = (dx < 0) ? -dx : dx;
              dy = (dy < 0) ? -dy : dy;
              if (dx > dy)
                drawFlatHorizontalIncLine();
              else
                drawFlatVerticalIncLine();
            }
          }
        } else {
          if (y1 == y2)
            drawGoraudHorizontalLine();
          else {
            int x1 = (int) vertexPool[0].x;
            int x2 = (int) vertexPool[1].x;
            if (x1 == x2)
              drawGoraudVerticalLine();
            else {
              int dx = x2 - x1;
              int dy = y2 - y1;
              dx = (dx < 0) ? -dx : dx;
              dy = (dy < 0) ? -dy : dy;
              if (dx > dy)
                drawGoraudHorizontalIncLine();
              else
                drawGoraudVerticalIncLine();
            }
          }
        }
        nVertex = 0;
      }
      break;
    case (N3_SWR_STATUS_DRAW_TRIANGLES):
      vertexPool[nVertex] = lastVertex;
      colorPool[nVertex] = lastColor;
      uvPool[nVertex] = lastUV;
      nVertex++;
      if (nVertex == 3) {
        /* dibujado del tri�ngulo con el pool */
        int color1 = colorPool[0].getPackedValue();
        int color2 = colorPool[1].getPackedValue();
        int color3 = colorPool[2].getPackedValue();
        if ((color1 == color2) && (color2 == color3)) {
          if ((!texturing) || (selectedTexture >= textures.size())
              || selectedTexture == -1)
            drawFlatTriangle();
          else if (textureMode == N3_SWR_REPLACE)
            drawReplaceTexturedTriangle();
          else
            drawFlatTexturedTriangle();
        } else {
          if ((!texturing) || (selectedTexture >= textures.size())
              || selectedTexture == -1)
            drawGoraudTriangle();
          else if (textureMode == N3_SWR_REPLACE)
            drawReplaceTexturedTriangle();
          else
            drawGoraudTexturedTriangle();
        }
        nVertex = 0;
      }
      break;
    case (N3_SWR_STATUS_DRAW_POLYGON):
      vertexPool[nVertex] = lastVertex;
      colorPool[nVertex] = lastColor;
      uvPool[nVertex] = lastUV;
      nVertex++;
      if (nVertex == 3) {
        /* dibujado del tri�ngulo con el pool */
        int color1 = colorPool[0].getPackedValue();
        int color2 = colorPool[1].getPackedValue();
        int color3 = colorPool[2].getPackedValue();
        if ((color1 == color2) && (color2 == color3)) {
          if ((!texturing) || (selectedTexture >= textures.size())
              || selectedTexture == -1)
            drawFlatTriangle();
          else if (textureMode == N3_SWR_REPLACE)
            drawReplaceTexturedTriangle();
          else
            drawFlatTexturedTriangle();
        } else {
          if ((!texturing) || (selectedTexture >= textures.size())
              || selectedTexture == -1)
            drawGoraudTriangle();
          else if (textureMode == N3_SWR_REPLACE)
            drawReplaceTexturedTriangle();
          else
            drawGoraudTexturedTriangle();
        }
        nVertex = 2;
        vertexPool[1] = vertexPool[2];
        colorPool[1] = colorPool[2];
        uvPool[1] = uvPool[2];
      }
      break;
    }
  }

  /**
   * Establece el color del pr�ximo v�rtice a dibujar.
   *
   * @param color
   *            Color del pr�ximo v�rtice a dibujar
   */
  public void setColor(N3ColorRGBA color) {
    lastColor = color;
  }

  /**
   * Establece las coordenadas de textura del pr�ximo v�rtice a dibujar.
   *
   * @param uv
   *            Coordenadas de textura del pr�ximo v�rtice a dibujar
   */
  public void setUV(N3TexCoord2D uv) {
    lastUV = uv;
  }

  /**
   * Establece el pr�ximo v�rtice a dibujar
   *
   * @param vertex
   *            Pr�ximo v�rtice a dibujar
   */
  public void setVertex(N3Point3D vertex) {
    lastVertex = vertex;
    processVertex();
  }

  /**
   * Inicializa el contenido del z buffer a la distancia m�xima.
   */
  public void cleanZBuffer() {
    if (status == N3_SWR_STATUS_INIT) {
      if (size > 0) {
        int half = size >> 1;
        zBuffer[0] = 1;

        for (int i = 1; i < size;) {
          System.arraycopy(zBuffer, 0, zBuffer, i, (i < half) ? i
              : size - i);
          i <<= 1;
        }
      }
    }
  }

  /**
   * Establece si el dibujado se realizar� utilizando el test de profundidad
   *
   * @param test
   *            true en el caso de que se desee realizar; false en caso
   *            contrario
   */
  public void setDepthTest(boolean test) {
    depthtest = test;
  }

  /**
   * Obtiene si se est� realizando el test de profundidad.
   *
   * @return true si se est� realizando; false en caso contrario
   */
  public boolean getDepthTest() {
    return depthtest;
  }

  /**
   * Establece si se utilizar�n o no texturas.
   *
   * @param value
   *            True para utilizar texturas; false en caso contrario
   */
  public void setTexturing(boolean value) {
    texturing = value;
  }

  /**
   * Obtiene si se est�n utilizando texturas.
   *
   * @return True si es est�n utilizando texturas; false en caso contrario
   */
  public boolean getTextuting() {
    return texturing;
  }

  /**
   * A�ade una textura al contexto.
   *
   * @param t
   *            Textura a a�adir
   * @return C�digo de la textura dentro del contexto
   */
  public int createTexture2D(byte[] data, int dataFormat, int dataType,
      int width, int height) {
    N3InternalTexture t = new N3InternalTexture();
    if (dataFormat == N3_RGB) {
      t.data = new byte[data.length + width * height];
      int j = 0;
      for (int i = 0; i < data.length; i += 3) {
        t.data[j++] = data[i];
        t.data[j++] = data[i + 1];
        t.data[j++] = data[i + 2];
        t.data[j++] = -1;
      }
    } else {
      t.data = new byte[data.length];
      System.arraycopy(data, 0, t.data, 0, data.length);
    }
    t.dataFormat = dataFormat;
    t.dataType = dataType;
    t.width = width;
    t.height = height;
    textures.add(t);
    return textures.size() - 1;
  }

  /**
   * Selecciona la textura activa
   *
   * @param index
   *            �ndice de la textura
   */
  public void selectTexture(int index) {
    selectedTexture = index;
  }

  /**
   * Especif�ca el modo de textura.
   *
   * @param mode
   *            Modo de aplicaci�n de la textura
   */
  public void setTextureMode(int mode) {
    textureMode = mode;
  }

  /**
   * Indica si un punto deber�a de dibujarse, teniendo en cuenta si hay otros
   * puntos entre �l y la c�mara. En el caso de que el z buffer est� activo y
   * la comprobaci�n sea verdadera, se actualiza el contenido del zBuffer;
   *
   * @param index
   *            Posici�n de la im�gen (de manera lineal) en la que se
   *            dibujar�a el punto
   * @param z
   *            Profundidad del punto
   * @return true si hay que dibujar el punto. False en caso contrario.
   */
  public boolean depthTest(int index, float z) {
    if (!depthtest)
      return (z >= 0.0f);
    else if (zBuffer[index] > z) {
      zBuffer[index] = z;
      return true;
    }
    return false;
  }

  /*---------------------------------------------------------------------------------
  M�todos de dibujado
  ---------------------------------------------------------------------------------*/

  /**
   * Dibuja un v�rtice con el �ltimo color especificado.
   */
  public void drawFlatVertex() {
    int x, y;
    x = (int) lastVertex.x;
    y = (int) lastVertex.y;
    int color = lastColor.getPackedValue();
    if ((x >= 0) && (x < width) && (y >= 0) && (y < height)) {
      float z = lastVertex.z;
      int pos = x + y * width;
      if (depthTest(pos, z))
        pixels[pos] = color;
      needUpdate = true;
    }
  }

  /**
   * Dibuja una l�nea horizontal con el �ltimo color especificado.
   */
  public void drawFlatHorizontalLine() {
    int y = (int) vertexPool[0].y;
    if ((y >= 0) && (y < height)) {
      int color = lastColor.getPackedValue();
      int x1 = (int) vertexPool[0].x;
      int x2 = (int) vertexPool[1].x;
      float z1 = vertexPool[0].z;
      float z2 = vertexPool[1].z;
      if (x1 > x2) {
        int tmpx = x2;
        x2 = x1;
        x1 = tmpx;
        float tmpz = z2;
        z2 = z1;
        z1 = tmpz;
      }
      int pos = x1 + width * y;
      float dz;
      if ((int) (x2 - x1) != 0)
        dz = (float) (z2 - z1) / (x2 - x1);
      else
        dz = 0;
      float z = z1;
      for (int x = x1; x <= x2; x++) {
        if ((x >= 0) && (x < width)) {
          if (depthTest(pos, z))
            pixels[pos] = color;
        }
        z += dz;
        pos++;
      }
      needUpdate = true;
    }
  }

  /**
   * Dibuja una l�nea vertical con el �ltimo color especificado.
   */
  public void drawFlatVerticalLine() {
    int x = (int) vertexPool[0].x;
    if ((x >= 0) && (x < width)) {
      int color = lastColor.getPackedValue();
      int y1 = (int) vertexPool[0].y;
      int y2 = (int) vertexPool[1].y;
      float z1 = vertexPool[0].z;
      float z2 = vertexPool[1].z;
      if (y1 > y2) {
        int tmpy = y2;
        y2 = y1;
        y1 = tmpy;
        float tmpz = z2;
        z2 = z1;
        z1 = tmpz;
      }
      int pos = x + width * y1;
      float dz;
      if ((int) (y2 - y1) != 0)
        dz = (float) (z2 - z1) / (y2 - y1);
      else
        dz = 0;
      float z = z1;
      for (int y = y1; y <= y2; y++) {
        if ((y >= 0) && (y < height)) {
          if (depthTest(pos, z))
            pixels[pos] = color;
        }
        z += dz;
        pos += width;
      }
      needUpdate = true;
    }
  }

  /**
   * Dibuja una l�nea horizontal con el �ltimo color especificado, en la cual
   * la x aumenta m�s r�pidamente que la y.
   */
  public void drawFlatHorizontalIncLine() {
    int color = lastColor.getPackedValue();
    int x1 = (int) vertexPool[0].x;
    int x2 = (int) vertexPool[1].x;
    int y1 = (int) vertexPool[0].y;
    int y2 = (int) vertexPool[1].y;
    float z1 = vertexPool[0].z;
    float z2 = vertexPool[1].z;
    int pos;
    if (x1 > x2) {
      int tmpx = x2;
      x2 = x1;
      x1 = tmpx;
      int tmpy = y2;
      y2 = y1;
      y1 = tmpy;
      float tmpz = z2;
      z2 = z1;
      z1 = tmpz;
    }
    float dz, dy;
    if ((int) (x2 - x1) != 0) {
      dz = (float) (z2 - z1) / (x2 - x1);
      dy = (float) (y2 - y1) / (x2 - x1);
    } else {
      dz = 0;
      dy = 0;
    }
    float z = z1;
    float y = y1;
    for (int x = x1; x <= x2; x++) {
      if ((x >= 0) && (x < width) && (y >= 0) && (y < height)) {
        pos = x + width * (int) y;
        if (depthTest(pos, z))
          pixels[pos] = color;
      }
      z += dz;
      y += dy;
    }
    needUpdate = true;
  }

  /**
   * Dibuja una l�nea vertical con el �ltimo color especificado, en la cual la
   * x aumenta m�s r�pidamente que la y.
   */
  public void drawFlatVerticalIncLine() {
    int color = lastColor.getPackedValue();
    int x1 = (int) vertexPool[0].x;
    int x2 = (int) vertexPool[1].x;
    int y1 = (int) vertexPool[0].y;
    int y2 = (int) vertexPool[1].y;
    float z1 = vertexPool[0].z;
    float z2 = vertexPool[1].z;
    int pos;
    if (y1 > y2) {
      int tmpx = x2;
      x2 = x1;
      x1 = tmpx;
      int tmpy = y2;
      y2 = y1;
      y1 = tmpy;
      float tmpz = z2;
      z2 = z1;
      z1 = tmpz;
    }
    float dz, dx;
    if ((int) (y2 - y1) != 0) {
      dz = (float) (z2 - z1) / (y2 - y1);
      dx = (float) (x2 - x1) / (y2 - y1);
    } else {
      dz = 0;
      dx = 0;
    }
    float z = z1;
    float x = x1;
    for (int y = y1; y <= y2; y++) {
      if ((x >= 0) && (x < width) && (y >= 0) && (y < height)) {
        pos = (int) x + width * y;
        if (depthTest(pos, z))
          pixels[pos] = color;
      }
      z += dz;
      x += dx;
    }
    needUpdate = true;
  }

  /**
   * Dibuja una l�nea horizontal, interpolando los colores de los v�rtices.
   */
  public void drawGoraudHorizontalLine() {
    int y = (int) vertexPool[0].y;
    if ((y >= 0) && (y < height)) {
      int c1 = colorPool[0].getPackedValue();
      int c2 = colorPool[1].getPackedValue();
      int x1 = (int) vertexPool[0].x;
      int x2 = (int) vertexPool[1].x;
      float z1 = vertexPool[0].z;
      float z2 = vertexPool[1].z;
      if (x1 > x2) {
        int tmpx = x2;
        x2 = x1;
        x1 = tmpx;
        int tmpc = c2;
        c2 = c1;
        c1 = tmpc;
        float tmpz = z2;
        z2 = z1;
        z1 = tmpz;
      }
      int pos = x1 + width * y;
      float dz, dr, dg, db, da;
      if ((int) (x2 - x1) != 0) {
        dz = (float) (z2 - z1) / (x2 - x1);
        dr = (float) ((c2 & 0x000000FF) - (c1 & 0x000000FF))
            / (x2 - x1);
        dg = (float) (((c2 & 0x0000FF00) >> 8) - ((c1 & 0x0000FF00) >> 8))
            / (x2 - x1);
        db = (float) (((c2 & 0x00FF0000) >> 16) - ((c1 & 0x00FF0000) >> 16))
            / (x2 - x1);
        da = (float) (((c2 & 0xFF000000) >> 24) - ((c1 & 0xFF000000) >> 24))
            / (x2 - x1);
      } else {
        dz = 0;
        dr = 0;
        dg = 0;
        db = 0;
        da = 0;
      }
      float z = z1;
      float r = (c1 & 0x000000FF);
      float g = (c1 & 0x0000FF00) >> 8;
      float b = (c1 & 0x00FF0000) >> 16;
      float a = (c1 & 0xFF000000) >> 24;
      int color = c1;
      for (int x = x1; x <= x2; x++) {
        if ((x >= 0) && (x < width)) {
          if (depthTest(pos, z))
            pixels[pos] = color;
        }
        z += dz;
        r += dr;
        g += dg;
        b += db;
        a += da;
        color = (int) r + ((int) g << 8) + ((int) b << 16)
            + ((int) a << 24);
        pos++;
      }
      needUpdate = true;
    }
  }

  /**
   * Dibuja una l�nea vertical, interpolando los colores de los v�rtices.
   */
  public void drawGoraudVerticalLine() {
    int x = (int) vertexPool[0].x;
    if ((x >= 0) && (x < width)) {
      int c1 = colorPool[0].getPackedValue();
      int c2 = colorPool[1].getPackedValue();
      int y1 = (int) vertexPool[0].y;
      int y2 = (int) vertexPool[1].y;
      float z1 = vertexPool[0].z;
      float z2 = vertexPool[1].z;
      if (y1 > y2) {
        int tmpy = y2;
        y2 = y1;
        y1 = tmpy;
        int tmpc = c2;
        c2 = c1;
        c1 = tmpc;
        float tmpz = z2;
        z2 = z1;
        z1 = tmpz;
      }
      int pos = x + width * y1;
      float dz, dr, dg, db, da;
      if ((int) (y2 - y1) != 0) {
        dz = (float) (z2 - z1) / (y2 - y1);
        dr = (float) ((c2 & 0x000000FF) - (c1 & 0x000000FF))
            / (y2 - y1);
        dg = (float) (((c2 & 0x0000FF00) >> 8) - ((c1 & 0x0000FF00) >> 8))
            / (y2 - y1);
        db = (float) (((c2 & 0x00FF0000) >> 16) - ((c1 & 0x00FF0000) >> 16))
            / (y2 - y1);
        da = (float) (((c2 & 0xFF000000) >> 24) - ((c1 & 0xFF000000) >> 24))
            / (y2 - y1);
      } else {
        dz = 0;
        dr = 0;
        dg = 0;
        db = 0;
        da = 0;
      }
      float z = z1;
      float r = (c1 & 0x000000FF);
      float g = (c1 & 0x0000FF00) >> 8;
      float b = (c1 & 0x00FF0000) >> 16;
      float a = (c1 & 0xFF000000) >> 24;
      int color = c1;
      for (int y = y1; y <= y2; y++) {
        if ((y >= 0) && (y < height)) {
          if (depthTest(pos, z))
            pixels[pos] = color;
        }
        z += dz;
        r += dr;
        g += dg;
        b += db;
        a += da;
        color = (int) r + ((int) g << 8) + ((int) b << 16)
            + ((int) a << 24);
        pos += width;
      }
      needUpdate = true;
    }
  }

  /**
   * Dibuja una l�nea que crece m�s r�pido horizontalmente, interpolando los
   * colores de los v�rtices.
   */
  public void drawGoraudHorizontalIncLine() {
    int c1 = colorPool[0].getPackedValue();
    int c2 = colorPool[1].getPackedValue();
    int x1 = (int) vertexPool[0].x;
    int x2 = (int) vertexPool[1].x;
    int y1 = (int) vertexPool[0].y;
    int y2 = (int) vertexPool[1].y;
    float z1 = vertexPool[0].z;
    float z2 = vertexPool[1].z;
    int pos;
    if (x1 > x2) {
      int tmpx = x2;
      x2 = x1;
      x1 = tmpx;
      int tmpy = y2;
      y2 = y1;
      y1 = tmpy;
      int tmpc = c2;
      c2 = c1;
      c1 = tmpc;
      float tmpz = z2;
      z2 = z1;
      z1 = tmpz;
    }
    float dz, dy, dr, dg, db, da;
    if ((int) (x2 - x1) != 0) {
      dz = (float) (z2 - z1) / (x2 - x1);
      dy = (float) (y2 - y1) / (x2 - x1);
      dr = (float) ((c2 & 0x000000FF) - (c1 & 0x000000FF)) / (x2 - x1);
      dg = (float) (((c2 & 0x0000FF00) >> 8) - ((c1 & 0x0000FF00) >> 8))
          / (x2 - x1);
      db = (float) (((c2 & 0x00FF0000) >> 16) - ((c1 & 0x00FF0000) >> 16))
          / (x2 - x1);
      da = (float) (((c2 & 0xFF000000) >> 24) - ((c1 & 0xFF000000) >> 24))
          / (x2 - x1);
    } else {
      dz = 0;
      dy = 0;
      dr = 0;
      dg = 0;
      db = 0;
      da = 0;
    }
    float z = z1;
    float y = y1;
    float r = (c1 & 0x000000FF);
    float g = (c1 & 0x0000FF00) >> 8;
    float b = (c1 & 0x00FF0000) >> 16;
    float a = (c1 & 0xFF000000) >> 24;
    int color = c1;
    for (int x = x1; x <= x2; x++) {
      if ((x >= 0) && (x < width) && (y >= 0) && (y < height)) {
        pos = x + width * (int) y;
        if (depthTest(pos, z))
          pixels[pos] = color;
      }
      z += dz;
      y += dy;
      r += dr;
      g += dg;
      b += db;
      a += da;
      color = (int) r + ((int) g << 8) + ((int) b << 16)
          + ((int) a << 24);
    }
    needUpdate = true;
  }

  /**
   * Dibuja una l�nea que crece m�s r�pido verticalmente, interpolando los
   * colores de los v�rtices.
   */
  public void drawGoraudVerticalIncLine() {
    int c1 = colorPool[0].getPackedValue();
    int c2 = colorPool[1].getPackedValue();
    int x1 = (int) vertexPool[0].x;
    int x2 = (int) vertexPool[1].x;
    int y1 = (int) vertexPool[0].y;
    int y2 = (int) vertexPool[1].y;
    float z1 = vertexPool[0].z;
    float z2 = vertexPool[1].z;
    int pos;
    if (y1 > y2) {
      int tmpx = x2;
      x2 = x1;
      x1 = tmpx;
      int tmpy = y2;
      y2 = y1;
      y1 = tmpy;
      int tmpc = c2;
      c2 = c1;
      c1 = tmpc;
      float tmpz = z2;
      z2 = z1;
      z1 = tmpz;
    }
    float dz, dx, dr, dg, db, da;
    if ((int) (y2 - y1) != 0) {
      dz = (float) (z2 - z1) / (y2 - y1);
      dx = (float) (x2 - x1) / (y2 - y1);
      dr = (float) ((c2 & 0x000000FF) - (c1 & 0x000000FF)) / (y2 - y1);
      dg = (float) (((c2 & 0x0000FF00) >> 8) - ((c1 & 0x0000FF00) >> 8))
          / (y2 - y1);
      db = (float) (((c2 & 0x00FF0000) >> 16) - ((c1 & 0x00FF0000) >> 16))
          / (y2 - y1);
      da = (float) (((c2 & 0xFF000000) >> 24) - ((c1 & 0xFF000000) >> 24))
          / (y2 - y1);
    } else {
      dz = 0;
      dx = 0;
      dr = 0;
      dg = 0;
      db = 0;
      da = 0;
    }
    float z = z1;
    float x = x1;
    float r = (c1 & 0x000000FF);
    float g = (c1 & 0x0000FF00) >> 8;
    float b = (c1 & 0x00FF0000) >> 16;
    float a = (c1 & 0xFF000000) >> 24;
    int color = c1;
    for (int y = y1; y <= y2; y++) {
      if ((x >= 0) && (x < width) && (y >= 0) && (y < height)) {
        pos = (int) x + width * y;
        if (depthTest(pos, z))
          pixels[pos] = color;
      }
      z += dz;
      x += dx;
      r += dr;
      g += dg;
      b += db;
      a += da;
      color = (int) r + ((int) g << 8) + ((int) b << 16)
          + ((int) a << 24);
    }
    needUpdate = true;
  }

  /**
   * Borra la im�gen y establece el �ltimo color establecido.
   */
  public void clear() {
    if (status == N3_SWR_STATUS_INIT) {
      if (size > 0) {
        int c = lastColor.getPackedValue();
        int half = size >> 1;
        pixels[0] = c;

        for (int i = 1; i < size;) {
          System.arraycopy(pixels, 0, pixels, i, (i < half) ? i
              : size - i);
          i <<= 1;
        }
        needUpdate = true;
      }
    }
  }

  /**
   * Borra la im�gen y establece el color definido.
   *
   * @param color
   *            Color de relleno
   */
  public void clearToColor(N3ColorRGBA color) {
    if (status == N3_SWR_STATUS_INIT) {
      if (size > 0) {
        int c = color.getPackedValue();
        int half = size >> 1;
        pixels[0] = c;

        for (int i = 1; i < size;) {
          System.arraycopy(pixels, 0, pixels, i, (i < half) ? i
              : size - i);
          i <<= 1;
        }
        needUpdate = true;
      }
    }
  }

  /**
   * Dibuja un tri�ngulo utilizando el pool, con el �ltimo color definido.
   */
  public void drawFlatTriangle() {
    int color = lastColor.getPackedValue();
    /* Buscamos el lado cuya proyecci�n sobre el eje Y es m�s larga */
    int dy01 = ((int) vertexPool[1].y - (int) vertexPool[0].y);
    dy01 = (dy01 < 0) ? -dy01 : dy01;
    int dy02 = ((int) vertexPool[2].y - (int) vertexPool[0].y);
    dy02 = (dy02 < 0) ? -dy02 : dy02;
    int dy12 = ((int) vertexPool[2].y - (int) vertexPool[1].y);
    dy12 = (dy12 < 0) ? -dy12 : dy12;
    int dy;
    int bx1, bx2, by1, by2, sx, sy;
    float bz1, bz2, sz;
    if ((dy01 >= dy02) && (dy01 >= dy12)) {
      /* El lado base ser� el 0-1 */
      bx1 = (int) vertexPool[0].x;
      by1 = (int) vertexPool[0].y;
      bz1 = vertexPool[0].z;
      bx2 = (int) vertexPool[1].x;
      by2 = (int) vertexPool[1].y;
      bz2 = vertexPool[1].z;
      sx = (int) vertexPool[2].x;
      sy = (int) vertexPool[2].y;
      sz = vertexPool[2].z;
      dy = dy01;
    } else if ((dy02 >= dy01) && (dy02 >= dy12)) {
      /* El lado base ser� el 0-2 */
      bx1 = (int) vertexPool[0].x;
      by1 = (int) vertexPool[0].y;
      bz1 = vertexPool[0].z;
      bx2 = (int) vertexPool[2].x;
      by2 = (int) vertexPool[2].y;
      bz2 = vertexPool[2].z;
      sx = (int) vertexPool[1].x;
      sy = (int) vertexPool[1].y;
      sz = vertexPool[1].z;
      dy = dy02;
    } else {
      /* El lado base ser� el 1-2 */
      bx1 = (int) vertexPool[1].x;
      by1 = (int) vertexPool[1].y;
      bz1 = vertexPool[1].z;
      bx2 = (int) vertexPool[2].x;
      by2 = (int) vertexPool[2].y;
      bz2 = vertexPool[2].z;
      sx = (int) vertexPool[0].x;
      sy = (int) vertexPool[0].y;
      sz = vertexPool[0].z;
      dy = dy12;
    }
    if (by1 > by2) {
      int tmpi = by1;
      by1 = by2;
      by2 = tmpi;
      tmpi = bx1;
      bx1 = bx2;
      bx2 = tmpi;
      float tmpf = bz1;
      bz1 = bz2;
      bz2 = tmpf;
    }
    float bdx, bdz, s1dx, s1dz, s2dx, s2dz, dsx, dsz;
    if ((int) dy != 0) {
      bdx = (float) (bx2 - bx1) / dy;
      bdz = (float) (bz2 - bz1) / dy;
    } else {
      bdx = 0;
      bdz = 0;
    }
    if ((int) (sy - by1) != 0) {
      s1dx = (float) (sx - bx1) / (sy - by1);
      s1dz = (float) (sz - bz1) / (sy - by1);
      dsx = bx1;
      dsz = bz1;
    } else {
      s1dx = 0;
      s1dz = 0;
      dsx = sx;
      dsz = sz;
    }
    if ((int) (by2 - sy) != 0) {
      s2dx = (float) (bx2 - sx) / (by2 - sy);
      s2dz = (float) (bz2 - sz) / (by2 - sy);
    } else {
      s2dx = 0;
      s2dz = 0;
    }
    float bx = bx1;
    float bz = bz1;
    int pos;
    int init, end;
    float initz, ldz;
    by2 = (by2 > height) ? height : by2;
    if (by1 < 0) {
      float skip = (-by1);
      bx += bdx * skip;
      bz += bdz * skip;
      if (sy > 0) {
        dsx += s1dx * skip;
        dsz += s1dz * skip;
      } else {
        float skips = (-sy);
        dsx = sx + s2dx * skips;
        dsz = sz + s2dz * skips;
      }
      by1 = 0;
    }
    if ((by1 < height) && (by2 > 0)) {
      for (int y = by1; y <= by2; y++) {
        /* Dibujamos la l�nea horizontal */
        if (bx > dsx) {
          init = (int) dsx;
          end = (int) bx;
          initz = dsz;
          ldz = (bz - dsz) / (end - init);
        } else {
          init = (int) bx;
          end = (int) dsx;
          initz = bz;
          ldz = (dsz - bz) / (end - init);
        }
        end = (end > width) ? width : end;
        if (init < 0) {
          float skip = (-init);
          initz += ldz * skip;
          init = 0;
        }
        pos = init + y * width;
        if ((y >= 0) && (y < height) && (init <= width) && (end >= 0)) {
          for (; init <= end; init++) {
            if ((init >= 0) && (init < width))
              if (depthTest(pos, initz))
                pixels[pos] = color;
            pos++;
            initz += ldz;
          }
        }
        /* Actualizamos los valores para la siguiente vuelta */
        bx += bdx;
        bz += bdz;
        dsx += ((y < sy) ? s1dx : s2dx);
        dsz += ((y < sy) ? s1dz : s2dz);
      }
    }
    needUpdate = true;
  }

  /**
   * Dibuja un tri�ngulo goraud utilizando el pool
   */
  public void drawGoraudTriangle() {
    int c0 = colorPool[0].getPackedValue();
    int c1 = colorPool[1].getPackedValue();
    int c2 = colorPool[2].getPackedValue();
    /* Buscamos el lado cuya proyecci�n sobre el eje Y es m�s larga */
    int dy01 = ((int) vertexPool[1].y - (int) vertexPool[0].y);
    dy01 = (dy01 < 0) ? -dy01 : dy01;
    int dy02 = ((int) vertexPool[2].y - (int) vertexPool[0].y);
    dy02 = (dy02 < 0) ? -dy02 : dy02;
    int dy12 = ((int) vertexPool[2].y - (int) vertexPool[1].y);
    dy12 = (dy12 < 0) ? -dy12 : dy12;
    int dy;
    int bx1, bx2, by1, by2, sx, sy, bc1, bc2, sc;
    float bz1, bz2, sz;
    if ((dy01 >= dy02) && (dy01 >= dy12)) {
      /* El lado base ser� el 0-1 */
      bx1 = (int) vertexPool[0].x;
      by1 = (int) vertexPool[0].y;
      bz1 = vertexPool[0].z;
      bx2 = (int) vertexPool[1].x;
      by2 = (int) vertexPool[1].y;
      bz2 = vertexPool[1].z;
      sx = (int) vertexPool[2].x;
      sy = (int) vertexPool[2].y;
      sz = vertexPool[2].z;
      bc1 = c0;
      bc2 = c1;
      sc = c2;
    } else if ((dy02 >= dy01) && (dy02 >= dy12)) {
      /* El lado base ser� el 0-2 */
      bx1 = (int) vertexPool[0].x;
      by1 = (int) vertexPool[0].y;
      bz1 = vertexPool[0].z;
      bx2 = (int) vertexPool[2].x;
      by2 = (int) vertexPool[2].y;
      bz2 = vertexPool[2].z;
      sx = (int) vertexPool[1].x;
      sy = (int) vertexPool[1].y;
      sz = vertexPool[1].z;
      bc1 = c0;
      bc2 = c2;
      sc = c1;
    } else {
      /* El lado base ser� el 1-2 */
      bx1 = (int) vertexPool[1].x;
      by1 = (int) vertexPool[1].y;
      bz1 = vertexPool[1].z;
      bx2 = (int) vertexPool[2].x;
      by2 = (int) vertexPool[2].y;
      bz2 = vertexPool[2].z;
      sx = (int) vertexPool[0].x;
      sy = (int) vertexPool[0].y;
      sz = vertexPool[0].z;
      bc1 = c1;
      bc2 = c2;
      sc = c0;
    }
    if (by1 > by2) {
      int tmpi = by1;
      by1 = by2;
      by2 = tmpi;
      tmpi = bx1;
      bx1 = bx2;
      bx2 = tmpi;
      tmpi = bc1;
      bc1 = bc2;
      bc2 = tmpi;
      float tmpf = bz1;
      bz1 = bz2;
      bz2 = tmpf;
    }
    float bdx, bdz, s1dx, s1dz, s2dx, s2dz, bda, bdr, bdg, bdb, s1da, s1dr, s1dg, s1db, s2da, s2dr, s2dg, s2db, dsx, dsz;
    int dscolor;
    dy = (int) (by2 - by1);
    if ((int) dy != 0) {
      bdx = (float) (bx2 - bx1) / dy;
      bdz = (float) (bz2 - bz1) / dy;
      bdr = (float) ((bc2 & 0x000000FF) - (bc1 & 0x000000FF)) / dy;
      bdg = (float) (((bc2 & 0x0000FF00) >> 8) - ((bc1 & 0x0000FF00) >> 8))
          / dy;
      bdb = (float) (((bc2 & 0x00FF0000) >> 16) - ((bc1 & 0x00FF0000) >> 16))
          / dy;
      bda = (float) (((bc2 >> 24) & 0x000000FF) - ((bc1 >> 24) & 0x000000FF))
          / dy;
    } else {
      bdx = 0;
      bdz = 0;
      bdr = 0;
      bdg = 0;
      bdb = 0;
      bda = 0;
    }
    float ds1y = (sy - by1);
    if ((int) ds1y != 0) {
      s1dx = (float) (sx - bx1) / ds1y;
      s1dz = (float) (sz - bz1) / ds1y;
      s1dr = (float) ((sc & 0x000000FF) - (bc1 & 0x000000FF)) / ds1y;
      s1dg = (float) (((sc & 0x0000FF00) >> 8) - ((bc1 & 0x0000FF00) >> 8))
          / ds1y;
      s1db = (float) (((sc & 0x00FF0000) >> 16) - ((bc1 & 0x00FF0000) >> 16))
          / ds1y;
      s1da = (float) (((sc >> 24) & 0x000000FF) - ((bc1 >> 24) & 0x000000FF))
          / ds1y;
      dsx = bx1;
      dsz = bz1;
      dscolor = bc1;
    } else {
      s1dx = 0;
      s1dz = 0;
      s1dr = 0;
      s1dg = 0;
      s1db = 0;
      s1da = 0;
      dsx = sx;
      dsz = sz;
      dscolor = sc;
    }
    float ds2y = (by2 - sy);
    if ((int) ds2y != 0) {
      s2dx = (float) (bx2 - sx) / ds2y;
      s2dz = (float) (bz2 - sz) / ds2y;
      s2dr = (float) ((bc2 & 0x000000FF) - (sc & 0x000000FF)) / ds2y;
      s2dg = (float) (((bc2 & 0x0000FF00) >> 8) - ((sc & 0x0000FF00) >> 8))
          / ds2y;
      s2db = (float) (((bc2 & 0x00FF0000) >> 16) - ((sc & 0x00FF0000) >> 16))
          / ds2y;
      s2da = (float) (((bc2 >> 24) & 0x000000FF) - ((sc >> 24) & 0x000000FF))
          / ds2y;
    } else {
      s2dx = 0;
      s2dz = 0;
      s2dr = 0;
      s2dg = 0;
      s2db = 0;
      s2da = 0;
    }
    float bx = bx1;
    float bz = bz1;

    float br = (bc1 & 0x000000FF);
    float bg = (bc1 & 0x0000FF00) >> 8;
    float bb = (bc1 & 0x00FF0000) >> 16;
    float ba = (bc1 >> 24) & 0x000000FF;
    int bcolor = bc1;

    float dsr = (dscolor & 0x000000FF);
    float dsg = (dscolor & 0x0000FF00) >> 8;
    float dsb = (dscolor & 0x00FF0000) >> 16;
    float dsa = (dscolor >> 24) & 0x000000FF;

    int pos;
    int init, end;
    float initz, ldz, initr, initg, initb, inita, ldr, ldg, ldb, lda;
    by2 = (by2 > height) ? height : by2;
    if (by1 < 0) {
      float skip = (-by1);
      bx += bdx * skip;
      bz += bdz * skip;
      br += bdr * skip;
      bg += bdg * skip;
      bb += bdb * skip;
      ba += bda * skip;
      bcolor = (int) br + ((int) bg << 8) + ((int) bb << 16)
          + ((int) ba << 24);
      if (sy > 0) {
        dsx += s1dx * skip;
        dsz += s1dz * skip;
        dsr += s1dr * skip;
        dsg += s1dg * skip;
        dsb += s1db * skip;
        dsa += s1da * skip;
        dscolor = (int) dsr + ((int) dsg << 8) + ((int) dsb << 16)
            + ((int) dsa << 24);
      } else {
        float skips = (-sy);
        dsx = sx + s2dx * skips;
        dsz = sz + s2dz * skips;
        dsr = (sc & 0xFF) + s2dr * skips;
        dsg = ((sc >> 8) & 0xFF) + s2dg * skips;
        dsb = ((sc >> 16) & 0xFF) + s2db * skips;
        dsa = ((sc >> 24) & 0xFF) + s2da * skips;
        dscolor = (int) dsr + ((int) dsg << 8) + ((int) dsb << 16)
            + ((int) dsa << 24);
      }
      by1 = 0;
    }
    if ((by1 < height) && (by2 > 0)) {
      for (int y = by1; y <= by2; y++) {
        /* Dibujamos la l�nea horizontal */
        if (bx > dsx) {
          init = (int) dsx;
          end = (int) bx;
          initz = dsz;
          ldz = (bz - dsz) / (end - init);
          initr = dsr;
          initg = dsg;
          initb = dsb;
          inita = dsa;
          ldr = (br - dsr) / (end - init);
          ldg = (bg - dsg) / (end - init);
          ldb = (bb - dsb) / (end - init);
          lda = (ba - dsa) / (end - init);
        } else {
          init = (int) bx;
          end = (int) dsx;
          initz = bz;
          ldz = (dsz - bz) / (end - init);
          initr = br;
          initg = bg;
          initb = bb;
          inita = ba;
          ldr = (dsr - br) / (end - init);
          ldg = (dsg - bg) / (end - init);
          ldb = (dsb - bb) / (end - init);
          lda = (dsa - ba) / (end - init);
        }
        end = (end > width) ? width : end;
        if (init < 0) {
          float skip = (-init);
          initz += ldz * skip;
          initr += ldr * skip;
          initg += ldg * skip;
          initb += ldb * skip;
          inita += lda * skip;
          init = 0;
        }
        pos = init + y * width;
        if ((y >= 0) && (y < height) && (init <= width) && (end >= 0))
          for (; init <= end; init++) {
            if ((init >= 0) && (init < width))
              if (depthTest(pos, initz))
                pixels[pos] = (int) initr + ((int) initg << 8)
                    + ((int) initb << 16)
                    + ((int) inita << 24);
            pos++;
            initz += ldz;
            initr += ldr;
            initg += ldg;
            initb += ldb;
            inita += lda;
          }
        /* Actualizamos los valores para la siguiente vuelta */
        bx += bdx;
        bz += bdz;
        br += bdr;
        bg += bdg;
        bb += bdb;
        ba += bda;
        bcolor = (int) br + ((int) bg << 8) + ((int) bb << 16)
            + ((int) ba << 24);

        dsx += ((y < sy) ? s1dx : s2dx);
        dsz += ((y < sy) ? s1dz : s2dz);
        dsr += ((y < sy) ? s1dr : s2dr);
        dsg += ((y < sy) ? s1dg : s2dg);
        dsb += ((y < sy) ? s1db : s2db);
        dsa += ((y < sy) ? s1da : s2da);
        dscolor = (int) dsr + ((int) dsg << 8) + ((int) dsb << 16)
            + ((int) dsa << 24);
      }
    }
    needUpdate = true;
  }

  /**
   * Dibuja un tri�ngulo utilizando el pool, con la textura seleccionada.
   */
  public void drawReplaceTexturedTriangle() {
    int color = lastColor.getPackedValue();
    /* Buscamos el lado cuya proyecci�n sobre el eje Y es m�s larga */
    int dy01 = ((int) vertexPool[1].y - (int) vertexPool[0].y);
    dy01 = (dy01 < 0) ? -dy01 : dy01;
    int dy02 = ((int) vertexPool[2].y - (int) vertexPool[0].y);
    dy02 = (dy02 < 0) ? -dy02 : dy02;
    int dy12 = ((int) vertexPool[2].y - (int) vertexPool[1].y);
    dy12 = (dy12 < 0) ? -dy12 : dy12;
    int dy;
    int bx1, bx2, by1, by2, sx, sy, btx1, bty1, btx2, bty2, stx, sty;
    float bz1, bz2, sz;
    N3InternalTexture texture = (N3InternalTexture) textures
        .elementAt(selectedTexture);
    if ((dy01 >= dy02) && (dy01 >= dy12)) {
      /* El lado base ser� el 0-1 */
      bx1 = (int) vertexPool[0].x;
      by1 = (int) vertexPool[0].y;
      bz1 = vertexPool[0].z;
      bx2 = (int) vertexPool[1].x;
      by2 = (int) vertexPool[1].y;
      bz2 = vertexPool[1].z;
      sx = (int) vertexPool[2].x;
      sy = (int) vertexPool[2].y;
      sz = vertexPool[2].z;

      btx1 = (int) (uvPool[0].u * (texture.width - 1));
      bty1 = (int) (uvPool[0].v * (texture.height - 1));
      btx2 = (int) (uvPool[1].u * (texture.width - 1));
      bty2 = (int) (uvPool[1].v * (texture.height - 1));
      stx = (int) (uvPool[2].u * (texture.width - 1));
      sty = (int) (uvPool[2].v * (texture.height - 1));

      dy = dy01;
    } else if ((dy02 >= dy01) && (dy02 >= dy12)) {
      /* El lado base ser� el 0-2 */
      bx1 = (int) vertexPool[0].x;
      by1 = (int) vertexPool[0].y;
      bz1 = vertexPool[0].z;
      bx2 = (int) vertexPool[2].x;
      by2 = (int) vertexPool[2].y;
      bz2 = vertexPool[2].z;
      sx = (int) vertexPool[1].x;
      sy = (int) vertexPool[1].y;
      sz = vertexPool[1].z;

      btx1 = (int) (uvPool[0].u * (texture.width - 1));
      bty1 = (int) (uvPool[0].v * (texture.height - 1));
      btx2 = (int) (uvPool[2].u * (texture.width - 1));
      bty2 = (int) (uvPool[2].v * (texture.height - 1));
      stx = (int) (uvPool[1].u * (texture.width - 1));
      sty = (int) (uvPool[1].v * (texture.height - 1));

      dy = dy02;
    } else {
      /* El lado base ser� el 1-2 */
      bx1 = (int) vertexPool[1].x;
      by1 = (int) vertexPool[1].y;
      bz1 = vertexPool[1].z;
      bx2 = (int) vertexPool[2].x;
      by2 = (int) vertexPool[2].y;
      bz2 = vertexPool[2].z;
      sx = (int) vertexPool[0].x;
      sy = (int) vertexPool[0].y;
      sz = vertexPool[0].z;

      btx1 = (int) (uvPool[1].u * (texture.width - 1));
      bty1 = (int) (uvPool[1].v * (texture.height - 1));
      btx2 = (int) (uvPool[2].u * (texture.width - 1));
      bty2 = (int) (uvPool[2].v * (texture.height - 1));
      stx = (int) (uvPool[0].u * (texture.width - 1));
      sty = (int) (uvPool[0].v * (texture.height - 1));

      dy = dy12;
    }
    if (by1 > by2) {
      int tmpi = by1;
      by1 = by2;
      by2 = tmpi;
      tmpi = bx1;
      bx1 = bx2;
      bx2 = tmpi;
      float tmpf = bz1;
      bz1 = bz2;
      bz2 = tmpf;
      tmpi = btx1;
      btx1 = btx2;
      btx2 = tmpi;
      tmpi = bty1;
      bty1 = bty2;
      bty2 = tmpi;
    }
    float bdx, bdz, s1dx, s1dz, s2dx, s2dz, dsx, dsz, btdx, btdy, s1tdx, s1tdy, s2tdx, s2tdy, dstx, dsty;
    if ((int) dy != 0) {
      bdx = (float) (bx2 - bx1) / dy;
      bdz = (float) (bz2 - bz1) / dy;
      btdx = (float) (btx2 - btx1) / dy;
      btdy = (float) (bty2 - bty1) / dy;
    } else {
      bdx = 0;
      bdz = 0;
      btdx = 0;
      btdy = 0;
    }
    if ((int) (sy - by1) != 0) {
      s1dx = (float) (sx - bx1) / (sy - by1);
      s1dz = (float) (sz - bz1) / (sy - by1);
      s1tdx = (float) (stx - btx1) / (sy - by1);
      s1tdy = (float) (sty - bty1) / (sy - by1);
      dsx = bx1;
      dsz = bz1;
      dstx = btx1;
      dsty = bty1;
    } else {
      s1dx = 0;
      s1dz = 0;
      s1tdx = 0;
      s1tdy = 0;
      dsx = sx;
      dsz = sz;
      dstx = stx;
      dsty = sty;
    }
    if ((int) (by2 - sy) != 0) {
      s2dx = (float) (bx2 - sx) / (by2 - sy);
      s2dz = (float) (bz2 - sz) / (by2 - sy);
      s2tdx = (float) (btx2 - stx) / (by2 - sy);
      s2tdy = (float) (bty2 - sty) / (by2 - sy);
    } else {
      s2dx = 0;
      s2dz = 0;
      s2tdx = 0;
      s2tdy = 0;
    }
    float bx = bx1;
    float bz = bz1;
    float btx = btx1;
    float bty = bty1;
    int pos;
    int init, end;
    float initz, ldz, inittx, initty, ltdx, ltdy;
    by2 = (by2 > height) ? height : by2;
    if (by1 < 0) {
      float skip = (-by1);
      bx += bdx * skip;
      bz += bdz * skip;
      btx += btdx * skip;
      bty += btdy * skip;
      if (sy > 0) {
        dsx += s1dx * skip;
        dsz += s1dz * skip;
        dstx += s1tdx * skip;
        dsty += s1tdy * skip;
      } else {
        float skips = (-sy);
        dsx = sx + s2dx * skips;
        dsz = sz + s2dz * skips;
        dstx = stx + s2tdx * skips;
        dsty = sty + s2tdy * skips;
      }
      by1 = 0;
    }
    int texdatapos;
    if ((by1 < height) && (by2 > 0)) {
      for (int y = by1; y <= by2; y++) {
        /* Dibujamos la l�nea horizontal */
        if (bx > dsx) {
          init = (int) dsx;
          end = (int) bx;
          initz = dsz;
          inittx = dstx;
          initty = dsty;
          ldz = (bz - dsz) / (end - init);
          ltdx = (btx - dstx) / (end - init);
          ltdy = (bty - dsty) / (end - init);
        } else {
          init = (int) bx;
          end = (int) dsx;
          inittx = btx;
          initty = bty;
          initz = bz;
          ldz = (dsz - bz) / (end - init);
          ltdx = (dstx - btx) / (end - init);
          ltdy = (dsty - bty) / (end - init);
        }
        end = (end > width) ? width : end;
        if (init < 0) {
          float skip = (-init);
          initz += ldz * skip;
          inittx += ltdx * skip;
          initty += ltdy * skip;
          init = 0;
        }
        pos = init + y * width;
        if ((y >= 0) && (y < height) && (init <= width) && (end >= 0)) {
          for (; init <= end; init++) {
            texdatapos = ((int) inittx + ((int) initty)
                * texture.width) * 4;
            if ((init >= 0) && (init < width))
              if (depthTest(pos, initz)) {
                color = ((int) texture.data[texdatapos])
                    + (((int) texture.data[texdatapos + 1]) << 8)
                    + (((int) texture.data[texdatapos + 2]) << 16)
                    + (((int) texture.data[texdatapos + 3]) << 24);
                pixels[pos] = color;
              }
            pos++;
            initz += ldz;
            inittx += ltdx;
            initty += ltdy;
          }
        }
        /* Actualizamos los valores para la siguiente vuelta */
        bx += bdx;
        bz += bdz;
        dsx += ((y < sy) ? s1dx : s2dx);
        dsz += ((y < sy) ? s1dz : s2dz);
        btx += btdx;
        bty += btdy;
        dstx += ((y < sy) ? s1tdx : s2tdx);
        dsty += ((y < sy) ? s1tdy : s2tdy);
      }
    }
    needUpdate = true;
  }

  /**
   * Dibuja un tri�ngulo utilizando el pool, con la textura seleccionada y el
   * �ltimo color especificado.
   */
  public void drawFlatTexturedTriangle() {
    int color = lastColor.getPackedValue();
    /* Buscamos el lado cuya proyecci�n sobre el eje Y es m�s larga */
    int dy01 = ((int) vertexPool[1].y - (int) vertexPool[0].y);
    dy01 = (dy01 < 0) ? -dy01 : dy01;
    int dy02 = ((int) vertexPool[2].y - (int) vertexPool[0].y);
    dy02 = (dy02 < 0) ? -dy02 : dy02;
    int dy12 = ((int) vertexPool[2].y - (int) vertexPool[1].y);
    dy12 = (dy12 < 0) ? -dy12 : dy12;
    int dy;
    int bx1, bx2, by1, by2, sx, sy, btx1, bty1, btx2, bty2, stx, sty;
    float bz1, bz2, sz;
    N3InternalTexture texture = (N3InternalTexture) textures
        .elementAt(selectedTexture);
    if ((dy01 >= dy02) && (dy01 >= dy12)) {
      /* El lado base ser� el 0-1 */
      bx1 = (int) vertexPool[0].x;
      by1 = (int) vertexPool[0].y;
      bz1 = vertexPool[0].z;
      bx2 = (int) vertexPool[1].x;
      by2 = (int) vertexPool[1].y;
      bz2 = vertexPool[1].z;
      sx = (int) vertexPool[2].x;
      sy = (int) vertexPool[2].y;
      sz = vertexPool[2].z;

      btx1 = (int) (uvPool[0].u * (texture.width - 1));
      bty1 = (int) (uvPool[0].v * (texture.height - 1));
      btx2 = (int) (uvPool[1].u * (texture.width - 1));
      bty2 = (int) (uvPool[1].v * (texture.height - 1));
      stx = (int) (uvPool[2].u * (texture.width - 1));
      sty = (int) (uvPool[2].v * (texture.height - 1));

      dy = dy01;
    } else if ((dy02 >= dy01) && (dy02 >= dy12)) {
      /* El lado base ser� el 0-2 */
      bx1 = (int) vertexPool[0].x;
      by1 = (int) vertexPool[0].y;
      bz1 = vertexPool[0].z;
      bx2 = (int) vertexPool[2].x;
      by2 = (int) vertexPool[2].y;
      bz2 = vertexPool[2].z;
      sx = (int) vertexPool[1].x;
      sy = (int) vertexPool[1].y;
      sz = vertexPool[1].z;

      btx1 = (int) (uvPool[0].u * (texture.width - 1));
      bty1 = (int) (uvPool[0].v * (texture.height - 1));
      btx2 = (int) (uvPool[2].u * (texture.width - 1));
      bty2 = (int) (uvPool[2].v * (texture.height - 1));
      stx = (int) (uvPool[1].u * (texture.width - 1));
      sty = (int) (uvPool[1].v * (texture.height - 1));

      dy = dy02;
    } else {
      /* El lado base ser� el 1-2 */
      bx1 = (int) vertexPool[1].x;
      by1 = (int) vertexPool[1].y;
      bz1 = vertexPool[1].z;
      bx2 = (int) vertexPool[2].x;
      by2 = (int) vertexPool[2].y;
      bz2 = vertexPool[2].z;
      sx = (int) vertexPool[0].x;
      sy = (int) vertexPool[0].y;
      sz = vertexPool[0].z;

      btx1 = (int) (uvPool[1].u * (texture.width - 1));
      bty1 = (int) (uvPool[1].v * (texture.height - 1));
      btx2 = (int) (uvPool[2].u * (texture.width - 1));
      bty2 = (int) (uvPool[2].v * (texture.height - 1));
      stx = (int) (uvPool[0].u * (texture.width - 1));
      sty = (int) (uvPool[0].v * (texture.height - 1));

      dy = dy12;
    }
    if (by1 > by2) {
      int tmpi = by1;
      by1 = by2;
      by2 = tmpi;
      tmpi = bx1;
      bx1 = bx2;
      bx2 = tmpi;
      float tmpf = bz1;
      bz1 = bz2;
      bz2 = tmpf;
      tmpi = btx1;
      btx1 = btx2;
      btx2 = tmpi;
      tmpi = bty1;
      bty1 = bty2;
      bty2 = tmpi;
    }
    float bdx, bdz, s1dx, s1dz, s2dx, s2dz, dsx, dsz, btdx, btdy, s1tdx, s1tdy, s2tdx, s2tdy, dstx, dsty;
    if ((int) dy != 0) {
      bdx = (float) (bx2 - bx1) / dy;
      bdz = (float) (bz2 - bz1) / dy;
      btdx = (float) (btx2 - btx1) / dy;
      btdy = (float) (bty2 - bty1) / dy;
    } else {
      bdx = 0;
      bdz = 0;
      btdx = 0;
      btdy = 0;
    }
    if ((int) (sy - by1) != 0) {
      s1dx = (float) (sx - bx1) / (sy - by1);
      s1dz = (float) (sz - bz1) / (sy - by1);
      s1tdx = (float) (stx - btx1) / (sy - by1);
      s1tdy = (float) (sty - bty1) / (sy - by1);
      dsx = bx1;
      dsz = bz1;
      dstx = btx1;
      dsty = bty1;
    } else {
      s1dx = 0;
      s1dz = 0;
      s1tdx = 0;
      s1tdy = 0;
      dsx = sx;
      dsz = sz;
      dstx = stx;
      dsty = sty;
    }
    if ((int) (by2 - sy) != 0) {
      s2dx = (float) (bx2 - sx) / (by2 - sy);
      s2dz = (float) (bz2 - sz) / (by2 - sy);
      s2tdx = (float) (btx2 - stx) / (by2 - sy);
      s2tdy = (float) (bty2 - sty) / (by2 - sy);
    } else {
      s2dx = 0;
      s2dz = 0;
      s2tdx = 0;
      s2tdy = 0;
    }
    float bx = bx1;
    float bz = bz1;
    float btx = btx1;
    float bty = bty1;
    int pos;
    int init, end;
    float initz, ldz, inittx, initty, ltdx, ltdy;
    by2 = (by2 > height) ? height : by2;
    if (by1 < 0) {
      float skip = (-by1);
      bx += bdx * skip;
      bz += bdz * skip;
      btx += btdx * skip;
      bty += btdy * skip;
      if (sy >= 0) {
        dsx += s1dx * skip;
        dsz += s1dz * skip;
        dstx += s1tdx * skip;
        dsty += s1tdy * skip;
      } else {
        float skips = (-sy);
        dsx = sx + s2dx * skips;
        dsz = sz + s2dz * skips;
        dstx = stx + s2tdx * skips;
        dsty = sty + s2tdy * skips;
      }
      by1 = 0;
    }
    int texdatapos;
    if ((by1 < height) && (by2 > 0)) {
      for (int y = by1; y <= by2; y++) {
        /* Dibujamos la l�nea horizontal */
        if (bx > dsx) {
          init = (int) dsx;
          end = (int) bx;
          initz = dsz;
          ldz = (bz - dsz) / (end - init);
          inittx = dstx;
          initty = dsty;
          ltdx = (btx - dstx) / (end - init);
          ltdy = (bty - dsty) / (end - init);
        } else {
          init = (int) bx;
          end = (int) dsx;
          initz = bz;
          ldz = (dsz - bz) / (end - init);
          inittx = btx;
          initty = bty;
          ltdx = (dstx - btx) / (end - init);
          ltdy = (dsty - bty) / (end - init);
        }
        end = (end > width) ? width : end;
        if (init < 0) {
          float skip = (-init);
          initz += ldz * skip;
          inittx += ltdx * skip;
          initty += ltdy * skip;
          init = 0;
        }
        pos = init + y * width;
        if ((y >= 0) && (y < height) && (init <= width) && (end >= 0)) {
          for (; init <= end; init++) {
            if ((init >= 0) && (init < width))
              if (depthTest(pos, initz)) {
                texdatapos = ((int) inittx + ((int) initty)
                    * texture.width) * 4;
                pixels[pos] = (int) (((int) texture.data[texdatapos] & 0xFF) * ((color & 0x000000FF) / 255))
                    | (int) ((((int) texture.data[texdatapos + 1] & 0xFF) * (((color & 0x0000FF00) >> 8) / 255)) << 8)
                    | (int) ((((int) texture.data[texdatapos + 2] & 0xFF) * (((color & 0x00FF0000) >> 16) / 255)) << 16)
                    | (int) ((((int) texture.data[texdatapos + 3] & 0xFF) * (((color >> 24) & 0x000000FF) / 255)) << 24);
                ;
              }
            pos++;
            initz += ldz;
            inittx += ltdx;
            initty += ltdy;
          }
        }
        /* Actualizamos los valores para la siguiente vuelta */
        bx += bdx;
        bz += bdz;
        dsx += ((y < sy) ? s1dx : s2dx);
        dsz += ((y < sy) ? s1dz : s2dz);
        btx += btdx;
        bty += btdy;
        dstx += ((y < sy) ? s1tdx : s2tdx);
        dsty += ((y < sy) ? s1tdy : s2tdy);
      }
    }
    needUpdate = true;
  }

  /**
   * Dibuja un tri�ngulo utilizando el pool, con la textura seleccionada, y
   * los colores del pool
   */
  public void drawGoraudTexturedTriangle() {
    int c0 = colorPool[0].getPackedValue();
    int c1 = colorPool[1].getPackedValue();
    int c2 = colorPool[2].getPackedValue();
    /* Buscamos el lado cuya proyecci�n sobre el eje Y es m�s larga */
    int dy01 = ((int) vertexPool[1].y - (int) vertexPool[0].y);
    dy01 = (dy01 < 0) ? -dy01 : dy01;
    int dy02 = ((int) vertexPool[2].y - (int) vertexPool[0].y);
    dy02 = (dy02 < 0) ? -dy02 : dy02;
    int dy12 = ((int) vertexPool[2].y - (int) vertexPool[1].y);
    dy12 = (dy12 < 0) ? -dy12 : dy12;
    int dy;
    int bx1, bx2, by1, by2, sx, sy, bc1, bc2, sc, btx1, bty1, btx2, bty2, stx, sty;
    float bz1, bz2, sz;
    N3InternalTexture texture = (N3InternalTexture) textures
        .elementAt(selectedTexture);
    if ((dy01 >= dy02) && (dy01 >= dy12)) {
      /* El lado base ser� el 0-1 */
      bx1 = (int) vertexPool[0].x;
      by1 = (int) vertexPool[0].y;
      bz1 = vertexPool[0].z;
      bx2 = (int) vertexPool[1].x;
      by2 = (int) vertexPool[1].y;
      bz2 = vertexPool[1].z;
      sx = (int) vertexPool[2].x;
      sy = (int) vertexPool[2].y;
      sz = vertexPool[2].z;
      bc1 = c0;
      bc2 = c1;
      sc = c2;

      btx1 = (int) (uvPool[0].u * (texture.width - 1));
      bty1 = (int) (uvPool[0].v * (texture.height - 1));
      btx2 = (int) (uvPool[1].u * (texture.width - 1));
      bty2 = (int) (uvPool[1].v * (texture.height - 1));
      stx = (int) (uvPool[2].u * (texture.width - 1));
      sty = (int) (uvPool[2].v * (texture.height - 1));

    } else if ((dy02 >= dy01) && (dy02 >= dy12)) {
      /* El lado base ser� el 0-2 */
      bx1 = (int) vertexPool[0].x;
      by1 = (int) vertexPool[0].y;
      bz1 = vertexPool[0].z;
      bx2 = (int) vertexPool[2].x;
      by2 = (int) vertexPool[2].y;
      bz2 = vertexPool[2].z;
      sx = (int) vertexPool[1].x;
      sy = (int) vertexPool[1].y;
      sz = vertexPool[1].z;
      bc1 = c0;
      bc2 = c2;
      sc = c1;

      btx1 = (int) (uvPool[0].u * (texture.width - 1));
      bty1 = (int) (uvPool[0].v * (texture.height - 1));
      btx2 = (int) (uvPool[2].u * (texture.width - 1));
      bty2 = (int) (uvPool[2].v * (texture.height - 1));
      stx = (int) (uvPool[1].u * (texture.width - 1));
      sty = (int) (uvPool[1].v * (texture.height - 1));

    } else {
      /* El lado base ser� el 1-2 */
      bx1 = (int) vertexPool[1].x;
      by1 = (int) vertexPool[1].y;
      bz1 = vertexPool[1].z;
      bx2 = (int) vertexPool[2].x;
      by2 = (int) vertexPool[2].y;
      bz2 = vertexPool[2].z;
      sx = (int) vertexPool[0].x;
      sy = (int) vertexPool[0].y;
      sz = vertexPool[0].z;
      bc1 = c1;
      bc2 = c2;
      sc = c0;

      btx1 = (int) (uvPool[1].u * (texture.width - 1));
      bty1 = (int) (uvPool[1].v * (texture.height - 1));
      btx2 = (int) (uvPool[2].u * (texture.width - 1));
      bty2 = (int) (uvPool[2].v * (texture.height - 1));
      stx = (int) (uvPool[0].u * (texture.width - 1));
      sty = (int) (uvPool[0].v * (texture.height - 1));

    }
    if (by1 > by2) {
      int tmpi = by1;
      by1 = by2;
      by2 = tmpi;
      tmpi = bx1;
      bx1 = bx2;
      bx2 = tmpi;
      tmpi = bc1;
      bc1 = bc2;
      bc2 = tmpi;
      float tmpf = bz1;
      bz1 = bz2;
      bz2 = tmpf;
      tmpi = btx1;
      btx1 = btx2;
      btx2 = tmpi;
      tmpi = bty1;
      bty1 = bty2;
      bty2 = tmpi;
    }
    float bdx, bdz, s1dx, s1dz, s2dx, s2dz, bda, bdr, bdg, bdb, s1da, s1dr, s1dg, s1db, s2da, s2dr, s2dg, s2db, dsx, dsz, btdx, btdy, s1tdx, s1tdy, s2tdx, s2tdy, dstx, dsty;
    int dscolor;
    dy = (int) (by2 - by1);
    if ((int) dy != 0) {
      bdx = (float) (bx2 - bx1) / dy;
      bdz = (float) (bz2 - bz1) / dy;
      bdr = (float) ((bc2 & 0x000000FF) - (bc1 & 0x000000FF)) / dy;
      bdg = (float) (((bc2 & 0x0000FF00) >> 8) - ((bc1 & 0x0000FF00) >> 8))
          / dy;
      bdb = (float) (((bc2 & 0x00FF0000) >> 16) - ((bc1 & 0x00FF0000) >> 16))
          / dy;
      bda = (float) (((bc2 >> 24) & 0x000000FF) - ((bc1 >> 24) & 0x000000FF))
          / dy;
      btdx = (float) (btx2 - btx1) / dy;
      btdy = (float) (bty2 - bty1) / dy;
    } else {
      bdx = 0;
      bdz = 0;
      bdr = 0;
      bdg = 0;
      bdb = 0;
      bda = 0;
      btdx = 0;
      btdy = 0;
    }
    float ds1y = (sy - by1);
    if ((int) ds1y != 0) {
      s1dx = (float) (sx - bx1) / ds1y;
      s1dz = (float) (sz - bz1) / ds1y;
      s1dr = (float) ((sc & 0x000000FF) - (bc1 & 0x000000FF)) / ds1y;
      s1dg = (float) (((sc & 0x0000FF00) >> 8) - ((bc1 & 0x0000FF00) >> 8))
          / ds1y;
      s1db = (float) (((sc & 0x00FF0000) >> 16) - ((bc1 & 0x00FF0000) >> 16))
          / ds1y;
      s1da = (float) (((sc >> 24) & 0x000000FF) - ((bc1 >> 24) & 0x000000FF))
          / ds1y;
      dsx = bx1;
      dsz = bz1;
      dscolor = bc1;
      s1tdx = (float) (stx - btx1) / ds1y;
      s1tdy = (float) (sty - bty1) / ds1y;
      dstx = btx1;
      dsty = bty1;
    } else {
      s1dx = 0;
      s1dz = 0;
      s1dr = 0;
      s1dg = 0;
      s1db = 0;
      s1da = 0;
      dsx = sx;
      dsz = sz;
      dscolor = sc;
      s1tdx = 0;
      s1tdy = 0;
      dstx = stx;
      dsty = sty;
    }
    float ds2y = (by2 - sy);
    if ((int) ds2y != 0) {
      s2dx = (float) (bx2 - sx) / ds2y;
      s2dz = (float) (bz2 - sz) / ds2y;
      s2dr = (float) ((bc2 & 0x000000FF) - (sc & 0x000000FF)) / ds2y;
      s2dg = (float) (((bc2 & 0x0000FF00) >> 8) - ((sc & 0x0000FF00) >> 8))
          / ds2y;
      s2db = (float) (((bc2 & 0x00FF0000) >> 16) - ((sc & 0x00FF0000) >> 16))
          / ds2y;
      s2da = (float) (((bc2 >> 24) & 0x000000FF) - ((sc >> 24) & 0x000000FF))
          / ds2y;
      s2tdx = (float) (btx2 - stx) / ds2y;
      s2tdy = (float) (bty2 - sty) / ds2y;
    } else {
      s2dx = 0;
      s2dz = 0;
      s2dr = 0;
      s2dg = 0;
      s2db = 0;
      s2da = 0;
      s2tdx = 0;
      s2tdy = 0;
    }
    float bx = bx1;
    float bz = bz1;
    float btx = btx1;
    float bty = bty1;

    float br = (bc1 & 0x000000FF);
    float bg = (bc1 & 0x0000FF00) >> 8;
    float bb = (bc1 & 0x00FF0000) >> 16;
    float ba = (bc1 >> 24) & 0x000000FF;
    int bcolor = bc1;

    float dsr = (dscolor & 0x000000FF);
    float dsg = (dscolor & 0x0000FF00) >> 8;
    float dsb = (dscolor & 0x00FF0000) >> 16;
    float dsa = (dscolor >> 24) & 0x000000FF;

    int pos;
    int init, end;
    float initz, ldz, initr, initg, initb, inita, ldr, ldg, ldb, lda, inittx, initty, ltdx, ltdy;
    by2 = (by2 > height) ? height : by2;
    if (by1 < 0) {
      float skip = (-by1);
      bx += bdx * skip;
      bz += bdz * skip;
      br += bdr * skip;
      bg += bdg * skip;
      bb += bdb * skip;
      ba += bda * skip;
      bcolor = (int) br + ((int) bg << 8) + ((int) bb << 16)
          + ((int) ba << 24);
      btx += btdx * skip;
      bty += btdy * skip;
      if (sy > 0) {
        dsx += s1dx * skip;
        dsz += s1dz * skip;
        dsr += s1dr * skip;
        dsg += s1dg * skip;
        dsb += s1db * skip;
        dsa += s1da * skip;
        dscolor = (int) dsr + ((int) dsg << 8) + ((int) dsb << 16)
            + ((int) dsa << 24);
        dstx += s1tdx * skip;
        dsty += s1tdy * skip;
      } else {
        float skips = (-sy);
        dsx = sx + s2dx * skips;
        dsz = sz + s2dz * skips;
        dsr = (sc & 0xFF) + s2dr * skips;
        dsg = ((sc >> 8) & 0xFF) + s2dg * skips;
        dsb = ((sc >> 16) & 0xFF) + s2db * skips;
        dsa = ((sc >> 24) & 0xFF) + s2da * skips;
        dscolor = (int) dsr + ((int) dsg << 8) + ((int) dsb << 16)
            + ((int) dsa << 24);
        dstx = stx + s2tdx * skips;
        dsty = sty + s2tdy * skips;
      }
      by1 = 0;
    }
    int texdatapos;
    if ((by1 < height) && (by2 > 0)) {
      for (int y = by1; y <= by2; y++) {
        /* Dibujamos la l�nea horizontal */
        if (bx > dsx) {
          init = (int) dsx;
          end = (int) bx;
          initz = dsz;
          ldz = (bz - dsz) / (end - init);
          initr = dsr;
          initg = dsg;
          initb = dsb;
          inita = dsa;
          ldr = (br - dsr) / (end - init);
          ldg = (bg - dsg) / (end - init);
          ldb = (bb - dsb) / (end - init);
          lda = (ba - dsa) / (end - init);
          inittx = dstx;
          initty = dsty;
          ltdx = (btx - dstx) / (end - init);
          ltdy = (bty - dsty) / (end - init);
        } else {
          init = (int) bx;
          end = (int) dsx;
          initz = bz;
          ldz = (dsz - bz) / (end - init);
          initr = br;
          initg = bg;
          initb = bb;
          inita = ba;
          ldr = (dsr - br) / (end - init);
          ldg = (dsg - bg) / (end - init);
          ldb = (dsb - bb) / (end - init);
          lda = (dsa - ba) / (end - init);
          inittx = btx;
          initty = bty;
          ltdx = (dstx - btx) / (end - init);
          ltdy = (dsty - bty) / (end - init);
        }
        end = (end > width) ? width : end;
        if (init < 0) {
          float skip = (-init);
          initz += ldz * skip;
          initr += ldr * skip;
          initg += ldg * skip;
          initb += ldb * skip;
          inita += lda * skip;
          inittx += ltdx * skip;
          initty += ltdy * skip;
          init = 0;
        }
        pos = init + y * width;
        if ((y >= 0) && (y < height) && (init <= width) && (end >= 0))
          for (; init <= end; init++) {
            if ((init >= 0) && (init < width))
              if (depthTest(pos, initz)) {
                texdatapos = ((int) inittx + ((int) initty)
                    * texture.width) * 4;
                pixels[pos] = (int) (((int) texture.data[texdatapos] & 0xFF) * (initr / 255))
                    | ((int) ((((int) texture.data[texdatapos + 1] & 0xFF) * (initg / 255))) << 8)
                    | ((int) ((((int) texture.data[texdatapos + 2] & 0xFF) * (initb / 255))) << 16)
                    | ((int) ((((int) texture.data[texdatapos + 3] & 0xFF) * (inita / 255))) << 24);
              }
            pos++;
            initz += ldz;
            initr += ldr;
            initg += ldg;
            initb += ldb;
            inita += lda;
            inittx += ltdx;
            initty += ltdy;
          }
        /* Actualizamos los valores para la siguiente vuelta */
        bx += bdx;
        bz += bdz;
        br += bdr;
        bg += bdg;
        bb += bdb;
        ba += bda;
        bcolor = (int) br + ((int) bg << 8) + ((int) bb << 16)
            + ((int) ba << 24);

        dsx += ((y < sy) ? s1dx : s2dx);
        dsz += ((y < sy) ? s1dz : s2dz);
        dsr += ((y < sy) ? s1dr : s2dr);
        dsg += ((y < sy) ? s1dg : s2dg);
        dsb += ((y < sy) ? s1db : s2db);
        dsa += ((y < sy) ? s1da : s2da);
        dscolor = (int) dsr + ((int) dsg << 8) + ((int) dsb << 16)
            + ((int) dsa << 24);

        btx += btdx;
        bty += btdy;
        dstx += ((y < sy) ? s1tdx : s2tdx);
        dsty += ((y < sy) ? s1tdy : s2tdy);
      }
    }
    needUpdate = true;
  }

  /*---------------------------------------------------------------------------------
  M�todos de la interfaz ImageProducer
  ---------------------------------------------------------------------------------*/

  public synchronized void addConsumer(ImageConsumer ic) {
    consumer = ic;
    consumer.setDimensions(width, height);
    consumer.setHints(ImageConsumer.TOPDOWNLEFTRIGHT
        | ImageConsumer.COMPLETESCANLINES | ImageConsumer.SINGLEPASS
        | ImageConsumer.SINGLEFRAME);
    consumer.setColorModel(colormodel);
  }

  public synchronized boolean isConsumer(ImageConsumer ic) {
    return ic == consumer;
  }

  public synchronized void removeConsumer(ImageConsumer ic) {
    if (ic == consumer)
      consumer = null;
  }

  public void requestTopDownLeftRightResend(ImageConsumer ic) {
  }

  public void startProduction(ImageConsumer ic) {
    addConsumer(ic);
  }
}
TOP

Related Classes of nu3a.render.software.N3SoftwareRenderContext$N3InternalTexture

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.