2
// Copyright ļæ½ 1997 - 2001, Paul C. Gregory
4
// Contact: pgregory@aqsis.com
6
// This library is free software; you can redistribute it and/or
7
// modify it under the terms of the GNU General Public
8
// License as published by the Free Software Foundation; either
9
// version 2 of the License, or (at your option) any later version.
11
// This library is distributed in the hope that it will be useful,
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
// General Public License for more details.
16
// You should have received a copy of the GNU General Public
17
// License along with this library; if not, write to the Free Software
18
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
\brief Implements a display driver for saving shadow maps.
23
\author Paul C. Gregory (pgregory@aqsis.com)
31
#ifdef AQSIS_SYSTEM_WIN32
42
#include "displaydriver.h"
46
#include "texturemap.h"
48
#if defined(AQSIS_SYSTEM_WIN32) || defined(AQSIS_SYSTEM_MACOSX)
52
using namespace Aqsis;
54
SqDDMessageFormatResponse frmt( 2 );
55
SqDDMessageCloseAcknowledge closeack;
57
void SaveAsShadowMap();
59
int main( int argc, char* argv[] )
62
char *portStr = getenv( "AQSIS_DD_PORT" );
64
if ( portStr != NULL )
66
port = atoi( portStr );
69
if ( DDInitialise( NULL, port ) == 0 )
76
#if defined(AQSIS_SYSTEM_WIN32) || defined(AQSIS_SYSTEM_MACOSX)
77
#define ZFILE_HEADER "Aqsis ZFile" VERSION_STR
78
#else // AQSIS_SYSTEM_WIN32
79
#define ZFILE_HEADER "Aqsis ZFile" VERSION
80
#endif // !AQSIS_SYSTEM_WIN32
86
uint16 g_Compression = COMPRESSION_NONE;
90
std::string strFilename( "output.tif" );
91
std::string strType( "zfile" );
92
TqFloat matWorldToCamera[ 4 ][ 4 ];
93
TqFloat matWorldToScreen[ 4 ][ 4 ];
95
TqInt Query( SOCKET s, SqDDMessageBase* pMsgB )
97
switch ( pMsgB->m_MessageID )
99
case MessageID_FormatQuery:
101
if ( DDSendMsg( s, &frmt ) <= 0 )
109
TqInt Open( SOCKET s, SqDDMessageBase* pMsgB )
111
SqDDMessageOpen * pMsg = static_cast<SqDDMessageOpen*>( pMsgB );
113
XRes = ( pMsg->m_CropWindowXMax - pMsg->m_CropWindowXMin );
114
YRes = ( pMsg->m_CropWindowYMax - pMsg->m_CropWindowYMin );
115
CWXMin = pMsg->m_CropWindowXMin;
116
CWYMin = pMsg->m_CropWindowYMin;
117
g_Channels = pMsg->m_Channels;
119
if ( g_Channels > 1 ) return ( -1 );
121
// Create a buffer big enough to hold a row of buckets.
122
pData = new TqFloat[ XRes * YRes ];
127
TqInt Data( SOCKET s, SqDDMessageBase* pMsgB )
129
SqDDMessageData * pMsg = static_cast<SqDDMessageData*>( pMsgB );
131
TqInt linelen = XRes * g_Channels;
132
char* pBucket = reinterpret_cast<char*>( &pMsg->m_Data );
135
for ( y = pMsg->m_YMin; y < pMsg->m_YMaxPlus1; y++ )
138
for ( x = pMsg->m_XMin; x < pMsg->m_XMaxPlus1; x++ )
140
if ( x >= 0 && y >= 0 && x < XRes && y < YRes )
142
TqInt so = ( y * linelen ) + ( x * g_Channels );
145
while ( i < g_Channels )
147
pData[ so++ ] = reinterpret_cast<TqFloat*>( pBucket ) [ i ];
151
pBucket += pMsg->m_ElementSize;
158
TqInt Close( SOCKET s, SqDDMessageBase* pMsgB )
160
// Save the shadowmap to a binary file.
161
if ( strFilename != "" )
163
if( strType.compare( "shadow" ) == 0 )
169
std::ofstream ofile( strFilename.c_str(), std::ios::out | std::ios::binary );
170
if ( ofile.is_open() )
172
// Save a file type and version marker
173
ofile << ZFILE_HEADER;
175
// Save the xres and yres.
176
ofile.write( reinterpret_cast<char* >( &XRes ), sizeof( XRes ) );
177
ofile.write( reinterpret_cast<char* >( &YRes ), sizeof( XRes ) );
179
// Save the transformation matrices.
180
ofile.write( reinterpret_cast<char*>( matWorldToCamera[ 0 ] ), sizeof( matWorldToCamera[ 0 ][ 0 ] ) * 4 );
181
ofile.write( reinterpret_cast<char*>( matWorldToCamera[ 1 ] ), sizeof( matWorldToCamera[ 0 ][ 0 ] ) * 4 );
182
ofile.write( reinterpret_cast<char*>( matWorldToCamera[ 2 ] ), sizeof( matWorldToCamera[ 0 ][ 0 ] ) * 4 );
183
ofile.write( reinterpret_cast<char*>( matWorldToCamera[ 3 ] ), sizeof( matWorldToCamera[ 0 ][ 0 ] ) * 4 );
185
ofile.write( reinterpret_cast<char*>( matWorldToScreen[ 0 ] ), sizeof( matWorldToScreen[ 0 ][ 0 ] ) * 4 );
186
ofile.write( reinterpret_cast<char*>( matWorldToScreen[ 1 ] ), sizeof( matWorldToScreen[ 0 ][ 0 ] ) * 4 );
187
ofile.write( reinterpret_cast<char*>( matWorldToScreen[ 2 ] ), sizeof( matWorldToScreen[ 0 ][ 0 ] ) * 4 );
188
ofile.write( reinterpret_cast<char*>( matWorldToScreen[ 3 ] ), sizeof( matWorldToScreen[ 0 ][ 0 ] ) * 4 );
190
// Now output the depth values
191
ofile.write( reinterpret_cast<char*>( pData ), sizeof( TqFloat ) * ( XRes * YRes ) );
196
if ( DDSendMsg( s, &closeack ) <= 0 )
203
TqInt Abandon( SOCKET s, SqDDMessageBase* pMsgB )
209
void SaveAsShadowMap()
211
TqChar version[ 80 ];
215
const char* mode = (g_append)? "a" : "w";
217
// Save the shadowmap to a binary file.
218
if ( strFilename.compare( "" ) != 0 )
220
TIFF * pshadow = TIFFOpen( strFilename.c_str(), mode );
221
if( pshadow != NULL )
223
TIFFCreateDirectory( pshadow );
225
#if defined(AQSIS_SYSTEM_WIN32) || defined(AQSIS_SYSTEM_MACOSX)
226
sprintf( version, "%s %s", STRNAME, VERSION_STR );
228
sprintf( version, "%s %s", STRNAME, VERSION );
230
TIFFSetField( pshadow, TIFFTAG_SOFTWARE, ( uint32 ) version );
231
TIFFSetField( pshadow, TIFFTAG_PIXAR_MATRIX_WORLDTOCAMERA, matWorldToCamera );
232
TIFFSetField( pshadow, TIFFTAG_PIXAR_MATRIX_WORLDTOSCREEN, matWorldToScreen );
233
TIFFSetField( pshadow, TIFFTAG_PIXAR_TEXTUREFORMAT, SHADOWMAP_HEADER );
234
TIFFSetField( pshadow, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK );
236
// Write the floating point image to the directory.
237
TqFloat *depths = ( TqFloat * ) pData;
239
#if defined(AQSIS_SYSTEM_WIN32) || defined(AQSIS_SYSTEM_MACOSX)
240
sprintf( version, "%s %s", STRNAME, VERSION_STR );
242
sprintf( version, "%s %s", STRNAME, VERSION );
244
TIFFSetField( pshadow, TIFFTAG_SOFTWARE, ( uint32 ) version );
245
TIFFSetField( pshadow, TIFFTAG_IMAGEWIDTH, XRes );
246
TIFFSetField( pshadow, TIFFTAG_IMAGELENGTH, YRes );
247
TIFFSetField( pshadow, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG );
248
TIFFSetField( pshadow, TIFFTAG_BITSPERSAMPLE, 32 );
249
TIFFSetField( pshadow, TIFFTAG_SAMPLESPERPIXEL, g_Channels );
250
TIFFSetField( pshadow, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT );
251
TIFFSetField( pshadow, TIFFTAG_TILEWIDTH, twidth );
252
TIFFSetField( pshadow, TIFFTAG_TILELENGTH, tlength );
253
TIFFSetField( pshadow, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP );
254
TIFFSetField( pshadow, TIFFTAG_COMPRESSION, g_Compression );
257
TqInt tsize = twidth * tlength;
258
TqInt tperrow = ( XRes + twidth - 1 ) / twidth;
259
TqFloat* ptile = static_cast<TqFloat*>( _TIFFmalloc( tsize * g_Channels * sizeof( TqFloat ) ) );
263
TqInt ctiles = tperrow * ( ( YRes + tlength - 1 ) / tlength );
265
for ( itile = 0; itile < ctiles; itile++ )
267
TqInt x = ( itile % tperrow ) * twidth;
268
TqInt y = ( itile / tperrow ) * tlength;
269
TqFloat* ptdata = pData + ( ( y * XRes ) + x ) * g_Channels;
270
// Clear the tile to black.
271
memset( ptile, 0, tsize * g_Channels * sizeof( TqFloat ) );
272
for ( TqUlong i = 0; i < tlength; i++ )
274
for ( TqUlong j = 0; j < twidth; j++ )
276
if ( ( x + j ) < XRes && ( y + i ) < YRes )
279
for ( ii = 0; ii < g_Channels; ii++ )
280
ptile[ ( i * twidth * g_Channels ) + ( ( ( j * g_Channels ) + ii ) ) ] = ptdata[ ( ( j * g_Channels ) + ii ) ];
283
ptdata += ( XRes * g_Channels );
285
TIFFWriteTile( pshadow, ptile, x, y, 0, 0 );
287
TIFFWriteDirectory( pshadow );
291
TIFFClose( pshadow );
297
TqInt HandleMessage( SOCKET s, SqDDMessageBase* pMsgB )
299
switch ( pMsgB->m_MessageID )
301
case MessageID_Filename:
303
SqDDMessageFilename * pMsg = static_cast<SqDDMessageFilename*>( pMsgB );
304
strFilename = pMsg->m_String;
308
case MessageID_DisplayType:
310
SqDDMessageDisplayType * pMsg = static_cast<SqDDMessageDisplayType*>( pMsgB );
311
strType = pMsg->m_String;
317
SqDDMessageNl* pMsg = static_cast<SqDDMessageNl*>( pMsgB );
318
memcpy( matWorldToCamera, pMsg->m_Matrix, sizeof( matWorldToCamera ) );
324
SqDDMessageNP* pMsg = static_cast<SqDDMessageNP*>( pMsgB );
325
memcpy( matWorldToScreen, pMsg->m_Matrix, sizeof( matWorldToScreen ) );
329
case MessageID_UserParam:
331
SqDDMessageUserParam * pMsg = static_cast<SqDDMessageUserParam*>( pMsgB );
332
// Check if we understand the parameter.
333
if( strncmp( pMsg->m_NameAndData, "append", pMsg->m_NameLength ) == 0 )
335
g_append = *reinterpret_cast<TqInt*>( &pMsg->m_NameAndData[ pMsg->m_NameLength + 1 ] );
337
else if( strncmp( pMsg->m_NameAndData, "compression", pMsg->m_NameLength ) == 0 )
339
const char* pvalue = reinterpret_cast<const char*>( &pMsg->m_NameAndData[ pMsg->m_NameLength + 1 ] );
340
if ( strstr( pvalue, "none" ) != 0 )
341
g_Compression = COMPRESSION_NONE;
342
else if ( strstr( pvalue, "lzw" ) != 0 )
343
g_Compression = COMPRESSION_LZW;
344
else if ( strstr( pvalue, "deflate" ) != 0 )
345
g_Compression = COMPRESSION_DEFLATE;
346
else if ( strstr( pvalue, "jpeg" ) != 0 )
347
g_Compression = COMPRESSION_JPEG;
348
else if ( strstr( pvalue, "packbits" ) != 0 )
349
g_Compression = COMPRESSION_PACKBITS;