Skinny3DSources ƒ/Lights.c

// file Lights.c
 
#include <Types.h>
 
 
#include "SkinnyMain.h"
#include "Lights.h"
// #include "ValueControls.h"
 
// local prototypes
static VccPtr   LightDataToVcc      (TQ3LightData           lightData);
static VccPtr   DirectLightDataToVcc(TQ3DirectionalLightData drLightData);
static VccPtr   PointLightDataToVcc (TQ3PointLightData      ptLightData);
static VccPtr   SpotLightDataToVcc  (TQ3SpotLightData       spLightData);
static void     AddStdLightDataValues(VccPtr vcc, TQ3LightData lightData);
 
static void VccToLightData      (VccPtr vcc, TQ3LightData           *lightData);
static void VccToDirectLightData(VccPtr vcc, TQ3DirectionalLightData *drLightData);
static void VccToPointLightData (VccPtr vcc, TQ3PointLightData      *ptLightData);
static void VccToSpotLightData  (VccPtr vcc, TQ3SpotLightData       *spLightData);
static void GetStdLightDataValues(VccPtr vcc, TQ3LightData          *lightData);
 
static TQ3LightObject FindLight(TQ3GroupObject lightGroup, TQ3ObjectType lType);
 
extern Rect gContrlRect;
 
 
// --------------------------------------------------------------------
TQ3GroupObject MakeLights(void)
{
    TQ3GroupPosition            groupPosition;
    TQ3GroupObject          lightGroup;
    TQ3LightData                lightData;
    TQ3PointLightData       pointLightData;
    TQ3DirectionalLightData directLightData;
    TQ3SpotLightData            spotLightData;
    TQ3LightObject          ambientLight, pointLight, fillLight, spotLight;
    TQ3Point3D              pointLocation = { -10.0, 0.0, 10.0 };
    TQ3Vector3D             fillDirection = { -5.0, 0.0, 10.0 };
    TQ3Point3D              spotLocation = { -10.0, 10.0, 10.0 };
    TQ3Vector3D             spotDirection = { 10.0, -10.0, -10.0 };
    TQ3ColorRGB             WhiteLight = { 1.0, 1.0, 1.0 };
    
    //  Set up light data for ambient light.  This light data will be used for point and fill
    //  light also.
 
    lightData.isOn       = kQ3True;
    lightData.color      = WhiteLight;
    lightData.brightness = .2;
    
    //  Create ambient light.
    ambientLight = Q3AmbientLight_New(&lightData);
    if ( ambientLight == nil ) goto bail;
    
    //  Create point light.
    lightData.brightness = 1.0;
    pointLightData.lightData        = lightData;
    pointLightData.castsShadows     = kQ3False;
    pointLightData.attenuation      = kQ3AttenuationTypeNone;
    pointLightData.location         = pointLocation;
    pointLight = Q3PointLight_New(&pointLightData);
    if ( pointLight == nil ) goto bail;
 
    //  Create fill light.
    lightData.brightness = .8;
    directLightData.lightData       = lightData;
    directLightData.castsShadows    = kQ3False;
    directLightData.direction       = fillDirection;
    fillLight = Q3DirectionalLight_New(&directLightData);
    if ( fillLight == nil ) goto bail;
 
    //  Create spot light.
    lightData.brightness = .4;
    spotLightData.lightData     = lightData;
    spotLightData.castsShadows  = kQ3False;
    spotLightData.attenuation   = kQ3AttenuationTypeNone;
    spotLightData.location      = spotLocation;
    spotLightData.direction     = spotDirection;
    spotLightData.hotAngle      = 0.2;
    spotLightData.outerAngle    = 0.4;
    spotLightData.fallOff       = kQ3FallOffTypeLinear;
    
    spotLight = Q3SpotLight_New(&spotLightData);
    if ( spotLight == nil ) goto bail;
 
    //  Create light group and add each of the lights into the group.
    lightGroup = Q3LightGroup_New();
    if ( lightGroup == nil ) goto bail;
    
    groupPosition = Q3Group_AddObject(lightGroup, ambientLight);
    if ( groupPosition == 0 ) goto bail;
    groupPosition = Q3Group_AddObject(lightGroup, pointLight);
    if ( groupPosition == 0 ) goto bail;
    groupPosition = Q3Group_AddObject(lightGroup, fillLight);
    if ( groupPosition == 0 ) goto bail;
    groupPosition = Q3Group_AddObject(lightGroup, spotLight);
    if ( groupPosition == 0 ) goto bail;
 
    //  Done!
    return ( lightGroup );
    
bail: // If any of the above failed, then return nothing!
    return ( nil );
}
 
 
// --------------------------------------------------------------------
static TQ3LightObject FindLight(TQ3GroupObject lightGroup, TQ3ObjectType lType)
{
    TQ3Status       status;
    TQ3Object       object;
    TQ3LightObject  light;
    TQ3GroupPosition    position;
    Boolean         found = false;
 
    status = Q3Group_GetFirstPosition(lightGroup, &position);
    if (status != kQ3Success)
        return NULL;
    do {
        status = Q3Group_GetPositionObject(lightGroup, position, &object);
        if (object == NULL)
            return NULL;
        light = (TQ3LightObject)object;
        found = (Q3Light_GetType(light) == lType);
        status = Q3Group_GetNextPosition(lightGroup, &position);
    } while ((!found) && (position != NULL));
    if (found)
        return light;
    else
        return NULL;
}
 
 
// --------------------------------------------------------------------
VccPtr  LightToVCC(TQ3GroupObject lightGroup, long selector)
{
    TQ3LightObject  light;
    TQ3Status       status;
    TQ3ObjectType   lType;
    TQ3LightData                lightData;
    TQ3DirectionalLightData drLightData;
    TQ3PointLightData       ptLightData;
    TQ3SpotLightData            spLightData;
    
    switch (selector) {
        case iAmbient:      lType = kQ3LightTypeAmbient;        break;
        case iDirectional:  lType = kQ3LightTypeDirectional;    break;
        case iPoint:        lType = kQ3LightTypePoint;          break;
        case iSpot:         lType = kQ3LightTypeSpot;           break;
        default:    return nil;
    }
    light = FindLight(lightGroup, lType);
    
    switch (selector) {
        case iAmbient:
                status = Q3AmbientLight_GetData(light, &lightData);
                return LightDataToVcc(lightData);
            break;
        case iDirectional:
                status = Q3DirectionalLight_GetData(light, &drLightData);
                return DirectLightDataToVcc(drLightData);
            break;
        case iPoint:
                status = Q3PointLight_GetData(light, &ptLightData);
                return PointLightDataToVcc(ptLightData);
            break;
        case iSpot:
                status = Q3SpotLight_GetData(light, &spLightData);
                return SpotLightDataToVcc(spLightData);
            break;
        default:
            return nil;
    }
}
 
 
#define cBasicLines 7
 
// --------------------------------------------------------------------
static VccPtr   LightDataToVcc(TQ3LightData lightData)
{
    VccPtr      vcc;
 
    vcc = NewVCluster((long)kQ3LightTypeAmbient, "\pAmbientLightData", cBasicLines, &gContrlRect);
    if (vcc == nil) return nil;
    AddStdLightDataValues(vcc, lightData);
    return vcc;
}
 
 
// --------------------------------------------------------------------
static VccPtr   DirectLightDataToVcc(TQ3DirectionalLightData drLightData)
{
    VccPtr      vcc;
 
    vcc = NewVCluster((long)kQ3LightTypeDirectional, "\pDirectionalLightData", 
                                                                cBasicLines + 4, &gContrlRect);
    if (vcc == nil) return nil;
    AddStdLightDataValues(vcc, drLightData.lightData);
    AddValueCtl(vcc, "\pcastsShadows", drLightData.castsShadows,   0.0, 1.0, 1.0); // [7]
    AddValueCtl(vcc, "\pdirection.x",  drLightData.direction.x,  -30.0, 30.0, 3.0);
    AddValueCtl(vcc, "\pdirection.y",  drLightData.direction.y,  -30.0, 30.0, 3.0);
    AddValueCtl(vcc, "\pdirection.z",  drLightData.direction.z,  -30.0, 30.0, 3.0);
    return vcc;
}
 
 
// --------------------------------------------------------------------
static VccPtr   PointLightDataToVcc(TQ3PointLightData ptLightData)
{
    VccPtr      vcc;
 
    vcc = NewVCluster((long)kQ3LightTypePoint, "\pPointLightData", cBasicLines + 6, &gContrlRect);
    if (vcc == nil) return nil;
    AddStdLightDataValues(vcc, ptLightData.lightData);
    AddValueCtl(vcc, "\pcastsShadows", ptLightData.castsShadows, 0.0, 1.0, 1.0); // [7]
    AddValueCtl(vcc, "\pattenuation", ptLightData.attenuation,  0.0,  2.0, 1.0);
    AddSeparator(vcc);
    AddValueCtl(vcc, "\plocation.x", ptLightData.location.x,  -30.0, 30.0, 3.0); // [10]
    AddValueCtl(vcc, "\plocation.y", ptLightData.location.y,  -30.0, 30.0, 3.0);
    AddValueCtl(vcc, "\plocation.z", ptLightData.location.z,  -30.0, 30.0, 3.0);
    return vcc;
}
 
 
// --------------------------------------------------------------------
static VccPtr   SpotLightDataToVcc(TQ3SpotLightData spLightData)
{
    VccPtr      vcc;
 
    vcc = NewVCluster((long)kQ3LightTypeSpot, "\pSpotLightData", cBasicLines + 14, &gContrlRect);
    if (vcc == nil) return nil;
    AddStdLightDataValues(vcc, spLightData.lightData);
    AddValueCtl(vcc, "\pcastsShadows", spLightData.castsShadows, 0.0, 1.0, 1.0); // [7]
    AddValueCtl(vcc, "\pattenuation", spLightData.attenuation,  0.0,  2.0, 1.0);
    AddSeparator(vcc);
    AddValueCtl(vcc, "\plocation.x", spLightData.location.x,  -30.0, 30.0, 3.0); // [10]
    AddValueCtl(vcc, "\plocation.y", spLightData.location.y,  -30.0, 30.0, 3.0);
    AddValueCtl(vcc, "\plocation.z", spLightData.location.z,  -30.0, 30.0, 3.0);
    AddSeparator(vcc);
    AddValueCtl(vcc, "\pdirection.x", spLightData.direction.x,  -30.0, 30.0, 3.0); // [14]
    AddValueCtl(vcc, "\pdirection.y", spLightData.direction.y,  -30.0, 30.0, 3.0);
    AddValueCtl(vcc, "\pdirection.z", spLightData.direction.z,  -30.0, 30.0, 3.0);
    AddSeparator(vcc);
    AddValueCtl(vcc, "\photAngle",   spLightData.hotAngle,  0.05, 1.0, 0.05);  // [18]
    AddValueCtl(vcc, "\pouterAngle", spLightData.outerAngle, 0.1, 2.0, 0.1);
    AddValueCtl(vcc, "\pfallOff",    spLightData.fallOff,   0.0, 3.0, 1.0);
    return vcc;
}
 
 
// --------------------------------------------------------------------
static void AddStdLightDataValues(VccPtr vcc, TQ3LightData lightData)
{
    AddValueCtl(vcc, "\pisOn",      lightData.isOn,       0.0, 1.0, 1.0); // [0]
    AddValueCtl(vcc, "\pbrightness",lightData.brightness, 0.0, 1.0, 0.1);
    AddSeparator(vcc);
    AddValueCtl(vcc, "\pcolor.r",   lightData.color.r,    0.0, 1.0, 0.1); // [3]
    AddValueCtl(vcc, "\pcolor.g",   lightData.color.g,    0.0, 1.0, 0.1);
    AddValueCtl(vcc, "\pcolor.b",   lightData.color.b,    0.0, 1.0, 0.1);
    AddSeparator(vcc); // cBasicLines = 7
}
 
 
// --------------------------------------------------------------------
void VCCtoLight(VccPtr vcc, TQ3GroupObject lightGroup)
{
    TQ3LightData                lightData;
    TQ3DirectionalLightData drLightData;
    TQ3PointLightData       ptLightData;
    TQ3SpotLightData            spLightData;
    TQ3Status               status;
    TQ3LightObject          light;
    TQ3ObjectType           lType;
    
    lType = (TQ3ObjectType)GetIdTag(vcc);
    light = FindLight(lightGroup, lType);
    if (light == NULL)
        return;
        
    switch  (lType) {
        case kQ3LightTypeAmbient:
                VccToLightData(vcc, &lightData);
                status = Q3AmbientLight_SetData(light, &lightData);
            break;
        case kQ3LightTypeDirectional:
                VccToDirectLightData(vcc, &drLightData);
                status = Q3DirectionalLight_SetData(light, &drLightData);
            break;
        case kQ3LightTypePoint:
                VccToPointLightData(vcc, &ptLightData);
                status = Q3PointLight_SetData(light, &ptLightData);
            break;
        case kQ3LightTypeSpot:
                VccToSpotLightData(vcc, &spLightData);
                status = Q3SpotLight_SetData(light, &spLightData);
            break;
    }
}
 
 
// --------------------------------------------------------------------
static void VccToLightData(VccPtr vcc, TQ3LightData *lightData)
{
    lightData->isOn         = (GetCurrentValue(vcc, 0) == 1.0);
    lightData->brightness   = GetCurrentValue(vcc, 1);
    lightData->color.r      = GetCurrentValue(vcc, 3);
    lightData->color.g      = GetCurrentValue(vcc, 4);
    lightData->color.b      = GetCurrentValue(vcc, 5);
}
 
 
// --------------------------------------------------------------------
static void VccToDirectLightData(VccPtr vcc, TQ3DirectionalLightData *drLightData)
{
    VccToLightData(vcc, &drLightData->lightData);
 
    drLightData->castsShadows   = (GetCurrentValue(vcc, 7) == 1.0);
    
    drLightData->direction.x    = GetCurrentValue(vcc, 8);
    drLightData->direction.y    = GetCurrentValue(vcc, 9);
    drLightData->direction.z    = GetCurrentValue(vcc, 10);
}
 
 
// --------------------------------------------------------------------
static void VccToPointLightData (VccPtr vcc, TQ3PointLightData *ptLightData)
{
    VccToLightData(vcc, &ptLightData->lightData);
 
    ptLightData->castsShadows   = (GetCurrentValue(vcc, 7) == 1.0);
    ptLightData->attenuation    = GetCurrentValue(vcc, 8); // 0, 1, 2
    
    ptLightData->location.x     = GetCurrentValue(vcc, 10);
    ptLightData->location.y     = GetCurrentValue(vcc, 11);
    ptLightData->location.z     = GetCurrentValue(vcc, 12);
}
 
 
 
// --------------------------------------------------------------------
static void VccToSpotLightData (VccPtr vcc, TQ3SpotLightData *spLightData)
{
    VccToLightData(vcc, &spLightData->lightData);
    
    spLightData->castsShadows   = (GetCurrentValue(vcc, 7) == 1.0);
    spLightData->attenuation    = GetCurrentValue(vcc, 8); // 0, 1, 2
    
    spLightData->location.x     = GetCurrentValue(vcc, 10);
    spLightData->location.y     = GetCurrentValue(vcc, 11);
    spLightData->location.z     = GetCurrentValue(vcc, 12);
    
    spLightData->direction.x    = GetCurrentValue(vcc, 14);
    spLightData->direction.y    = GetCurrentValue(vcc, 15);
    spLightData->direction.z    = GetCurrentValue(vcc, 16);
 
    spLightData->hotAngle       = GetCurrentValue(vcc, 18);
    spLightData->outerAngle     = GetCurrentValue(vcc, 19);
    spLightData->fallOff        = GetCurrentValue(vcc, 20); // 0, 1, 2, 3
}