// ======================================================================== //
// Copyright 2009-2015 Intel Corporation                                    //
//                                                                          //
// Licensed under the Apache License, Version 2.0 (the "License");          //
// you may not use this file except in compliance with the License.         //
// You may obtain a copy of the License at                                  //
//                                                                          //
//     http://www.apache.org/licenses/LICENSE-2.0                           //
//                                                                          //
// Unless required by applicable law or agreed to in writing, software      //
// distributed under the License is distributed on an "AS IS" BASIS,        //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and      //
// limitations under the License.                                           //
// ======================================================================== //

#pragma once

struct ISPCTriangle 
{
  int v0;                /*< first triangle vertex */
  int v1;                /*< second triangle vertex */
  int v2;                /*< third triangle vertex */
  int materialID;        /*< material of triangle */
};

struct ISPCQuad
{
  int v0;                /*< first triangle vertex */
  int v1;                /*< second triangle vertex */
  int v2;                /*< third triangle vertex */
  int v3;                /*< fourth triangle vertex */
};

enum ISPCType { TRIANGLE_MESH, SUBDIV_MESH, HAIR_SET, INSTANCE, GROUP, QUAD_MESH, LINE_SEGMENTS };

struct ISPCGeometry
{
  ISPCType type;
};

struct ISPCTriangleMesh
{
  uniform ISPCGeometry geom;
  uniform Vec3fa* positions;    //!< vertex position array
  uniform Vec3fa* positions2;    //!< vertex position array
  uniform Vec3fa* normals;       //!< vertex normal array
  uniform Vec2f* texcoords;     //!< vertex texcoord array
  uniform ISPCTriangle* triangles;  //!< list of triangles
  uniform ISPCQuad* quads;  //!< list of triangles // FIXME: remove
  int numVertices;
  int numTriangles;
  int numQuads;
  int geomID;
  int meshMaterialID;
};

struct ISPCQuadMesh
{
  uniform ISPCGeometry geom;
  uniform Vec3fa* positions;    //!< vertex position array
  uniform Vec3fa* positions2;    //!< vertex position array
  uniform Vec3fa* normals;       //!< vertex normal array
  uniform Vec2f* texcoords;     //!< vertex texcoord array
  uniform ISPCQuad* quads;  //!< list of triangles
  int numVertices;
  int numQuads;
  int geomID;
  int meshMaterialID;
};

struct ISPCSubdivMesh
{
  uniform ISPCGeometry geom;
  uniform Vec3fa* positions;       //!< vertex positions
  uniform Vec3fa* normals;         //!< face vertex normals
  uniform Vec2f* texcoords;        //!< face texture coordinates
  uniform int* position_indices;   //!< position indices for all faces
  uniform int* normal_indices;     //!< normal indices for all faces
  uniform int* texcoord_indices;   //!< texcoord indices for all faces
  uniform int* verticesPerFace;    //!< number of indices of each face
  uniform int* holes;              //!< face ID of holes
  uniform float* subdivlevel;      //!< subdivision level
  uniform Vec2i* edge_creases;          //!< crease index pairs
  uniform float* edge_crease_weights;   //!< weight for each crease
  uniform int* vertex_creases;          //!< indices of vertex creases
  uniform float* vertex_crease_weights; //!< weight for each vertex crease
  uniform int* face_offsets;
  int numVertices;
  int numFaces;
  int numEdges;
  int numEdgeCreases;
  int numVertexCreases;
  int numHoles;
  int materialID;
  int geomID;
};

struct ISPCHair
{
  int vertex;
  int id;
};

struct ISPCLineSegments
{
  uniform ISPCGeometry geom;
  Vec3fa* v;        //!< control points (x,y,z,r)
  Vec3fa* v2;       //!< hair control points (x,y,z,r)
  int* indices;     //!< for each segment, index to first control point
  int numVertices;
  int numSegments;
  int materialID;
};

struct ISPCHairSet
{
  uniform ISPCGeometry geom;
  Vec3fa* v;       //!< hair control points (x,y,z,r)
  Vec3fa* v2;       //!< hair control points (x,y,z,r)
  ISPCHair* hairs; //!< for each hair, index to first control point
  int numVertices;
  int numHairs;
  int materialID;
};

struct ISPCInstance
{
  uniform ISPCGeometry geom;
  int8 align[12];
  struct {
    struct {
      Vec3fa vx;
      Vec3fa vy;
      Vec3fa vz;
    } l;
    Vec3fa p;
  } space;
  int geomID;
};

struct ISPCGroup
{
  ISPCGeometry geom;
  ISPCGeometry** geometries;
  size_t numGeometries;
};

struct ISPCAmbientLight
{
  Vec3fa L;                  //!< radiance of ambient light
};

struct ISPCPointLight
{
  Vec3fa P;                  //!< position of point light
  Vec3fa I;                  //!< radiant intensity of point light
};

struct ISPCDirectionalLight
{
  Vec3fa D;                  //!< Light direction
  Vec3fa E;                  //!< Irradiance (W/m^2)
};

struct ISPCDistantLight
{
  Vec3fa D;             //!< Light direction
  Vec3fa L;             //!< Radiance (W/(m^2*sr))
  float halfAngle;     //!< Half illumination angle
  float radHalfAngle;  //!< Half illumination angle in radians
  float cosHalfAngle;  //!< Cosine of half illumination angle
};

enum MaterialTy 
{ 
  MATERIAL_OBJ, 
  MATERIAL_THIN_DIELECTRIC, 
  MATERIAL_METAL, 
  MATERIAL_VELVET, 
  MATERIAL_DIELECTRIC, 
  MATERIAL_METALLIC_PAINT, 
  MATERIAL_MATTE, 
  MATERIAL_MIRROR, 
  MATERIAL_REFLECTIVE_METAL, 
  MATERIAL_HAIR 
};

struct ISPCMaterial
{
  int ty;
  int align0,align1,align2;
  Vec3fa v[7];
};

struct MatteMaterial
{
  int ty;
  int align[3];

  Vec3fa reflectance;
};

struct MirrorMaterial
{
  int ty;
  int align[3];
  Vec3fa reflectance;
};

enum TEXTURE_FORMAT {
  RGBA8        = 1,
  RGB8         = 2,
  FLOAT32      = 3,
};

struct Texture {      
  uniform int width;
  uniform int height;    
  uniform int format;
  uniform int bytesPerTexel;
  uniform int width_mask;
  uniform int height_mask;
  void *uniform data;
};

struct OBJMaterial
{
  int ty;
  int align[3];

  int illum;             /*< illumination model */
  float d;               /*< dissolve factor, 1=opaque, 0=transparent */
  float Ns;              /*< specular exponent */
  float Ni;              /*< optical density for the surface (index of refraction) */
  
  Vec3fa Ka;              /*< ambient reflectivity */
  Vec3fa Kd;              /*< diffuse reflectivity */
  Vec3fa Ks;              /*< specular reflectivity */
  Vec3fa Kt;              /*< transmission filter */

  Texture* map_d;
  Texture* map_Kd;          /*< dummy */
  Texture* map_Displ;       /*< dummy */
};

struct MetalMaterial
{
  int ty;
  int align[3];

  Vec3fa reflectance;
  Vec3fa eta;
  Vec3fa k;
  float roughness;
};

struct ReflectiveMetalMaterial
{
  int ty;
  int align[3];

  Vec3fa reflectance;
  Vec3fa eta;
  Vec3fa k;
  float roughness;
};

struct VelvetMaterial
{
  int ty;
  int align[3];

  Vec3fa reflectance;
  Vec3fa horizonScatteringColor;
  float backScattering;
  float horizonScatteringFallOff;
};

struct DielectricMaterial
{
  int ty;
  int align[3];
  Vec3fa transmissionOutside;
  Vec3fa transmissionInside;
  float etaOutside;
  float etaInside;
};

struct ThinDielectricMaterial
{
  int ty;
  int align[3];
  Vec3fa transmission;
  Vec3fa transmissionFactor;
  float eta;
  float thickness;
};

struct MetallicPaintMaterial
{
  int ty;
  int align[3];
  Vec3fa shadeColor;
  Vec3fa glitterColor;
  float glitterSpread;
  float eta;
};

struct HairMaterial
{
  int ty;
  int align[3];
  Vec3fa Kr;
  Vec3fa Kt;
  float nx;
  float ny;
};

struct ISPCSubdivMeshKeyFrame {
  ISPCSubdivMesh** subdiv;                   //!< list of subdiv meshes
  int numSubdivMeshes;                       //!< number of subdiv meshes
};

struct ISPCScene 
{
  uniform ISPCGeometry* uniform* geometries;   //!< list of geometries
  uniform ISPCMaterial* materials;             //!< material list
  int numGeometries;                           //!< number of geometries
  int numMaterials;                            //!< number of materials

  uniform ISPCAmbientLight* ambientLights; //!< list of ambient lights
  int numAmbientLights;                    //!< number of ambient lights
  
  uniform ISPCPointLight* pointLights;     //!< list of point lights
  int numPointLights;                      //!< number of point lights
  
  uniform ISPCDirectionalLight* dirLights; //!< list of directional lights
  int numDirectionalLights;                //!< number of directional lights

  uniform ISPCDistantLight* distantLights; //!< list of distant lights
  int numDistantLights;                    //!< number of distant lights

  ISPCSubdivMeshKeyFrame** subdivMeshKeyFrames;
  int numSubdivMeshKeyFrames;

}; // ISPCScene
