/*
======================================================================
libpr1.c

Eric Haines
Ernie Wright  01 Jun 05

A library of primitive object output routines, part 1 of 3.  Modified
for use in a LightWave Modeler plug-in.  Most of the public routines
here actually concern scene information.

   lib_output_comment()
   lib_output_viewpoint()
   lib_output_light()
   lib_output_background_color()

There are two utility routines that have been entirely removed from
this implementation.

   lib_output_vector()
   axis_to_z()

The vector function isn't called by any SPD component.  The axis
routine is called by a torus function in libpr3.c, in a section for
writing to ART format files, which has been removed.

The one object-related function here is

   lib_output_color()

which creates and initializes a LightWave surface.
====================================================================== */

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include "lwmod.h"
#include "def.h"
#include "lib.h"


/*
======================================================================
lib_output_comment()
====================================================================== */

void lib_output_comment( char *comment )
{
}


/*
======================================================================
lib_output_viewpoint()

Output viewpoint (camera) location.

   from           the eye location
   at             the center of the image, AKA "lookat"
   up             up vector
   fov_angle      vertical field of view of the camera
   aspect_ratio   aspect ratio of horizontal fov to vertical fov
   hither         distance to the near plane
   resx           X resolution of resulting image
   resy           Y resolution of resulting image

For all databases some viewing parameters are always the same.
Viewing angle is defined as from the center of top pixel row to
bottom pixel row and left column to right column.  Yon is "at
infinity."
====================================================================== */

void lib_output_viewpoint( COORD3 from, COORD3 at, COORD3 up,
   double fov_angle, double aspect_ratio, double hither, int resx, int resy )
{
   lwSetCamera( from, at, up, fov_angle, aspect_ratio, resx, resy );
}


/*
======================================================================
lib_output_light()

Output a point light source.
====================================================================== */

void lib_output_light( COORD4 center_pt )
{
   lwAddLight( center_pt, center_pt[ 3 ] );
}


/*
======================================================================
lib_output_background_color()

Output a scene background color.
====================================================================== */

void lib_output_background_color( COORD3 color )
{
   lwSetBackgroundColor( color );
}


/*
======================================================================
create_surface_name()

Called by lib_output_color()
====================================================================== */

static char *create_surface_name( char *name, int val )
{
   static char txname[ 32 ];

   sprintf( txname, "spd.%s.%02d", name, val );
   return txname;
}


/*
======================================================================
lib_output_color()

Create a surface and make it the default for subsequent geometry.

The routine name and color index are used to build a unique surface
name.  If a surface by that name already exists in Modeler, it's
made the current surface.  Otherwise a new surface is created.

The specular angle argument is the half angle, in degrees, at which
the intensity of the specular spot has fallen off to 50%.  This can
be converted to the exponent in the Phong specular expression, from
which LightWave's glossiness parameter can be derived.
====================================================================== */

char *lib_output_color(
   char  *name,         // routine name
   int    index,        // color index
   COORD3 color,        // base color
   double ka,           // ambient intensity (ignored, scene setting)
   double kd,           // diffuse intensity
   double ks,           // reflectivity
   double ks_spec,      // specularity
   double ang,          // half angle (degrees) of spec spot 50%
   double kt,           // transparency
   double i_of_r        // index of refraction
)
{
   double phong, gloss, lwcolor[ 3 ];
   char *surfname, *objname;
   LWSurfaceID *surfid;

   surfname = create_surface_name( name, index );
   objname = lwGetCurrentObject();

   /* if the surface already exists, just make it current */

   surfid = lwGetSurfacesByName( objname, surfname );
   if ( surfid && surfid[ 0 ] ) {
      lwSetDefaultSurface( surfname );
      return surfname;
   }

   if ( ang <= 0.0 )
      phong = 4096.0;
   else if ( ang >= 32.765 )
      phong = 4.0;
   else
      phong = log( 0.5 ) / log( cos( DEG2RAD( ang )));
   gloss = ( log2( phong ) - 2.0 ) / 10.0;

   lwCreateSurface( objname, surfname );
   lwSetSurfEdSurface( objname, surfname );

   lwcolor[ 0 ] = color[ 0 ];
   lwcolor[ 1 ] = color[ 1 ];
   lwcolor[ 2 ] = color[ 2 ];
   lwSetSurfaceColor( SURF_COLR, lwcolor );

   lwSetSurfaceFloat( SURF_DIFF, kd );
   lwSetSurfaceFloat( SURF_SPEC, ks_spec );
   lwSetSurfaceFloat( SURF_GLOS, gloss );
   lwSetSurfaceFloat( SURF_REFL, ks );
   lwSetSurfaceFloat( SURF_TRAN, kt );
   lwSetSurfaceFloat( SURF_RIND, i_of_r );

   lwSetDefaultSurface( surfname );
   return surfname;
}
