2013-07-24 16:13:57 +00:00
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers , whose names
* are too numerous to list here . Please refer to the COPYRIGHT
* file distributed with this source distribution .
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation ; either version 2
* of the License , or ( at your option ) any later version .
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 , USA .
*
*/
# include "common/scummsys.h"
2013-07-29 15:59:09 +00:00
# include "graphics/colormasks.h"
2013-07-24 16:13:57 +00:00
2013-07-29 02:37:32 +00:00
# include "zvision/render_table.h"
2013-07-29 20:03:08 +00:00
# include "zvision/vector2.h"
2013-07-24 16:13:57 +00:00
namespace ZVision {
2013-07-26 19:28:08 +00:00
RenderTable : : RenderTable ( uint32 numColumns , uint32 numRows )
2013-07-24 16:13:57 +00:00
: _numRows ( numRows ) ,
2013-07-26 17:26:30 +00:00
_numColumns ( numColumns ) ,
_renderState ( RenderState : : FLAT ) {
2013-07-24 16:13:57 +00:00
assert ( numRows ! = 0 & & numColumns ! = 0 ) ;
2013-07-29 20:03:08 +00:00
_internalBuffer = new Vector2 [ numRows * numColumns ] ;
2013-07-24 16:13:57 +00:00
}
RenderTable : : ~ RenderTable ( ) {
delete [ ] _internalBuffer ;
}
void RenderTable : : setRenderState ( RenderState newState ) {
_renderState = newState ;
switch ( newState ) {
case PANORAMA :
_panoramaOptions . fieldOfView = 60 ;
2013-07-29 02:38:53 +00:00
_panoramaOptions . linearScale = 0.55f ;
2013-07-24 16:13:57 +00:00
break ;
case TILT :
2013-07-29 20:08:03 +00:00
2013-07-24 16:13:57 +00:00
break ;
case FLAT :
// Intentionally left empty
break ;
}
}
2013-07-29 15:59:09 +00:00
uint16 mixTwoRGB ( uint16 colorOne , uint16 colorTwo , float percentColorOne ) {
assert ( percentColorOne < 1.0f ) ;
float rOne = float ( ( colorOne & Graphics : : ColorMasks < 555 > : : kRedMask ) > > Graphics : : ColorMasks < 555 > : : kRedShift ) ;
float rTwo = float ( ( colorTwo & Graphics : : ColorMasks < 555 > : : kRedMask ) > > Graphics : : ColorMasks < 555 > : : kRedShift ) ;
float gOne = float ( ( colorOne & Graphics : : ColorMasks < 555 > : : kGreenMask ) > > Graphics : : ColorMasks < 555 > : : kGreenShift ) ;
float gTwo = float ( ( colorTwo & Graphics : : ColorMasks < 555 > : : kGreenMask ) > > Graphics : : ColorMasks < 555 > : : kGreenShift ) ;
float bOne = float ( ( colorOne & Graphics : : ColorMasks < 555 > : : kBlueMask ) > > Graphics : : ColorMasks < 555 > : : kBlueShift ) ;
float bTwo = float ( ( colorTwo & Graphics : : ColorMasks < 555 > : : kBlueMask ) > > Graphics : : ColorMasks < 555 > : : kBlueShift ) ;
float rFinal = rOne * percentColorOne + rTwo * ( 1.0f - percentColorOne ) ;
float gFinal = gOne * percentColorOne + gTwo * ( 1.0f - percentColorOne ) ;
float bFinal = bOne * percentColorOne + bTwo * ( 1.0f - percentColorOne ) ;
uint16 returnColor = ( byte ( rFinal + 0.5f ) < < Graphics : : ColorMasks < 555 > : : kRedShift ) |
( byte ( gFinal + 0.5f ) < < Graphics : : ColorMasks < 555 > : : kGreenShift ) |
( byte ( bFinal + 0.5f ) < < Graphics : : ColorMasks < 555 > : : kBlueShift ) ;
return returnColor ;
}
2013-07-29 02:37:32 +00:00
void RenderTable : : mutateImage ( uint16 * sourceBuffer , uint16 * destBuffer , uint32 imageWidth , uint32 imageHeight , Common : : Rect subRectangle , Common : : Rect destRectangle ) {
bool isTransposed = _renderState = = RenderTable : : PANORAMA | | _renderState = = RenderTable : : TILT ;
2013-07-26 17:26:30 +00:00
for ( int y = subRectangle . top ; y < subRectangle . bottom ; y + + ) {
uint32 normalizedY = y - subRectangle . top ;
2013-07-29 02:37:32 +00:00
2013-07-26 17:26:30 +00:00
for ( int x = subRectangle . left ; x < subRectangle . right ; x + + ) {
uint32 normalizedX = x - subRectangle . left ;
2013-07-29 02:37:32 +00:00
uint32 index = ( y + destRectangle . top ) * _numColumns + ( x + destRectangle . left ) ;
// RenderTable only stores offsets from the original coordinates
uint32 sourceYIndex = y + _internalBuffer [ index ] . y ;
uint32 sourceXIndex = x + _internalBuffer [ index ] . x ;
// Clamp the yIndex to the size of the image
sourceYIndex = CLIP < uint32 > ( sourceYIndex , 0 , imageHeight - 1 ) ;
// Clamp the xIndex to the size of the image
sourceXIndex = CLIP < uint32 > ( sourceXIndex , 0 , imageWidth - 1 ) ;
// TODO: Figure out a way to not have branching every loop. The only way that comes to mind is to have a whole separate set of for loops for isTransposed, but that's ugly. The compiler might do this anyway in the end
if ( isTransposed ) {
destBuffer [ normalizedY * subRectangle . width ( ) + normalizedX ] = sourceBuffer [ sourceXIndex * imageHeight + sourceYIndex ] ;
} else {
destBuffer [ normalizedY * subRectangle . width ( ) + normalizedX ] = sourceBuffer [ sourceYIndex * imageWidth + sourceXIndex ] ;
}
2013-07-26 17:26:30 +00:00
}
}
}
2013-07-29 20:08:03 +00:00
void RenderTable : : generateRenderTable ( ) {
switch ( _renderState ) {
case ZVision : : RenderTable : : PANORAMA :
generatePanoramaLookupTable ( ) ;
break ;
case ZVision : : RenderTable : : TILT :
generateTiltLookupTable ( ) ;
break ;
case ZVision : : RenderTable : : FLAT :
// Intentionally left empty
break ;
}
}
2013-07-24 16:13:57 +00:00
void RenderTable : : generatePanoramaLookupTable ( ) {
memset ( _internalBuffer , 0 , _numRows * _numColumns * sizeof ( uint16 ) ) ;
float halfWidth = ( float ) _numColumns / 2.0f ;
float halfHeight = ( float ) _numRows / 2.0f ;
2013-07-29 02:38:53 +00:00
float fovRadians = ( _panoramaOptions . fieldOfView * M_PI / 180.0f ) ;
2013-07-24 16:13:57 +00:00
float halfHeightOverTan = halfHeight / tan ( fovRadians ) ;
float tanOverHalfHeight = tan ( fovRadians ) / halfHeight ;
2013-07-26 17:26:30 +00:00
// TODO: Change the algorithm to write a whole row at a time instead of a whole column at a time. AKA: for(y) { for(x) {}} instead of for(x) { for(y) {}}
for ( uint32 x = 0 ; x < _numColumns ; x + + ) {
2013-07-24 16:13:57 +00:00
// Add an offset of 0.01 to overcome zero tan/atan issue (vertical line on half of screen)
2013-07-26 17:26:30 +00:00
float temp = atan ( tanOverHalfHeight * ( ( float ) x - halfWidth + 0.01f ) ) ;
2013-07-24 16:13:57 +00:00
2013-07-29 02:37:32 +00:00
int32 newX = floor ( ( halfHeightOverTan * _panoramaOptions . linearScale * temp ) + halfWidth ) ;
2013-07-26 17:26:30 +00:00
float cosX = cos ( temp ) ;
2013-07-24 16:13:57 +00:00
2013-07-26 17:26:30 +00:00
for ( uint32 y = 0 ; y < _numRows ; y + + ) {
2013-07-24 16:13:57 +00:00
int32 newY = floor ( halfHeight + ( y - halfHeight ) * cosX ) ;
2013-07-26 17:26:30 +00:00
uint32 index = y * _numColumns + x ;
2013-07-29 02:37:32 +00:00
// Only store the x,y offsets instead of the absolute positions
_internalBuffer [ index ] . x = newX - x ; //pixel index
_internalBuffer [ index ] . y = newY - y ; //pixel index
2013-07-24 16:13:57 +00:00
}
}
}
void RenderTable : : generateTiltLookupTable ( ) {
}
} // End of namespace ZVision