2
// Copyright (C) 1997 - 2001, Paul C. Gregory
4
// Contact: pgregory@aqsis.org
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 Declares the CqMotionSpec template class for handling any class capable of being motion blurred.
23
\author Paul C. Gregory (pgregory@aqsis.org)
26
//? Is .h included already?
27
#ifndef MOTION_H_INCLUDED
28
#define MOTION_H_INCLUDED 1
32
#include <aqsis/aqsis.h>
34
#include <aqsis/ri/ri.h>
39
//----------------------------------------------------------------------
40
/** \class CqMotionSpec
41
* Abstract base class from which all classes supporting motion blur should derive.
48
/** Default constructor.
49
* \param a The default value for the motion object, used when expanding the timeslots.
51
CqMotionSpec( const T& a )
54
//AddTimeSlot(0.0f, a);
58
CqMotionSpec( const CqMotionSpec<T>& From )
62
virtual ~CqMotionSpec()
64
//for(std::vector<T>::iterator i=m_aObjects.begin(); i<m_aObjects.end(); i++)
65
// ClearMotionObject((*i));
68
/** Assignment operator.
70
void operator=( const CqMotionSpec<T>& From )
74
for ( std::vector<TqFloat>::const_iterator t = From.m_aTimes.begin(); t<From.m_aTimes.end(); t++ )
75
m_aTimes.push_back( *t );
76
for( typename std::vector<T>::const_iterator o = From.m_aObjects.begin(); o<From.m_aObjects.end(); o++ )
77
m_aObjects.push_back( *o );
78
m_DefObject = From.m_DefObject;
81
/** Put the specified motion object at the specified time, create a new timeslot if none exists,
82
* else overwrite the existing value.
83
* \param time The frame time to place the new object at.
84
* \param Object The new object to put in the timeslot.
86
void AddTimeSlot( TqFloat time, const T& Object )
91
m_aTimes.push_back( time );
92
m_aObjects.push_back( Object );
96
if ( TimeSlotExists( time, iIndex ) )
98
ClearMotionObject( m_aObjects[ iIndex ] );
99
m_aObjects[ iIndex ] = Object;
103
// Insert the timeslot at the proper place.
104
std::vector<TqFloat>::iterator itime = m_aTimes.begin();
105
typename std::vector<T>::iterator iobj = m_aObjects.begin();
106
while ( itime != m_aTimes.end() && *itime < time )
108
m_aTimes.insert( itime, time );
109
m_aObjects.insert( iobj, Object );
112
/** Combine the specified motion object with any existing one at the specified time.
113
* Will create a new timeslot if none exists.
114
* \param time The time of the relevant timeslot.
115
* \param Object The new obejct to combine with any existing one.
117
void ConcatTimeSlot( TqFloat time, const T& Object )
120
if ( TimeSlotExists( time, iIndex ) )
121
m_aObjects[ iIndex ] = ConcatMotionObjects( m_aObjects[ iIndex ], Object );
124
// Add a new slot a nd set it to the default value before concatenating the
126
AddTimeSlot( time, m_DefObject );
127
TimeSlotExists( time, iIndex );
128
m_aObjects[ iIndex ] = ConcatMotionObjects( m_aObjects[ iIndex ], Object );
131
/** Combine the specified motion object with all timeslots.
132
* \param Object The object to combine.
134
void ConcatAllTimeSlots( const T& Object )
136
for ( typename std::vector<T>::iterator i = m_aObjects.begin(); i<m_aObjects.end(); i++ )
137
( *i ) = ConcatMotionObjects( ( *i ), Object );
139
/** Get the frame time at the specified timeslot index.
140
* \param index The timeslot index/
141
* \return Float frame time.
143
TqFloat Time( TqInt index )
146
if ( m_aTimes.size() == 0 )
148
else if ( index < 0 )
149
return ( m_aTimes[ 0 ] );
150
else if ( index < cTimes() )
151
return ( m_aTimes[ index ] );
153
return ( m_aTimes.back() );
155
/** Get the number of timeslots.
156
* \return Integer timeslot count.
160
return ( m_aTimes.size() );
162
/** Return whether this motion block is actually motion blurred or not.
163
* \return Boolean indicating motion blurred.
165
bool fMotionBlurred() const
167
return ( cTimes() > 1 );
169
/** Get the index of the timeslot for the specified time, and if not exact, the fractional
170
* distance between it and the following timeslot 0-1.
171
* \param time Float frame time.
172
* \param iIndex Reference to the integer index to fill in.
173
* \param Fraction Reference to the float fraction to fill in.
174
* \return Boolean indicating the index is exact.
176
bool GetTimeSlot( TqFloat time, TqInt& iIndex, TqFloat& Fraction ) const
178
assert( cTimes() > 0 );
180
if ( time >= m_aTimes.back() )
182
iIndex = m_aTimes.size() - 1;
185
else if ( time <= m_aTimes.front() )
192
// Find the appropriate time span.
194
while ( time >= m_aTimes[ iIndex + 1 ] )
196
Fraction = ( time - m_aTimes[ iIndex ] ) / ( m_aTimes[ iIndex + 1 ] - m_aTimes[ iIndex ] );
197
return ( m_aTimes[ iIndex ] == time );
200
/** Get the index of the timeslot for the specified time, if it exists.
201
* \param time Float frame time.
202
* \param iIndex Reference to the integer index to fill in.
203
* \return Boolean indicating the index exists.
205
bool TimeSlotExists( TqFloat time, TqInt& iIndex ) const
207
//assert( cTimes() > 0 );
208
//assert(time>=0.0f);
210
// Find the appropriate time span.
212
while ( iIndex < cTimes() && time != m_aTimes[ iIndex ] )
214
return ( iIndex < cTimes() );
216
/** Get the motion object at the specified time using linearinterpolation as appropriate.
217
* \param time Float frame time.
218
* \return New object representing the motion object at the specified time.
220
T GetMotionObjectInterpolated( TqFloat time ) const
224
if ( GetTimeSlot( time, iIndex, Fraction ) )
225
return ( m_aObjects[ iIndex ] );
227
return ( LinearInterpolateMotionObjects( Fraction, m_aObjects[ iIndex ], m_aObjects[ iIndex + 1 ] ) );
230
/** Get the motion object at the specified time, will only work if the timeslot exists.
231
* \param time Float frame time.
232
* \return Reference to the object at the appropriate timeslot.
234
const T& GetMotionObject( TqFloat time ) const
238
if ( GetTimeSlot( time, iIndex, Fraction ) )
239
return ( m_aObjects[ iIndex ] );
243
return ( m_DefObject );
247
const T& GetDefaultObject() const
252
/** Get the motion object at the specified index.
253
* \param iIndex Index in the array of time slots.
254
* \return Reference to the object at the appropriate timeslot.
256
const T& GetMotionObject( TqInt iIndex ) const
258
assert( iIndex >= 0 && iIndex < cTimes() );
259
return ( m_aObjects[ iIndex ] );
262
/** Set the motion object to use as the default when expanding the timeslot list.
263
* \param a The new default motion object.
265
void SetDefaultObject( const T& a )
270
/** Empty all keyframes
276
typename std::vector<T>::iterator i;
277
for(i=m_aObjects.begin(); i!=m_aObjects.end(); i++)
278
ClearMotionObject(*i);
282
/** Pure virtual, overridden by deriving classes. Clear a motion object.
284
virtual void ClearMotionObject( T& A ) const = 0;
285
/** Pure virtual, overridden by deriving classes. Combine motion obects.
287
virtual T ConcatMotionObjects( const T& A, const T& B ) const = 0;
288
/** Pure virtual, overridden by deriving classes. Linear interpolate between motion objects.
290
virtual T LinearInterpolateMotionObjects( TqFloat Fraction, const T& A, const T& B ) const = 0;
293
std::vector<TqFloat> m_aTimes; ///< Array of float timeslot times.
294
std::vector<T> m_aObjects; ///< Array of motion objects for each timeslot.
295
T m_DefObject; ///< Default motion object, used when expanding the list of timeslots.
300
//-----------------------------------------------------------------------
304
#endif // MOTION_H_INCLUDED