/* Copyright (C) 2003 by Peter Eastman

   This program 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 2 of the License, or (at your option) any later version.

   This program 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. */

package artofillusion.texture;

import artofillusion.*;
import artofillusion.object.*;
import java.io.*;

/** This class defines a scalar parameter who value is defined at each vertex of each face of a mesh. */

public class FaceVertexParameterValue implements ParameterValue
{
  private double value[][];
  
  /** Create a new FaceVertexParameterValue object.  val is an array of size [3][n] where n is the
      number of faces in the mesh. */
  
  public FaceVertexParameterValue(double val[][])
  {
    value = val;
  }
  
  /** Create a new FaceVertexParameterValue for a triangle mesh, and initialize it to appropriate default values. */
  
  public FaceVertexParameterValue(TriangleMesh mesh, TextureParameter param)
  {
    MeshVertex vert[] = mesh.getVertices();
    TriangleMesh.Face face[] = mesh.getFaces();
    value = new double [3][face.length];
    if (param.type == TextureParameter.NORMAL_PARAMETER)
      for (int i = 0; i < value.length; i++)
        for (int j = 0; j < value[i].length; j++)
          value[i][j] = param.defaultVal;
    if (param.type == TextureParameter.X_COORDINATE)
      for (int i = 0; i < face.length; i++)
      {
        value[0][i] = vert[face[i].v1].r.x;
        value[1][i] = vert[face[i].v2].r.x;
        value[2][i] = vert[face[i].v3].r.x;
      }
    if (param.type == TextureParameter.Y_COORDINATE)
      for (int i = 0; i < face.length; i++)
      {
        value[0][i] = vert[face[i].v1].r.y;
        value[1][i] = vert[face[i].v2].r.y;
        value[2][i] = vert[face[i].v3].r.y;
      }
    if (param.type == TextureParameter.Z_COORDINATE)
      for (int i = 0; i < face.length; i++)
      {
        value[0][i] = vert[face[i].v1].r.z;
        value[1][i] = vert[face[i].v2].r.z;
        value[2][i] = vert[face[i].v3].r.z;
      }
  }
  
  /** Get the list of parameter values. */
  
  public double [][] getValue()
  {
    return value;
  }
  
  /** Set the list of parameter values. */
  
  public void setValue(double val[][])
  {
    value = val;
  }
  
  /** Get the value of the parameter at a particular point in a particular triangle. */
  
  public double getValue(int tri, int v1, int v2, int v3, double u, double v, double w)
  {
    return u*value[0][tri]+v*value[1][tri]+w*value[2][tri];
  }
  
  /** Get the average value of the parameter over the entire surface. */
  
  public double getAverageValue()
  {
    double avg = 0.0;
    int n = 0;
    
    for (int i = 0; i < value.length; i++)
      for (int j = 0; j < value[i].length; j++)
      {
        avg += value[i][j];
        n++;
      }
    return (avg/n);
  }
  
  /** Create a duplicate of this object. */
  
  public ParameterValue duplicate()
  {
    double d[][] = new double [value.length][];
    for (int i = 0; i < d.length; i++)
    {
      d[i] = new double [value[i].length];
      System.arraycopy(value[i], 0, d[i], 0, value[i].length);
    }
    return new FaceVertexParameterValue(d);
  }
  
  /** Determine whether this object represents the same set of values as another one. */
  
  public boolean equals(Object o)
  {
    if (!(o instanceof FaceVertexParameterValue))
      return false;
    FaceVertexParameterValue v = (FaceVertexParameterValue) o;
    if (v.value[0].length != value[0].length)
      return false;
    for (int i = 0; i < value.length; i++)
      for (int j = 0; j < value[i].length; j++)
        if (v.value[i][j] != value[i][j])
          return false;
    return true;
  }
  
  /** Write out a serialized representation of this object to a stream. */
  
  public void writeToStream(DataOutputStream out) throws IOException
  {
    out.writeInt(value[0].length);
    for (int i = 0; i < value.length; i++)
      for (int j = 0; j < value[i].length; j++)
        out.writeDouble(value[i][j]);
  }
  
  /** Reconstruct a serialized object. */
  
  public FaceVertexParameterValue(DataInputStream in) throws IOException
  {
    int len = in.readInt();
    value = new double [3][len];
    for (int i = 0; i < value.length; i++)
      for (int j = 0; j < value[i].length; j++)
        value[i][j] = in.readDouble();
  }
}
