[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8.2.2 A Complete Example

 
 
/*
    Copyright (c)The 3Delight Team.
    All Rights Reserved.
*/

//
// = LIBRARY
//     3delight
// = AUTHOR(S)
//     Aghiles Kheffache
// = VERSION
//     $Revision: 1.4 $
// = DATE RELEASED
//     $Date: 2003/06/30 19:30:17 $
// = RCSID
//     $Id: zfile.cpp,v 1.4 2003/06/30 19:30:17 aghiles Exp $
//

#include <ndspy.h>
#include <uparam.h>

#include <assert.h>
#include <stdio.h>
#include <float.h>
#include <string.h>
#include <limits.h>

/* ZFile Display Driver Implementation */

const unsigned kDefaultZFileSize = 512;

/*
zfile format:
    zFile format is (matrices and image are row-major):
    magic # (0x2f0867ab)                                    (4 bytes)
    width (short)                                           (2 bytes)
    height (short)                                          (2 bytes)
    shadow matrices (32 floats, 16 for NP and 16 for Nl)  (128 bytes)
    image data (floats)                        (width*height*4 bytes)
    
    NOTE
    Matrices are stored in row major format.
*/
class zFile
{
public:
    zFile(
        const char* fileName,
        const float* np, const float* nl,
        unsigned short width, unsigned short height )

    : m_file(0x0), m_width(width), m_height(height),
    m_currentLine(0), m_pixelsLeftOnLine(width)
    {
        m_file = fopen( fileName, "wb" );

        if( m_file )
        {
            unsigned long magic = 0x2f0867ab;

            assert( sizeof(long) == 4 );

            fwrite( &magic, 4, 1, m_file );
            fwrite( &m_width, sizeof(m_width), 1, m_file );
            fwrite( &m_height, sizeof(m_height), 1, m_file );
            fwrite( np, sizeof(float), 16, m_file );
            fwrite( nl, sizeof(float), 16, m_file );
        }
    }

    ~zFile()
    {
        if( m_file )
        {
            fclose(m_file);
        }
    }
    
    bool Valid() const { return m_file != 0x0; }

    unsigned GetWidth() const {return m_width;}
    unsigned GetHeight() const {return m_height;}

    bool WriteScanline(
        unsigned short y, unsigned short size, const float* data )
    {
        if( y != m_currentLine || size > m_pixelsLeftOnLine )
        {
            return false;
        }
        
        m_pixelsLeftOnLine -= size;

        if( m_pixelsLeftOnLine == 0 )
        {
            ++m_currentLine;
            m_pixelsLeftOnLine = m_width;
        }
        
        return fwrite( data, sizeof(float), size, m_file ) == size;
    }

private:
    FILE* m_file;
    unsigned short m_width;
    unsigned short m_height;

    unsigned short m_currentLine;
    unsigned short m_pixelsLeftOnLine;
};

/*
    A utility function to get user parameters ...
*/
const void* GetParameter(
    const char *name,
    unsigned n,
    const UserParameter parms[] )
{
    for( unsigned i=0; i<n; i++ )
    {
        if(0 == strcmp(name, parms[i].name))
        {
            return parms[i].value;
        }
    }
    return 0x0;
}

/*
    Open
*/
PtDspyError DspyImageOpen(
    PtDspyImageHandle *i_phImage,
    const char *i_drivername,
    const char *i_filename,
    int i_width,  int i_height,
    int i_parametercount,
    const UserParameter i_parameters[],
    int i_numFormat,
    PtDspyDevFormat i_format[],
    PtFlagStuff *flagstuff ) 
{
    int i;
    bool zfound = false;

    const float* nl =
        (float*)GetParameter( "Nl", i_parametercount, i_parameters );

    const float* np =
        (float*)GetParameter( "NP", i_parametercount, i_parameters );

    /* Loop through all provided data channels and only ask for the 'z'
       channel. */

    for( i=0; i<i_numFormat; i++ )
    {
        if( strcmp(i_format[i].name, "z") != 0 )
        {
            i_format[i].type = PkDspyNone;
        }
        else
        {
            i_format[i].type = PkDspyFloat32;
            zfound = true;
        }
    }

    if( !zfound )
    {
        fprintf( stderr, "dspy_z : need 'z' in order to proceed.\n" );
        return PkDspyErrorUnsupported;
    }

    if( !nl || !np )
    {
        fprintf(
            stderr,
            "dspy_z : need Nl & Np matrices in order to proceed. bug.\n" );
        return PkDspyErrorBadParams;
    }

    if (i_width > USHRT_MAX || i_height > USHRT_MAX)
    {
        fprintf(
            stderr,
            "dspy_z : image too large for zfile format" \
            " (use shadowmap ddriver).\n" );
        return PkDspyErrorUndefined;
    }    

    zFile* aZFile = new zFile( i_filename, np, nl, i_width, i_height );

    if( !aZFile || !aZFile->Valid() )
    {
        fprintf(
            stderr,
            "dspy_z : cannot create file" \
            "(permissions ? free disk space ?).\n" );

        delete aZFile;    
        return PkDspyErrorNoResource;
    }
    
    *i_phImage = (void*) aZFile;

    /* Ask display manager to provide data scanline by scanline
    */
    flagstuff->flags |= PkDspyFlagsWantsScanLineOrder;

    return PkDspyErrorNone;
}

/*
    DspyImageQuery
*/
PtDspyError DspyImageQuery(
    PtDspyImageHandle i_hImage,
    PtDspyQueryType i_type,
    size_t i_datalen,         
    void *i_data )
{
    zFile *aZFile = (zFile*) i_hImage;

    if( !i_data )
    {
        return PkDspyErrorBadParams;
    }
    
    switch( i_type )
    {
        case PkSizeQuery:
        {
            PtDspySizeInfo sizeQ;

            if( aZFile )
            {
                sizeQ.width = aZFile->GetWidth();
                sizeQ.height = aZFile->GetHeight();
                sizeQ.aspectRatio = 1;
            }
            else
            {
                sizeQ.width = kDefaultZFileSize;
                sizeQ.height = kDefaultZFileSize;
                sizeQ.aspectRatio = 1;
            }

            memcpy(
                i_data, &sizeQ,
                i_datalen>sizeof(sizeQ) ? sizeof(sizeQ) : i_datalen );

            break;
        }

        case PkOverwriteQuery:
        {
            PtDspyOverwriteInfo overwQ;

            overwQ.overwrite = 1;

            memcpy(
                i_data, &overwQ,
                i_datalen>sizeof(overwQ) ? sizeof(overwQ) : i_datalen );

            break;
        }

        default:
            return PkDspyErrorUnsupported;
    }

    return PkDspyErrorNone;        
}


/*
    DspyImageData
    
    Data is expected in scanline order (as asked in DspyImageOpen()).
*/
PtDspyError DspyImageData(
    PtDspyImageHandle i_hImage,
    int i_xmin, int i_xmax_plusone,
    int i_ymin, int i_ymax_plusone,
    int i_entrySize,        
    const unsigned char* i_data )
{
    zFile* aZFile = (zFile*) i_hImage;
    const float* fdata = (const float*) i_data;

    if( !aZFile || !fdata )
    {
        return PkDspyErrorBadParams;
    }

    /* Perform some sanity checks but everything should be fine really ...
       :> */

    if( i_ymax_plusone - i_ymin > 1 ||
        i_xmin != 0 ||
        i_xmax_plusone != aZFile->GetWidth() ||
        i_entrySize != sizeof(float) )
    {
        return PkDspyErrorBadParams;
    }

    if( !aZFile->WriteScanline(i_ymin, i_xmax_plusone - i_xmin, fdata) )
    {
        return PkDspyErrorNoResource;
    }

    return PkDspyErrorNone;
}

/*
    DspyImageDelayClose

    Not used by 3Delight yet.
*/
PtDspyError DspyImageDelayClose( PtDspyImageHandle i_hImage )
{
    return DspyImageClose( i_hImage );    
}

/*
    DspyImageClose
    
    delete our object.
*/
PtDspyError DspyImageClose( PtDspyImageHandle i_hImage )
{
    zFile* aZFile = (zFile*) i_hImage;
    
    if( !aZFile )
    {
        return PkDspyErrorUndefined;
    }

    delete aZFile;

    return PkDspyErrorNone;
}



[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

This document was generated by Aghiles Kheffache on July, 31 2003 using texi2html
3Delight 1.0.0. Copyright 2000-2003 The 3Delight Team. All Rights Reserved.