• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
cozzie

return a float array in a function

18 posts in this topic

Hi,

 

I'm trying to make a const function returning a float[3] array with the position of my camera.

But I can't manage to do this, without passing the array as a function parameter.

 

To be exact, this is what I do now:

void CD3dcam::GetPositionF(float pPos[]) const
{
	pPos[0] = mPosition.x;
	pPos[1] = mPosition.y;
	pPos[2] = mPosition.z;
}

But this is ofcourse annoying if I want to pass GetPositionF to a function as a parameter, where a float array is expected.

So I tried something like

 

float* CD3dcam::GetPositionF() const

{

   float pos[3];

   pos[0] = mPosition.x;

   pos[1] = mPosition.y;

   pos[2] = mPosition.z;

 

   return pos;

}

 

This compiles, but gives a warning that I'm returning the address of a local variable in memory, instead of a pointer to the actual values.

Any ideas anyone?

Edited by cozzie
0

Share this post


Link to post
Share on other sites

Update;

This seems to work, not sure though if it's correct:

float* CD3dcam::GetPositionF() const
{
	float *pos = new float[3];

	pos[0] = mPosition.x;
	pos[1] = mPosition.y;
	pos[2] = mPosition.z;

	return pos;
}
0

Share this post


Link to post
Share on other sites
You either get the user to pass you the array (what you had), return the address of a global object or return an object that wraps the array. The last one is probably what I would go for. You seem to be using float[3] to represent points. Make a class Point instead, and return that.

EDIT: Yes, you could also return a dynamically allocated buffer, which is what you did in your second post. But then the calling code needs to remember to delete[] it, and they don't, and this is how you create memory leaks. Edited by Álvaro
2

Share this post


Link to post
Share on other sites

You can return a struct (by value, i.e. not via a pointer to the struct) which has a float[3] as its only member as well if you really want to return the array. This may copy but the compiler should be able to optimise the copy out.

 

Don't return the address of a global variable, it doesn't scale well (meaning: doesn't scale at all) if you need to call it recursively or on multiple threads.

 

EDIT: I see Alvaro suggested making a Point class, missed that, it's the same as what I suggested using a class instead of a struct.

Edited by Paradigm Shifter
0

Share this post


Link to post
Share on other sites

Thanks.

I'm not sure though if making a struct will bring me what I'm looking for.

The function I have to pass the float array too, expects a pointer array:

 

HRESULT SetFloatArray(
  [in]  D3DXHANDLE hParameter,
  [in]  const FLOAT *pf,
  [in]  UINT Count
);
 

That would mean that I have to create a local object of the struct in every frame, filling it with GetPositionF and passing the member of the object to the function above.

Sounds a bit 'waste', although I don't know how to do it easier.

0

Share this post


Link to post
Share on other sites

I 'solved' it now by making a public member float array: mPosF[3] and update it when the camera moves.

And in the SetFloatArray I just call that public member of my camera class.

This works for now, still not sure if there's a better way though.

 

Paradigm shifter: that's sort of what I did now, I think :)

Edited by cozzie
0

Share this post


Link to post
Share on other sites

You could make a conversion operator:

struct Vec3
{
    float x,y,z;
 
    operator float* ()
    {
        return &x;
    }
 
    operator const float* () const
    {
        return &x;
    }

};
Edited by belfegor
2

Share this post


Link to post
Share on other sites

I 'solved' it now by making a public member float array: mPosF[3] and update it when the camera moves.

And in the SetFloatArray I just call that public member of my camera class.

This works for now, still not sure if there's a better way though.

 

Paradigm shifter: that's sort of what I did now, I think smile.png

 

This is NOT the way to go. If you have public access to the position, you will be able to change it's data without letting your CD3dcam class know about it, which is bad because you'll not be able to cache the view matrix (to recalculate it only when needed later, when you're optimizing).

 

The best approach is to use a struct much like belfegor posted and have the following methods on your CD3dcam:

const Vec3& getPosition() const
{
   return mPos;
}

void setPosition( const Vec3& pos )
{
   mPos = pos;
}
0

Share this post


Link to post
Share on other sites

 

Update;

This seems to work, not sure though if it's correct:

float* CD3dcam::GetPositionF() const
{
	float *pos = new float[3];

	pos[0] = mPosition.x;
	pos[1] = mPosition.y;
	pos[2] = mPosition.z;

	return pos;
}

Indeed that will work. It'll make it very easy to have memory leaks though, and will possibly bring problems if this method uses a different memory allocator implementation than what is used by the caller to free it up later.

0

Share this post


Link to post
Share on other sites
Note that C++ has a standard container to encapsulate fixed size arrays: std::array. Here you could use a std::array<float, 3>. Of course, std::array is a relatively recent addition to C++, so not all compilers will have it. If yours doesn't you can use boost::array instead. While there is no implicit conversion from a std::array<float, 3> to float *, you can use .data() on a non-const rvalue. Ex:
std::array<float, 3> foo();
void bar(float *);

int main(int, char **) {
  bar(foo().data());
}
1

Share this post


Link to post
Share on other sites

@rip-off

Thank you for pointing out possible problems with this.

One way i could see to avoid that is to make:

struct Vec3
{
private:

    operator bool ()
    {
        return false;
    }

public:
...

and have compile time error if such thing happen by accident.

Do you see any problem with this?

0

Share this post


Link to post
Share on other sites

I still think a named function, such as toArray() / asArray(), would be better.

 

You'd have to add "operator bool() const" too, to avoid the same problem with const objects. You could still run into this problem inside private or friend functions, though this is unlikely to be a scenario for a (formerly) simple vector class. You could however omit the implementation, thus getting a linker error if it is erroneously used even by a privileged function. Finally, you have to explain/justify these bizarre function stubs to your team, and write a suitably menacing comment so no-one accidentally deletes the apparently unused code...

2

Share this post


Link to post
Share on other sites

Thanks all.

I think I've a found a good balance without taking risk and now did it like this:

// private members

D3DXVECTOR3 mPosition;
float *mPosF;

// public member function prototype
float* GetPositionF() const;

// the member function implementation
float* CD3dcam::GetPositionF() const
{
	return mPosF;
}

// in constructor
mPosF = new float[3];

// in destructor
delete[] mPosF;

// the call where I use the array
if(FAILED(pD3dscene->mShaders[0].mEffect->SetFloatArray(pD3dscene->mShaders[0].mHCameraPos, (float*)pCam->GetPositionF(), 3))) return false;	// NOT SHARED YET!!!! MIND YOU!!

0

Share this post


Link to post
Share on other sites

D3DXVECTOR3 already have conversion/cast operator so you could just pass that:

const D3DXVECTOR3& CD3dcam::GetPosition() const
{
    return mPosition;
}
...
if(FAILED(pD3dscene->mShaders[0].mEffect->SetFloatArray(pD3dscene->mShaders[0].mHCameraPos, pCam->GetPosition(), 3)) return false;
Edited by belfegor
0

Share this post


Link to post
Share on other sites


Thanks all.

I think I've a found a good balance without taking risk and now did it like this:
[...]

 

Your use of new and delete[] seems suspicious. Why do you want to allocate a separate piece of memory to contain the same stuff you already have in the D3DXVECTOR3 representation? Taking the address of the `x' member and treating it as an array of 3 floats should work just fine. The C++ standard doesn't guarantee that it will work, of course. If that bothers you, I am sure there are some pills you can take. :)

0

Share this post


Link to post
Share on other sites

[background=#fafbfc]You could make a conversion operator...[/size][/background]

... but don't. There is a reason why the standard committed opted for std::string::c_str() rather than making an implicit conversion to C string.
Note that if you have a C++11 compiler, you can use [tt]explicit[/tt] conversion operators which avoid many of the problems with implicit conversions.
1

Share this post


Link to post
Share on other sites

Thanks Alvaro. I actually didn't check if D3DXVECTOR3 had an operator to return a float array for XYZ.

Got it working now, with no unnecessary float array and keeping track of XYZ pos 2 times each frame

0

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  
Followers 0