Sign in to follow this  
Barrow Boy

Problem with an array return-type of a function

Recommended Posts

I have a function that takes two arrays of structs, 'colors' and 'verts' (for vertices), then updates the array of verts according to the colors array. It then returns the new verts array, and I think this is where it's having problems. Here is the function:
CUSTOMVERTEX[3] update_verts( CUSTOMVERTEX verts[3], COLOR colors[3] )
{
	verts[0].COLOR = D3DCOLOR_XRGB( colors[0].R, colors[0].G, colors[0].B );
	verts[1].COLOR = D3DCOLOR_XRGB( colors[1].R, colors[1].G, colors[1].B );
	verts[2].COLOR = D3DCOLOR_XRGB( colors[2].R, colors[2].G, colors[2].B );

	return verts;
}
CUSTOMVERTEX has been defined thus:
struct CUSTOMVERTEX { FLOAT X, Y, Z, RHW; DWORD COLOR; };
and COLOR thus:
struct COLOR
{
	DWORD R, G, B;
	bool isFadingRed, isFadingGreen, isFadingBlue;
};
Here are the declarations of the two arrays:
COLOR t_colors[] =
	{
		{ 0, 0, 255, true, false, false },
		{ 0, 255, 0, false, true, false },
		{ 255, 0, 0, false, false, true },
	};
CUSTOMVERTEX t_vert[] =
	{
		{ 320.0f, 50.0f, 0.5f, 1.0f, D3DCOLOR_XRGB( 0, 0, 255 ), },
		{ 520.0f, 400.0f, 0.5f, 1.0f, D3DCOLOR_XRGB( 0, 255, 0 ), },
		{ 120.0f, 400.0f, 0.5f, 1.0f, D3DCOLOR_XRGB( 255, 0, 0 ), },
	};
Is there something wrong with my return type? The errors are:
c:\documents and settings\sam\my documents\visual studio 2008\projects\triangle2\triangle2\triangle2.cpp(89) : error C2143: syntax error : missing ';' before '['
c:\documents and settings\sam\my documents\visual studio 2008\projects\triangle2\triangle2\triangle2.cpp(89) : error C3409: empty attribute block is not allowed
c:\documents and settings\sam\my documents\visual studio 2008\projects\triangle2\triangle2\triangle2.cpp(89) : error C2143: syntax error : missing ']' before 'constant'
c:\documents and settings\sam\my documents\visual studio 2008\projects\triangle2\triangle2\triangle2.cpp(89) : error C2059: syntax error : 'constant'
c:\documents and settings\sam\my documents\visual studio 2008\projects\triangle2\triangle2\triangle2.cpp(90) : error C2143: syntax error : missing ';' before '{'
c:\documents and settings\sam\my documents\visual studio 2008\projects\triangle2\triangle2\triangle2.cpp(90) : error C2447: '{' : missing function header (old-style formal list?)
c:\documents and settings\sam\my documents\visual studio 2008\projects\triangle2\triangle2\triangle2.cpp(152) : error C3861: 'update_verts': identifier not found

Share this post


Link to post
Share on other sites
You cannot return an array: arrays decay to pointers when passed to or returned from functions. You could modify the return type to a pointer, which is safe in this case because you are not returning a local pointer. Alternatively, you could put the array in a structure so that passing and returning works as expected:

struct Vertices
{
CUSTOMVERTEX data[3];
};

Vertices update_verts( Vertices verts, COLOR colors[3] )
{
verts.data[0].COLOR = D3DCOLOR_XRGB( colors[0].R, colors[0].G, colors[0].B );
verts.data[1].COLOR = D3DCOLOR_XRGB( colors[1].R, colors[1].G, colors[1].B );
verts.data[2].COLOR = D3DCOLOR_XRGB( colors[2].R, colors[2].G, colors[2].B );

return verts;
}


Share this post


Link to post
Share on other sites
When you pass an array in that way, the changes made locally by the function will affect the caller's version of the array - the array is "decayed" to a pointer, so that the function works directly with the caller's array instead of a pointer.

Consequently, you could just return void and have the caller just expect the changes in the array. (But note that if you need to keep the original data around, you will have to make a copy yourself, explicitly.)

This is just something that C and C++ do with arrays. It's a hack in the language design, really. If you want your arrays to actually behave like other data types in the language, you may want to wrap them in a struct yourself (as shown), or save yourself that effort by using boost::array.

Share this post


Link to post
Share on other sites
Ok, I tried putting t_verts into a struct, and I get an error saying that it can't convert CUSTOMVERTEX[3] to FLOAT. Here is my struct:

CUSTOMVERTEX t_vert[] =
{
{ 320.0f, 50.0f, 0.5f, 1.0f, D3DCOLOR_XRGB( 0, 0, 255 ), },
{ 520.0f, 400.0f, 0.5f, 1.0f, D3DCOLOR_XRGB( 0, 255, 0 ), },
{ 120.0f, 400.0f, 0.5f, 1.0f, D3DCOLOR_XRGB( 255, 0, 0 ), },
};

verticies verts = { t_vert };

Share this post


Link to post
Share on other sites
I would write it like this

void update_verts( CUSTOMVERTEX * const verts, COLOR * const colors, const size_t elements )
{
for( size_t i = 0; i < elements; i++ )
verts[i].COLOR = D3DCOLOR_XRGB( colors[i].R, colors[i].G, colors[i].B );
}





That should work fine, and fits in more with the name because it is updating a prexisting array, not creating a new one.

Share this post


Link to post
Share on other sites
Treb, using your code, the program will run, but now I have a bigger problem. The program is meant to change the colors of the vertices of a triangle, but now it simply displays the triangle and the colors remain constant. Here's the code:

// include the basic windows header files and the Direct3D header file
#include <windows.h>
#include <windowsx.h>
#include <d3d9.h>

// define the screen resolution and keyboard macros
#define SCREEN_WIDTH 1024
#define SCREEN_HEIGHT 768
#define KEY_DOWN( vk_code ) ( ( GetAsyncKeyState( vk_code ) & 0x8000 ) ? 1 : 0 )
#define KEY_UP( vk_code ) ( ( GetAsyncKeyState( vk_code ) & 0x8000 ) ? 0 : 1 )

// include the Direct3D Library file
#pragma comment ( lib, "d3d9.lib" )

// global declarations
LPDIRECT3D9 d3d; // the pointer to our Direct3D interface
LPDIRECT3DDEVICE9 d3ddev; // the pointer to the device class
LPDIRECT3DVERTEXBUFFER9 t_buffer = NULL; // the pointer to the vertex buffer

// function prototypes
void initD3D( HWND hWnd ); // sets up and initializes Direct3D
void render_frame( void ); // renders a single frame
void cleanD3D( void ); // closes Direct3D and releases memory
void init_graphics( void ); // 3D declarations

struct CUSTOMVERTEX { FLOAT X, Y, Z, RHW; DWORD COLOR; };
#define CUSTOMFVF ( D3DFVF_XYZRHW | D3DFVF_DIFFUSE )

size_t elements = 3;

struct COLOR
{
DWORD R, G, B;
bool isFadingRed, isFadingGreen, isFadingBlue;
};

struct verticies
{
CUSTOMVERTEX data[3];
};

void switch_color( COLOR colors[3] )
{
// alter colors[0]
if( colors[0].isFadingRed )
{
colors[0].isFadingRed = !colors[0].isFadingRed;
colors[0].isFadingGreen = !colors[0].isFadingGreen;
}
else if( colors[0].isFadingGreen )
{
colors[0].isFadingGreen = !colors[0].isFadingGreen;
colors[0].isFadingBlue = !colors[0].isFadingBlue;
}
else
{
colors[0].isFadingBlue = !colors[0].isFadingBlue;
colors[0].isFadingRed = !colors[0].isFadingRed;
}

// alter colors[1]
if( colors[1].isFadingRed )
{
colors[1].isFadingRed = !colors[1].isFadingRed;
colors[1].isFadingGreen = !colors[1].isFadingGreen;
}
else if( colors[1].isFadingGreen )
{
colors[1].isFadingGreen = !colors[1].isFadingGreen;
colors[1].isFadingBlue = !colors[1].isFadingBlue;
}
else
{
colors[1].isFadingBlue = !colors[1].isFadingBlue;
colors[1].isFadingRed = !colors[1].isFadingRed;
}

// alter colors[2]
if( colors[2].isFadingRed )
{
colors[2].isFadingRed = !colors[2].isFadingRed;
colors[2].isFadingGreen = !colors[2].isFadingGreen;
}
else if( colors[2].isFadingGreen )
{
colors[2].isFadingGreen = !colors[2].isFadingGreen;
colors[2].isFadingBlue = !colors[2].isFadingBlue;
}
else
{
colors[2].isFadingBlue = !colors[2].isFadingBlue;
colors[2].isFadingRed = !colors[2].isFadingRed;
}
}

void update_verts( CUSTOMVERTEX * const verts, COLOR * const colors, const size_t elements )
{
for( size_t i = 0; i < elements; i++ )
verts[i].COLOR = D3DCOLOR_XRGB( colors[i].R, colors[i].G, colors[i].B );
}

void graphics_loop( CUSTOMVERTEX verts[3], COLOR colors[3], short &count )
{
// alter colors[0]
if( colors[0].isFadingRed )
{
colors[0].R++;
colors[0].B--;
}
else if( colors[0].isFadingGreen )
{
colors[0].G++;
colors[0].R--;
}
else
{
colors[0].B++;
colors[0].G--;
}

// alter colors[1]
if( colors[1].isFadingRed )
{
colors[1].R++;
colors[1].B--;
}
else if( colors[1].isFadingGreen )
{
colors[1].G++;
colors[1].R--;
}
else
{
colors[1].B++;
colors[1].G--;
}

// alter colors[2]
if( colors[2].isFadingRed )
{
colors[2].R++;
colors[2].B--;
}
else if( colors[2].isFadingGreen )
{
colors[2].G++;
colors[2].R--;
}
else
{
colors[2].B++;
colors[2].G--;
}

// update verts array
update_verts( verts, colors, elements );

if( count == 255 )
{
switch_color( colors );
count = 0;
}

VOID* pVoid; // a void pointer

// lock t_buffer and load the vertices into it
t_buffer->Lock( 0, 0, ( void** )&pVoid, 0 );
memcpy( pVoid, verts, sizeof( verts ) );
t_buffer->Unlock();

return;
}

// the WindowProc function prototype
LRESULT CALLBACK WindowProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam );


// the entry point for any Windows program
int WINAPI WinMain( HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow )
{
HWND hWnd;
WNDCLASSEX wc;

ZeroMemory( &wc, sizeof( WNDCLASSEX ) );

wc.cbSize = sizeof( WNDCLASSEX );
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = ( WNDPROC )WindowProc;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor( NULL, IDC_ARROW );
// wc.hbrBackground = ( HBRUSH )COLOR_WINDOW; // not needed any more
wc.lpszClassName = L"WindowClass";

RegisterClassEx( &wc );

hWnd = CreateWindowEx( NULL,
L"WindowClass",
L"Our Direct3D Program",
WS_EX_TOPMOST | WS_POPUP, // fullscreen values
0, 0, // the starting x and y positions should be 0
SCREEN_WIDTH, SCREEN_HEIGHT, // set the window to 640 x 480
NULL,
NULL,
hInstance,
NULL );

ShowWindow( hWnd, nCmdShow );

// set up and initialize Direct3D
initD3D( hWnd );

short count = 0;
COLOR t_colors[] =
{
{ 0, 0, 255, true, false, false },
{ 0, 255, 0, false, true, false },
{ 255, 0, 0, false, false, true },
};

CUSTOMVERTEX t_vert[] =
{
{ 320.0f, 50.0f, 0.5f, 1.0f, D3DCOLOR_XRGB( 0, 0, 255 ), },
{ 520.0f, 400.0f, 0.5f, 1.0f, D3DCOLOR_XRGB( 0, 255, 0 ), },
{ 120.0f, 400.0f, 0.5f, 1.0f, D3DCOLOR_XRGB( 255, 0, 0 ), },
};

// enter the main loop:

MSG msg;

while( TRUE )
{
DWORD starting_point = GetTickCount();

if ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
{
if ( msg.message == WM_QUIT )
break;

TranslateMessage( &msg );
DispatchMessage( &msg );
}

graphics_loop( t_vert, t_colors, count );
render_frame();

// check the 'escape' key
if( KEY_DOWN( VK_ESCAPE ) )
PostMessage( hWnd, WM_DESTROY, 0, 0 );

while ( ( GetTickCount() - starting_point ) < 25 );
}

// clean up DirectX and COM
cleanD3D();

return msg.wParam;
}


// this is the main message handler for the program
LRESULT CALLBACK WindowProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
{
switch( message )
{
case WM_DESTROY:
{
PostQuitMessage( 0 );
return 0;
} break;
}

return DefWindowProc ( hWnd, message, wParam, lParam );
}


// this function initializes and prepares Direct3D for use
void initD3D( HWND hWnd )
{
d3d = Direct3DCreate9( D3D_SDK_VERSION );

D3DPRESENT_PARAMETERS d3dpp;

ZeroMemory( &d3dpp, sizeof( d3dpp ) );
d3dpp.Windowed = FALSE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.hDeviceWindow = hWnd;
d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
d3dpp.BackBufferWidth = SCREEN_WIDTH;
d3dpp.BackBufferHeight = SCREEN_HEIGHT;

// create a device class using this information and the info from the d3dpp stuct
d3d->CreateDevice( D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp,
&d3ddev );

init_graphics();

return;
}


// this is the function used to render a single frame
void render_frame( void )
{
d3ddev->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB( 0, 0, 0 ), 1.0f, 0 );

d3ddev->BeginScene();

// select which vertex format we are using
d3ddev->SetFVF( CUSTOMFVF );

// select the vertex buffer to display
d3ddev->SetStreamSource( 0, t_buffer, 0, sizeof( CUSTOMVERTEX ) );

// copy the vertex buffer to the back buffer
d3ddev->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 1 );

d3ddev->EndScene();

d3ddev->Present( NULL, NULL, NULL, NULL );

return;
}


// this is the function that cleans up Direct3D and COM
void cleanD3D( void )
{
t_buffer->Release(); // close and release the vertex buffer
d3ddev->Release(); // close and release the 3D device
d3d->Release(); // close and release Direct3D

return;
}

void init_graphics()
{
CUSTOMVERTEX t_vert[] =
{
{ 320.0f, 50.0f, 0.5f, 1.0f, D3DCOLOR_XRGB( 0, 0, 255 ), },
{ 520.0f, 400.0f, 0.5f, 1.0f, D3DCOLOR_XRGB( 0, 255, 0 ), },
{ 120.0f, 400.0f, 0.5f, 1.0f, D3DCOLOR_XRGB( 255, 0, 0 ), },
};

// create a vertex buffer interface called t_buffer
d3ddev->CreateVertexBuffer( 3*sizeof( CUSTOMVERTEX ),
0,
CUSTOMFVF,
D3DPOOL_MANAGED,
&t_buffer,
NULL );

VOID* pVoid; // a void pointer

// lock t_buffer and load the vertices into it
t_buffer->Lock( 0, 0, ( void** )&pVoid, 0 );
memcpy( pVoid, t_vert, sizeof( t_vert ) );
t_buffer->Unlock();

return;
}

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