Sign in to follow this  
Scet

[solved](software rendering) Y axis flipped

Recommended Posts

Hi, I have a very simple problem with my software rasterizer that I think is realted to faulty matrix math. Basically the Y axis is flipped, negative is "up" and positive is "down". This is with the model view matrix set as identity. Here is my matrix code:
#include <math.h>
#include "sp_matrix.h"
#include "sp_state.h"
#include "sp_viewport.h"

/***************************** local constants *****************************/

#define SP_CURRENT_MATRIX	0x0023

/***************************** local variables *****************************/

static SPfloat ModelViewStack[1][16];

static SPfloat ProjectionStack[1][16];

/*static*/ SPfloat* StackPointer[2] = { ModelViewStack[0], ProjectionStack[0] };

static SPboolean WorldInvalid = SP_TRUE;

static SPfloat WorldMatrix[16];

/***************************** local functions *****************************/

static SPvoid spMatrixMultiply( SPfloat* left, SPfloat* right, SPfloat* output )
{
	SPsize r, c, i;
	static SPfloat result[16];
	for( r = 0; r < 4; r++ )
	{
		for( c = 0; c < 16; c += 4 )
		{
			for( i = 0; i < 4; i++ )
			{
				result[r+c] += ( left[r+(i<<2)] * right[i+c] );
			}
		}
	}
	for( i = 0; i < 16; i++ )
	{
		output[i] = result[i]; 
		result[i] = 0;
	}
	return;
}

static SPvoid spMultMatrixVertex( SPfloat* matrix, SPvertex* in, SPvertex* out )
{
    SPint i;
	SPfloat* result;
    for( i = 0, result = &out->X; i < 4; i++, result++ ) 
	{
		*result = ( ( in->X * matrix[i] ) + ( in->Y * matrix[4+i] ) + ( in->Z * matrix[8+i] ) + ( in->W * matrix[12+i] ) );
    }
	return;
}

/***************************** global functions *****************************/

SPvoid spLoadIdentity( SPvoid )
{
	SPfloat identity[16] = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 };
	spLoadMatrix( identity );
	return;
}

SPvoid spLoadMatrix( SPfloat* matrix )
{
	SPsize i;
	SPfloat* current;
	current = spGetStateV( SP_CURRENT_MATRIX );
	for( i = 0; i < 16; i++ )
	{
		current[i] = matrix[i];
	}
	WorldInvalid = SP_TRUE;
	return;
}

SPvoid spMatrixMode( SPenum mode )
{
	spSetStateI( SP_MATRIX_MODE, mode );
	spSetStateV( SP_CURRENT_MATRIX, StackPointer[mode&1] );
	return;
}

SPvoid spMultMatrix( SPfloat* right )
{
	SPfloat* left;
	left = spGetStateV( SP_CURRENT_MATRIX );
	spMatrixMultiply( left, right, left );
	WorldInvalid = SP_TRUE;
	return;
}

SPvoid spPerspective( SPfloat fovy, SPfloat aspect, SPfloat znear, SPfloat zfar )
{
	SPfloat cot, radians;
	static SPfloat perspective[16] = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 };
	radians = ( ( fovy * 0.5f ) * ( 3.14159f / 180.0f ) );
	cot = (SPfloat)( cos( radians ) / sin( radians ) );
	perspective[0]  = ( cot / aspect );
	perspective[5]  = cot;
	perspective[10] = ( -( zfar + znear ) / ( zfar - znear ) ); 
	perspective[11] = -1.0f;
	perspective[14] = ( ( -2.0f * znear * zfar ) / ( zfar - znear ) );
	perspective[15] = 0.0f;
	spMultMatrix( perspective );
	Viewport.ZFar = zfar;
	Viewport.ZNear = znear;
	return;
}


SPvoid spProject( SPvertex* input, SPvertex* output, SPsize count )
{
	SPsize i;
	SPvertex temp;
	for( i = 0; i < count; i++, input++, output++ )
	{
		input->W = 1.0f;
		spMultMatrixVertex( StackPointer[0], input, &temp );
		spMultMatrixVertex( StackPointer[1], &temp, output );
		if( output->W == 0.0f )
		{
			continue;
		}
		output->X /= output->W;
		output->X = ( ( output->X * 0.5f ) + 0.5f );
		output->X *= Viewport.Width;
		output->Y /= output->W;
		output->Y = ( ( output->Y * 0.5f ) + 0.5f );
		output->Y *= Viewport.Height;
		output->Z = output->W;
	}
	return;
}

SPvoid spTranslate( SPfloat x, SPfloat y, SPfloat z )
{
	static SPfloat translation[16] = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 };
	translation[12] = x;
	translation[13] = y;
	translation[14] = z;
	spMultMatrix( translation );	
	return;
}


After projection the X and Z values are correct, it's just the Y that's wrong. I tried changing "perspective[11] = -1.0f" to "perspective[11] = 1.0f" in spPerspective. That fixed the Y axis, but flipped the X axis. What's wrong? Thanks. Edit: Changing "output->Y = ( ( output->Y * 0.5f ) + 0.5f );" to "output->Y = ( ( output->Y * -0.5f ) + 0.5f );" seems to fix the problem. [Edited by - Scet on September 13, 2009 5:31:07 PM]

Share this post


Link to post
Share on other sites
Silly question, perhaps, but are you sure the framebuffer is addressed linearly from top-left going down, or is it bottom-left going up? Depending on what you use to display your results, this may be the problem -- On Windows, for instance, DIB sections are by default upside down, and to correct for this you pass in a negative height.

Share this post


Link to post
Share on other sites
That's not it. If I check the projected Y values, they are wrong, and that's before anything is drawn. There's something wrong with either spMultMatrixVertex, spPerspective or spProject.

Share this post


Link to post
Share on other sites
thread title says its solved, but you didn't tell us how you fixed it. That's generally considered pretty rude. Someone took the time to (try) help you, so we're interested in knowing how you fixed it, so that we can help either ourselves or others when they have a similar problem.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this