// -*- C++ -*-
#ifndef RIBMTREADER_H
#define RIBMTREADER_H
/* Copyright 1996 
 * Wed Jun 17 16:31:22 1998  Brian Edward Smits  (bes@phoenix.cs.utah.edu)
 * 
 * RiBMTReader.H
 * 
 *	
 * 
 * $Id: RiBMTReader.H,v 1.6 1999/10/01 18:23:02 bes Exp $ 
 * 
 */
#ifndef RICOMMON_H
#include <RiCommon.H>
#endif

#ifndef RIREADER_H
#include <RiReader.H>
#endif

#ifndef RITEXTURE_H
#include <RiTexture.H>
#endif


class RiMaterialBuilder;
class RiIORead;
class RiIOReadBinary;

/***************************************************************
CLASS
    RiBMTReader
     Reader for the Binary Model Transfer (simple binary data) format.

DESCRIPTION

GRAMMER
     Any values between !! are unsigned characters 						<BR>
     <file>        = <magic><statement>+ 							<BR>
     <magic>       = "BMT"!v! where v is the version (as unsigned char starting at 0)		<BR>
     <statement>   = <camera>|<poly>|<polyMesh>|<brdf>|assignBRDF|<EOF>				<BR>
     <camera>      = "c"!t!eeeaaafrl  where (all floats) e = eye, a = lookAt, f = fov (degrees),<BR>
                     r = aspect ratio, l = lens radius, and t is the type (0 only) 		<BR>
     <poly>        = "p"!t!!nn!<vertex_data>  !t! is vertexDataFormat !nn! is num vertices 	<BR>
     <vertex_data> = ppp|pppnnn|pppnnnuu|pppuu  p = pnt coord  n = normal coord  u = uv coord 	<BR>  
     <triMesh>     = "m"!t!!nnnn!!mmmm!<vertArray><normalArray><uvArray><pVertIndicesArray>    <BR>
                     !nnnn! is number of vertices (norms and uvs too if present) !mmmm! is number  <BR>
		     of tris <pvertIndicesArray> is an array of ints (length = 3 * numTris       <BR>
     <brdf>        = "b"!nnnn!!ssss!!c!* !nnnn! is the name index (increase from zero by one    <BR>
                      in the file) and !ssss! is the length of the material data (!c!) 		<BR>
     <assignBRDF>  = "B"!nnnn!  !nnnn! is the name index (increase from zero by one in the file)<BR>
     <pLight>	   = "l"!tt!<light specific data> 						<BR>
       <ambLight>    = <color>
       <dirLight>	   = <color><dir><char shadows>							<BR>
       <pointLight>  = <color><pos><radius><ushort decayRate><char shadows>			<BR>
       <coneSpotLt>  = <color><pos><dir><radius><ushort decayRate><coneAngle><penumAngle><char shadows> <BR>
       <sunLt>       = <turbidity><time (decimal)><short julian day><latitude><longitude>    <BR>
                       <short std Meridian><vector north><vector up><char shadows> <BR>
     <Inst>        = "i"!iiii!!mmmmmmmmmmmmmmmm!<all valid tags>"i"!iiii!			<BR>
                     iiii is 4byte instance ID (increasing from 0 by one, m* is 3x4 float matrix<BR>
     <InstRef>     = "I"!iiii!!mmmmmmmmmmmmmmmm! as above.	     				<BR>
     
  WARNING
     This file format is not meant to be editable.  There may be order specific or
     numbering specific things in the file.  Currently, the material ID is expected to
     increase by one from zero for each material read in the file.  The instance ID is
     also expected to increase this way (

     No swapping done.  Assumes all multibyte quantities are in SGI byte order.

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

class RiBMTReader : public RiReader {
  public:
				////
    enum  PolyTypeFlag {polyNormals = 1, polyUVs = 2};
				////
    enum  LightType {ambientLight = 1, directionalLight, pointLight, coneSpotLight, sunLight};
				// GROUP: Constructors and assignment
				//// Default Constructor (must have an istream handy)
    RiBMTReader(istream &);
				//// Reads an inst.  Does not insert it into instList.  That's for
				//   reading or for instances within this instance.
    RiBMTReader(RiIORead *in, int instNumber);
				//// Destructor
    virtual ~RiBMTReader();
				// GROUP: Members
				//// Read the input stream and return true for success.
    virtual bool Read();
  protected:
				////  Read in everything after the initial header (needed for instances)
    bool ReadGeometry();
				//// Read in a camera and construct it.
    bool ReadCamera();
				//// Read in a polygon and build it.
    bool ReadPolygon();
				//// Read in a polygonal mesh (UNIMPLEMENTED)
    bool ReadTriMesh();
				//// Handle materials (somehow)
    bool ReadMaterial();
				//// Handle all point/Maya style lights
    bool ReadPointLight();
				//// Handle setting the current material
    bool ReadSetMaterial();
				//// Handle the creation of an instance (after delegating the reading)
				//   Note that the creation is a reference as well.
				// EOI is set to true if the Read call closes the instance.
    bool ReadInstance(bool &EOI);
				//// Handle the reference of an instance
    bool ReadReferenceInstance();
  private:
    ////Copy Constructor
    RiBMTReader(const RiBMTReader &);
    //// Assignment
    RiBMTReader &operator=(const RiBMTReader &);
				//// Current valid material
    RiMaterial *currentMaterial;
				////
    int		 matBufferLen;
				////
    char	*matBuffer;
				////
    RiMaterialBuilder *materialBuilder;
				////
    RiIORead	*in;
				////
    unsigned int instNum;
				////  List of all instances read so far.
    static RWTValOrderedVector<RiRayObject *> instList;
				//// List of all materials found so far in the file (position == ID)
    static RWTValOrderedVector<RiMaterial *> materialList;
};



/***************************************************************
CLASS
    RiMaterialBuilder
     Tries to build materials based on a chunk of binary data

DESCRIPTION
     <Detailed description with any warnings>

GRAMMER
     <material data> = <material><modifier>*
     <material>      = !tt!!mmmm!<material specific data>
     <modifier>      = !tt!!mmmm!<modifier specific data><modifier>*
     mmmm            = unsigned int bit field.  (bits tell which part of the previous obj are to
                       be modified.
GRAMMER2
     <material>      = !tt!<material specific data> // eventually B[01]<bump mapping texture>
     <texture>       = !xx!<texture specific data>
     <color>         = "c"fff or "C"<spectral texture>
     <float>         = "f"f or "F"<float texture>
     <vect3>         = "v"fff or "V"<Vector texture>
     <vect2>         = "u"ff or "U"<2d vector texture>

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

class RiMaterialBuilder {
  public:
				//// Type of material node
				//   [] diffuse  Standard diffuse brdf
				//   [] coupled  Shirley coupled model (PacificGraphics 97)
				//   [] supersurface scattering model
				//   [] cookTorrance  slightly modified Cook-Torrance Model
    enum MaterialType {diffuse = 1, coupled, super, cookTorrance};
				//// Type of material node
				//   [] checker2D  Maya's 2dChecker Texture
    enum TextureType {checker2D = 1, ramp2D, file2D};
				// GROUP: Constructors and assignment
				//// Default Constructor
    RiMaterialBuilder(){}
				// GROUP: Members
				//// Build a material or return NULL if error/invalid/unavailable
    RiMaterial *Build(char *data, unsigned int len) const;
  private:
				////
    RiScalarTextureProxy   ReadScalar(RiIOReadBinary *in) const;
				////
    RiVector2TextureProxy  ReadVector2(RiIOReadBinary *in) const;
				////
    RiVector3TextureProxy  ReadVector3(RiIOReadBinary *in) const;
				////
    RiVector3TextureProxy  ReadColor(RiIOReadBinary *in) const;
				////
    RiSpectrumTextureProxy ReadSpectrum(RiIOReadBinary *in) const;
				////
    RiTexture *ReadTexture(RiIOReadBinary *in) const;
				////
    RiMaterial *BuildMaterial(RiIOReadBinary *in) const;
				////Copy Constructor
    RiMaterialBuilder(const RiMaterialBuilder &);
				//// Assignment
    RiMaterialBuilder &operator=(const RiMaterialBuilder &);
};



#endif /* RIBMTREADER_H */

