Package nu3a.material

Source Code of nu3a.material.N3Material

/*
*  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.material;

import java.util.Vector;

import nu3a.material.color.N3ColorData;
import nu3a.material.color.N3ColorRGBA;
import nu3a.material.texture.N3Texture;
import nu3a.material.texture.N3Texture2D;
import nu3a.names.N3NameManager;
import nu3a.names.N3NamedObject;
import nu3a.names.exception.N3NameException;
import nu3a.persistence.N3PersistentResource;
import nu3a.persistence.N3PersistentResourceList;
import nu3a.persistence.N3SceneReader;
import nu3a.render.N3Render;
import nu3a.scene.N3Scene;
import nu3a.util.Observer;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

/**
* Clase que contiene informaci�n de material de un objeto.
*/
public class N3Material implements Observer, N3NamedObject,
    N3PersistentResource {
  /**
   * El material se aplica a la cara frontal.
   */
  public final static int N3_FRONT = 0;
  /**
   * El material se aplica a la cara trasera.
   */
  public final static int N3_BACK = 1;
  /**
   * El material se aplica por las dos caras.
   */
  public final static int N3_FRONT_AND_BACK = 2;

  /**
   * No se aplica textura.
   */
  public final static int N3_NO_TEXTURE = 0;
  /**
   * La textura reemplaza al color del objeto.
   */
  public final static int N3_REPLACE = 1;
  /**
   * La textura se aplica de forma decal.
   */
  public final static int N3_DECAL = 2;
  /**
   * La textura modula el color del objeto.
   */
  public final static int N3_MODULATE = 3;
  /**
   * La textura se aplica mediante haciendo blending.
   */
  public final static int N3_BLEND = 4;

  /**
   * Nombre del material
   */
  protected String name;

  /**
   * Escena a la que pertenece el material.
   */
  protected N3Scene scene;

  /**
   * Informaci�n del color del objeto.
   */
  protected N3ColorData colorData;

  /**
   * Texturas asociadas a este material.
   */
  protected Vector textures;

  /**
   * Indica que se aplica multitextura.
   */
  protected boolean multitexture;

  /**
   * Indica que la multitextura esta sucia y se debe recalcular.
   */
  protected boolean isDirty;

  /**
   * Almacena la textura resultado de la aplicaci�n de multitexturas.
   */
  protected N3Texture texture_calc;

  /**
   * Indica el modo seleccionado para aplicar la textura del material.
   */
  protected int texture_mode;

  /**
   * Indica cual era el estado del render
   */
  protected boolean oldTextureStatus;

  /**
   * Indica en el modo de textura �nica cual de las texturas que posee el
   * material es la textura activa.
   */
  protected N3Texture active_texture;

  /**
   * Indica si se aplica las caracteristicas del material.
   */
  protected boolean apply_material;

  /**
   * Indica a que cara(s) se aplica el material.
   */
  protected int face;

  /**
   * Color ambiental del material
   */
  protected N3ColorRGBA ambient_color;

  /**
   * Color difuso del material
   */
  protected N3ColorRGBA diffuse_color;

  /**
   * Color especular del material.
   */
  protected N3ColorRGBA specular_color;

  /**
   * Color de la luz emitida por el objeto.
   */
  protected N3ColorRGBA emission_color;

  /**
   * Brillo de la emision de color.
   */
  protected float shininess;

  /**
   * Constructor el material. Caracteristicas iniciales aaaa
   *
   * @param name
   *            Nombre del material.
   */
  public N3Material(N3Scene scene, String name) throws N3NameException {
    this.name = name;
    this.scene = scene;
    scene.addNamedObject(this);
    colorData = new N3ColorData();
    textures = new Vector(0, 1);
    texture_mode = N3_MODULATE;
    multitexture = false;
    isDirty = false;
    active_texture = null;
    apply_material = false;
    ambient_color = new N3ColorRGBA(1f, 1f, 1f);
    diffuse_color = new N3ColorRGBA(1f, 1f, 1f);
    specular_color = new N3ColorRGBA(1f, 1f, 1f);
    emission_color = new N3ColorRGBA(0f, 0f, 0f);
    face = N3_FRONT;
  }

  // ////////////// Implementaci�n de la interfaz N3NamedObject
  /**
   * Establece el nombre del nodo. Ha de ser �nico para toda la escena.
   *
   * @param n
   *            Nombre del nodo
   */
  public void setName(String n) throws N3NameException {
    scene.removeNamedObject(this);
    name = n;
    scene.addNamedObject(this);
  }

  public void setNameManager(N3NameManager manager) {
  }

  /**
   * Obtiene el nombre del nodo
   *
   * @return Nombre del nodo
   */
  public String getName() {
    return name;
  }

  // //////////////

  /**
   * Avisa del cambio de alguna de las texturas.
   */
  public void update() {
    setDirty();
  }

  /**
   * Permite cambiar la informaci�n de color del material
   *
   * @param colorData
   *            Informaci�n del color.
   */
  public void setColorData(N3ColorData colorData) {
    this.colorData = colorData;
  }

  /**
   * Permite obtener la informaci�n de color asociada a este material.
   *
   * @return Informaci�n de color del material.
   */
  public N3ColorData getColorData() {
    return colorData;
  }

  /**
   * Permite determinar de que forma se mezclan la textura y el color que
   * tiene asignado el material.
   *
   * @param mode
   *            Modo que se utilizar� para aplicar las texturas.
   */
  public void setTextureMode(int mode) {
    texture_mode = mode;
  }

  /**
   * Permite indicar si el material soporta multitextura.
   */
  public void setMultitexture(boolean multitexture, N3Render render) {
    this.multitexture = multitexture;
    if (isDirty)
      calculeMultitexture(render);
  }

  /**
   * Permite indicar que la multitextura esta sucia y es necesario
   * recalcularla.
   */
  protected void setDirty() {
    isDirty = true;
  }

  /**
   * Realiza el blending de dos texturas.
   *
   * @param dest
   *            Datos de la textura destino
   * @param src
   *            Datos de la textura or�gen
   * @param srcAlpha
   *            Transparencia de la textura or�gen
   */
  protected void blend(byte[] dest, byte[] src, float srcAlpha) {
    int end;
    end = (dest.length < src.length ? dest.length : src.length);
    float beta = (1.0f - srcAlpha);
    for (int i = 0; i < end; i++) {
      dest[i] = (byte) (((src[i] & 0xff) * srcAlpha) + ((dest[i] & 0xff) * beta));
    }
  }

  /**
   * Recalcula la multitextura generando la textura en el render indicado.
   */
  protected void calculeMultitexture(N3Render render) {
    if (!textures.isEmpty()) {
      N3Texture2D texture = (N3Texture2D) textures.elementAt(0);
      byte[] data = texture.getData();
      for (int i = 0; i < textures.size(); i++) {
        N3Texture2D texture2 = (N3Texture2D) textures.elementAt(i);
        blend(data, texture2.getData(), texture2.getAlpha());
      }
      try {
        texture_calc = new N3Texture2D(scene, name + "_multitext");
        texture_calc.genTexture(data, texture.getDataFormat(),
            texture.getWidth(), texture.getHeight(), render);
        active_texture = texture_calc;
      } catch (N3NameException ne) {
        System.out
            .println("Nombre de la multitextura repetida. Mal rollo!!!!");
        ne.printStackTrace();
      }
      isDirty = false;
    }
  }

  /*
   * Permite obtener el modo en el que se aplica la textura del material.
   *
   * @return Modo utilizado en la aplicaci�n de texturas.
   */
  public int getTextureMode() {
    return texture_mode;
  }

  /**
   * Permite a�adir una textura al material. En el modo de textura �nica la
   * �ltima textura a�adida es la textura que se aplica.
   *
   * @param texture
   *            Textura a a�adir.
   */
  public void addTexture(N3Texture texture) {
    active_texture = texture;
    texture.registryObserver(this);
    textures.add(texture);
    setDirty();
  }

  /**
   * Permite eliminar del material la textura indicada. Si la textura
   * eliminada era la activa en el modo de �nica textura, pasa a ser la
   * textura activa la anterior si existe.
   *
   * @param texture
   *            Textura a eliminar del material.
   */
  public void removeTexture(N3Texture texture) {

    if (!multitexture && texture == active_texture) {
      int i = textures.indexOf(texture);
      if (i > 0)
        active_texture = (N3Texture) textures.elementAt(i - 1);
      else
        active_texture = null;
    }
    texture.removeObserver(this);
    textures.remove(texture);
    setDirty();
  }

  /**
   * Permite indicar si se aplican o no las caracteriscas del material al
   * objeto. Es necesario ademas especificar las distintas componentes de
   * color del material para que se aplique el material.
   *
   * @param apply
   *            True si se aplican las caracteristicas.
   */
  public void applyMaterial(boolean apply) {
    apply_material = apply;
  }

  /**
   * Permite especificar la componente ambiental del material.
   *
   * @param c
   *            Color ambiental del material.
   */
  public void setAmbientColor(N3ColorRGBA c) {
    ambient_color = c;
  }

  /**
   * Permite especificar la componente difusa del material
   *
   * @param c
   *            Color difuso del material.
   */
  public void setDiffuseColor(N3ColorRGBA c) {
    diffuse_color = c;
  }

  /**
   * Permite especificar la componente especular del material.
   *
   * @param c
   *            Color especular del material.
   */
  public void setSpecularColor(N3ColorRGBA c, float shininess) {
    specular_color = c;
    this.shininess = shininess;
  }

  /**
   * Permite especificar la componente de emisi�n de color del material.
   *
   * @param c
   *            Color de emisi�n del material.
   * @param shininess
   */
  public void setEmissionColor(N3ColorRGBA c) {
    emission_color = c;
  }

  /**
   * Permite asignar todas las componentes del material.
   *
   * @param c
   *            Color ambiental del material.
   * @param c
   *            Color difuso del material.
   * @param c
   *            Color especular del material.
   * @param shininess
   * @param c
   *            Color de emisi�n del material.
   */
  public void setMaterialComponents(N3ColorRGBA ambient, N3ColorRGBA diffuse,
      N3ColorRGBA specular, float shininess, N3ColorRGBA emission) {
    ambient_color = ambient;
    diffuse_color = diffuse;
    specular_color = specular;
    emission_color = emission;
    this.shininess = shininess;
  }

  /**
   * Pone el material actual por defecto en el render. Todos los objetos
   * visuales se renderizaran con este material a partir de ahora.
   *
   * @param render
   *            Render en el que aplicar las caracter�sticas del material.
   */
  public void renderMaterial(N3Render render) {
    switch (face) {
    case N3_FRONT:
      face = render.N3_FRONT;
      break;
    case N3_BACK:
      face = render.N3_BACK;
      break;
    case N3_FRONT_AND_BACK:
      face = render.N3_FRONT_AND_BACK;
      break;
    }
    ;
    if (apply_material) {

      render.setColorMaterial(true);
      render.setColorMaterialAmbient(face, ambient_color);
      render.setColorMaterialDiffuse(face, diffuse_color);
      render.setColorMaterialSpecular(face, specular_color);
      render.setColorMaterialEmission(face, emission_color);
    } else {
      render.setColorMaterial(true);
      render.setColorMaterialAmbient(face, new N3ColorRGBA(1f, 1f, 1f));
      render.setColorMaterialDiffuse(face, new N3ColorRGBA(1f, 1f, 1f));
      render.setColorMaterialSpecular(face, new N3ColorRGBA(1f, 1f, 1f));
      render.setColorMaterialEmission(face, new N3ColorRGBA(0f, 0f, 0f));
    }

    if (texture_mode != N3_NO_TEXTURE && !textures.isEmpty()) {
      switch (texture_mode) {
      case N3_REPLACE:
        render.setTextureMode(render.N3_REPLACE);
        break;
      case N3_DECAL:
        render.setTextureMode(render.N3_DECAL);
        break;
      case N3_MODULATE:
        render.setTextureMode(render.N3_MODULATE);
        break;
      case N3_BLEND:
        render.setTextureMode(render.N3_BLEND);
        break;
      }
      render.setTexturing(true);
      render.selectTexture(active_texture);
      if (multitexture && isDirty)
        calculeMultitexture(render);
    } else {
      render.setTexturing(false);
    }
  }

  public void getPersistentResources(N3PersistentResourceList resources) {
    for (int i = 0; i < textures.size(); i++)
      resources.addResource((N3Texture) textures.elementAt(i));
    resources.addResource(ambient_color);
    resources.addResource(specular_color);
    resources.addResource(diffuse_color);
    resources.addResource(emission_color);
  }

  public Element getXMLDescription(Document doc,
      N3PersistentResourceList resources) {
    Element result = doc.createElement("resource");
    result.setAttribute("class", getClass().getName());

    Element textNode;

    Element data = doc.createElement("name");
    data.setAttribute("value", name);
    result.appendChild(data);

    data = doc.createElement("textureinfo");
    for (int i = 0; i < textures.size(); i++) {
      N3Texture t;
      t = (N3Texture) textures.elementAt(i);
      textNode = doc.createElement("textureitem");
      textNode.setAttribute("index", "" + resources.indexOf(t));
      data.appendChild(textNode);
    }
    result.appendChild(data);

    data = doc.createElement("multitexture");
    data.setAttribute("value", "" + multitexture);
    result.appendChild(data);

    data = doc.createElement("texturemode");
    data.setAttribute("value", "" + texture_mode);
    result.appendChild(data);

    data = doc.createElement("activetexture");
    data.setAttribute("textureindex", "" + textures.indexOf(active_texture));
    result.appendChild(data);

    data = doc.createElement("applymaterial");
    data.setAttribute("value", "" + apply_material);
    result.appendChild(data);

    data = doc.createElement("face");
    data.setAttribute("value", "" + face);
    result.appendChild(data);

    data = doc.createElement("shininess");
    data.setAttribute("value", "" + shininess);
    result.appendChild(data);

    data = doc.createElement("ambient");
    data.setAttribute("index", "" + resources.indexOf(ambient_color));
    result.appendChild(data);

    data = doc.createElement("specular");
    data.setAttribute("index", "" + resources.indexOf(specular_color));
    result.appendChild(data);

    data = doc.createElement("diffuse");
    data.setAttribute("index", "" + resources.indexOf(diffuse_color));
    result.appendChild(data);

    data = doc.createElement("emission");
    data.setAttribute("index", "" + resources.indexOf(emission_color));
    result.appendChild(data);

    return result;
  }

  /**
   * Devuelve una instancia de la clase, a partir de los par�metros, y de la
   * descripci�n XML en infoNode.
   *
   * @param infoNode
   *            Descripci�n XML de la instacia a crear
   * @param nodes
   *            Rama XML con las descripciones de los recursos de la escena
   * @param resources
   *            Lista de recursos de la escena
   * @param reader
   *            Instancia capaz de crear recursos que a�n no se han creado
   * @param render
   *            Render para el que se est� creando la escena
   * @param scene
   *            Escena que se est� creando
   * @return Instancia de la clase con la informaci�n especificada
   */
  public static N3PersistentResource loadInstance(Element infoNode,
      NodeList nodes, N3PersistentResourceList resources,
      N3SceneReader reader, N3Render render, N3Scene scene)
      throws Exception {
    Element texData;
    NodeList texts;
    N3Texture tex;
    int index;
    N3ColorRGBA a, s, d, e;
    float shininess;
    Element data = (Element) infoNode.getElementsByTagName("name").item(0);

    N3Material result = new N3Material(scene, data.getAttribute("value"));

    data = (Element) infoNode.getElementsByTagName("textureinfo").item(0);
    texts = infoNode.getElementsByTagName("textureitem");
    for (int i = 0; i < texts.getLength(); i++) {
      texData = (Element) texts.item(i);
      index = Integer.parseInt(texData.getAttribute("index"));
      tex = (N3Texture) reader.getResource(index, nodes);
      result.addTexture(tex);
    }
    data = (Element) infoNode.getElementsByTagName("multitexture").item(0);
    result.setMultitexture(
        (new Boolean(data.getAttribute("value"))).booleanValue(),
        render);
    data = (Element) infoNode.getElementsByTagName("texturemode").item(0);
    result.setTextureMode(Integer.parseInt(data.getAttribute("value")));
    data = (Element) infoNode.getElementsByTagName("activetexture").item(0);
    index = Integer.parseInt(data.getAttribute("textureindex"));
    if (index != -1)
      result.active_texture = (N3Texture) result.textures
          .elementAt(index);
    else
      result.active_texture = null;
    data = (Element) infoNode.getElementsByTagName("applymaterial").item(0);
    result.applyMaterial((new Boolean(data.getAttribute("value")))
        .booleanValue());
    data = (Element) infoNode.getElementsByTagName("face").item(0);
    result.face = Integer.parseInt(data.getAttribute("value"));

    data = (Element) infoNode.getElementsByTagName("shininess").item(0);
    shininess = Float.parseFloat(data.getAttribute("value"));
    data = (Element) infoNode.getElementsByTagName("ambient").item(0);
    index = Integer.parseInt(data.getAttribute("index"));
    a = (N3ColorRGBA) reader.getResource(index, nodes);
    data = (Element) infoNode.getElementsByTagName("diffuse").item(0);
    index = Integer.parseInt(data.getAttribute("index"));
    d = (N3ColorRGBA) reader.getResource(index, nodes);
    data = (Element) infoNode.getElementsByTagName("specular").item(0);
    index = Integer.parseInt(data.getAttribute("index"));
    s = (N3ColorRGBA) reader.getResource(index, nodes);
    data = (Element) infoNode.getElementsByTagName("emission").item(0);
    index = Integer.parseInt(data.getAttribute("index"));
    e = (N3ColorRGBA) reader.getResource(index, nodes);

    result.setMaterialComponents(a, d, s, shininess, e);

    return result;
  }
}
TOP

Related Classes of nu3a.material.N3Material

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.