Jump to content
  • Advertisement
Sign in to follow this  
cozzie

sorting std::vector instead of array

This topic is 1829 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi,

I've implemented the usage of std::vector's instead of dynamically allocated arrays.

Now my sorting function won't run anymore.

 

Can someone help me in the right direction?

 

The code of the sort action:

				sort(mEffect[fx].meshesPerMatBlended[mat].instance[m].blendedMeshOrderTemp, 
					mEffect[fx].meshesPerMatBlended[mat].instance[m].blendedMeshOrderTemp.begin() + mEffect[fx].meshesPerMatBlended[mat].instance[m].nrInstances, [&](int a, int b) 
					{ return mEffect[fx].meshesPerMatBlended[mat].instance[m].blendedMeshDistToCam[a] > mEffect[fx].meshesPerMatBlended[mat].instance[m].blendedMeshDistToCam[b]; });

The new variable declaration:

	std::vector<int>	blendedMeshIndexTemp;	// for sorting blended meshes on dist from camera
	std::vector<int>	blendedMeshOrderTemp;	// for sorting blended meshes on dist from camera
	std::vector<float>	blendedMeshDistToCam;	// for sorting blended meshes on dist from camera

And the old variable declaration:

int		*blendedMeshIndexTemp;	// for sorting blended meshes on dist from camera
int		*blendedMeshOrderTemp;	// for sorting blended meshes on dist from camera
float	*blendedMeshDistToCam;	// for sorting blended meshes on dist from camera

Edited by cozzie

Share this post


Link to post
Share on other sites
Advertisement

The first and second parameters are the begin and end iterator of the range to sort.

sort(mEffect[fx].meshesPerMatBlended[mat].instance[m].blendedMeshOrderTemp.begin(), mEffect[fx].meshesPerMatBlended[mat].instance[m].blendedMeshOrderTemp.end(), ...

Share this post


Link to post
Share on other sites

Thanks, that was quick :)

Got it, maybe actually posted to quick...

 

My assumption is that when passing the name of the array I pass a pointer to the first element of the array (which 'sort' expects), thats why I have to use .begin() now, to also point to the 1st element. Is that correct?

Share this post


Link to post
Share on other sites

BTW, if you're using C++11, it's a good idea to use std::begin and std::end:

http://en.cppreference.com/w/cpp/iterator/begin

http://en.cppreference.com/w/cpp/iterator/end

 

These will work both with the containers and C-style (fixed) arrays -- useful for situations just like this, when you're switching between the two.

// Although some tweaking is needed for the C-style dynamic arrays: http://stackoverflow.com/questions/15904896/range-based-for-loop-on-a-dynamic-array

Share this post


Link to post
Share on other sites
@matt-d: thanks, good idea.

@iMalc: thanks, I'll look into it, didn't know there are so much 'rules' and 'laws'. Without programming education/ courses I just tend to do things and fix when necessary (or someone mentions a rule/law :)). For example the rule of three I've found out when I wanted to reinitialize/ assign an object and reuse it from scratch

Share this post


Link to post
Share on other sites

@iMalc; I've looked into it, and I read the law of demeter as follows: try to prevent that objects of class A are changed in methods of class C, through class B. Because then class C has to now a lot about objects of class 'A'. By following the law you the code is better re-usable, portable etc.

 

What I've done next is see how the code sample above applies to this.

This is my current design:

 

- I have a class Scenegraph

- there's one object of Scenegraph included in my main D3D class

- member functions of the D3D class are the only functions that call Scenegraph member(s) / functions

 

The code sample above is part of a member function of the Scenegraph class:

/**************************************************************************************/
/***							SORT BLENDED MESHES									***/
/*** ==> usage: during updating the 3d scene graph									***/
/*** ==> updates meshInstBlended inst array sorted back to front on cam distance	***/
/**************************************************************************************/

bool CSceneGraph::SortBlendedMeshes()
{
	for(int fx=0;fx<mNrEffects;++fx)
	{
		for(int mat=0;mat<mEffect[fx].nrMaterialsBlended;++mat)
		{
			for(int m=0;m<mEffect[fx].meshesPerMatBlended[mat].nrMeshes;++m)
			{
				for(int mi=0;mi<mEffect[fx].meshesPerMatBlended[mat].instance[m].nrInstances;++mi) 
				{
					mEffect[fx].meshesPerMatBlended[mat].instance[m].blendedMeshIndexTemp[mi] = mEffect[fx].meshesPerMatBlended[mat].instance[m].instances[mi];
					mEffect[fx].meshesPerMatBlended[mat].instance[m].blendedMeshDistToCam[mi] = mMeshInst[mEffect[fx].meshesPerMatBlended[mat].instance[m].instances[mi]].distToCam;
				}

				sort(mEffect[fx].meshesPerMatBlended[mat].instance[m].blendedMeshOrderTemp.begin(), 
					mEffect[fx].meshesPerMatBlended[mat].instance[m].blendedMeshOrderTemp.begin() + mEffect[fx].meshesPerMatBlended[mat].instance[m].nrInstances, [&](int a, int b) 
					{ return mEffect[fx].meshesPerMatBlended[mat].instance[m].blendedMeshDistToCam[a] > mEffect[fx].meshesPerMatBlended[mat].instance[m].blendedMeshDistToCam[b]; });

				for(int mi=0;mi<mEffect[fx].meshesPerMatBlended[mat].instance[m].nrInstances;++mi) 
					mEffect[fx].meshesPerMatBlended[mat].instance[m].instances[mi] = 
						mEffect[fx].meshesPerMatBlended[mat].instance[m].blendedMeshIndexTemp[mEffect[fx].meshesPerMatBlended[mat].instance[m].blendedMeshOrderTemp[mi]];
			}
		}
	}
	return true;
}

This member function only uses/updates/manipulates member variables of the Scenegraph object itself.

So I'm not sure how the law of demeter is being violated here.

 

The three vectors are part a struct called 'Q_MESHINSTMESH', of which there exists a vector in the struct Q_EFFECT, which exists as vector in the Scenegraph class (one Q_MESHINSTMESH per mesh, for each effect).

typedef struct Q_MESHINSTMESH
{
	int					nrInstances;
	std::vector<int>	instances;
	
	std::vector<int>	blendedMeshIndexTemp;	// for sorting blended meshes on dist from camera
	std::vector<int>	blendedMeshOrderTemp;	// for sorting blended meshes on dist from camera
	std::vector<float>	blendedMeshDistToCam;	// for sorting blended meshes on dist from camera
} Q_MESHINSTMESH;

?

?

typedef struct Q_EFFECT
{
	int			nrMeshInst;
	int			nrMaterials;

	int						nrMaterialsOpaque;
	int						nrMaterialsBlended;
	std::vector<int>		materialsOpaque;
	std::vector<int>		materialsBlended;
	std::vector<Q_MATMESH>	meshesPerMatOpaque;
	std::vector<Q_MATMESH>	meshesPerMatBlended;
	
	int					nrMeshes;
	int					nrMeshesOpaque;
	int					nrMeshesBlended;
	std::vector<int>	mesh;
	std::vector<int>	meshOpaque;
	std::vector<int>	meshBlended;

	std::vector<int>	meshInst;
} Q_EFFECT;

And the whole scenegraph class:

class CSceneGraph
{
public:
	std::vector<int>		mDynamicMeshInstIndex;

	// LIGHTING, total
	std::vector<int>		mDirLights;
	std::vector<int>		mPointLights;

	// LIGHTING, active
	std::vector<int>		mVisibleDirLights;		
	std::vector<int>		mVisiblePointLights;		

	std::vector<Q_MESH>		mMesh;
	std::vector<Q_MESHINST>	mMeshInst;
	std::vector<Q_MATERIAL>	mMaterials;
	std::vector<Q_LIGHT>	mLights;
	std::vector<Q_EFFECT>	mEffect;

	Q_MESHINST				mMeshInstWeapon;

	int GetNrMeshes()					const;
	int	GetNrMeshInst()					const;
	int	GetNrMeshInstDynamic()			const;
	int	GetNrMaterials()				const;
	int	GetNrEffects()					const;
	// LIGHTING, total
	int GetNrLights()					const;
	int	GetNrDirLights()				const;
	int	GetNrPointLights()				const;
	// LIGHTING, maximum rendering
	int	GetMaxDirLights()				const;
	int	GetMaxPointLights()				const;
	// LIGHTING, active
	int	GetNrVisibleDirLights()			const;
	int	GetNrVisiblePointLights()		const;

	bool Create(const Crealysm_d3drenderer::CD3dscene &pD3dscene, const int pLightingEffectId);
	void UpdateDistToCamMIBlended(const Crealysm_d3drenderer::CD3dscene &pD3dscene, const Crealysm_d3drenderer::CD3dcam &pCam);
	void UpdateDistToCamLights(const Crealysm_d3drenderer::CD3dscene &pD3dscene, const Crealysm_d3drenderer::CD3dcam &pCam);
	bool SortBlendedMeshes();

	bool CullLights(const Crealysm_d3drenderer::CD3dscene &pD3dscene);
	bool UpdateLightAffectMeshData(const Crealysm_d3drenderer::CD3dscene &pD3dscene);		
	bool UpdateLightAffectWeaponMesh(const Crealysm_d3drenderer::CD3dscene &pD3dscene, const Crealysm_d3drenderer::CD3dcam &pCam);		

	CSceneGraph();
	~CSceneGraph(); 

private:
	int			mNrMeshes;
	int			mNrMeshInst;
	int			mNrMeshInstDynamic;
	int			mNrMaterials;
	int			mNrEffects;

	// LIGHTING, total
	int			mNrLights;
	int			mNrDirLights;
	int			mNrPointLights;

	// LIGHTING, maximum rendering
	int			mMaxDirLights;
	int			mMaxPointLights;

	// LIGHTING, active
	int			mNrVisibleDirLights;
	int			mNrVisiblePointLights;

	bool mMeshDataCreated;
	bool mMeshInstDataCreated;		
	bool mLightDataCreated;			
	bool mEffectDataCreated;
	bool mEffectMeshDataCreated;
	bool mEffectMatDataCreated;

	bool CreateMeshData(const Crealysm_d3drenderer::CD3dscene &pD3dscene);
	bool CreateMeshInstData(const Crealysm_d3drenderer::CD3dscene &pD3dscene);
	bool CreateMaterialData(const Crealysm_d3drenderer::CD3dscene &pD3dscene);
	bool CreateLightData(const Crealysm_d3drenderer::CD3dscene &pD3dscene);

	void CreateEffectMeshData(const Crealysm_d3drenderer::CD3dscene &pD3dscene);
	bool CreateEffectMaterialData();
	bool CreateEffectMatMeshIndex();
};

The D3D class object has a UpdateScenegraph function, where this SortBlendedMeshes function is being called. Before the scene is rendered.

 

The design 'above this', is as followed:

- main application has:

** 1 D3D object, including 1 SceneGraph

** 1 D3DScene object

** The scenegraph uses information on meshes, lights etc., from the D3DScene (passed as const reference to some member functions of the scenegraph).

 

Can you explain in which part you're seeing potential risks by violating the Law of Demeter?

Edited by cozzie

Share this post


Link to post
Share on other sites
I'll refrain from commenting on the fundental design issues, and just point out that this kind of drilling down is atrocious to read. It will eventually lead to bugs and silly code, if it hasn't already.
mEffect[fx].meshesPerMatBlended[mat].instance[m].blendedMeshIndexTemp[mEffect[fx].meshesPerMatBlended[mat].instance[m].blendedMeshOrderTemp[mi]]
Using iterators rather than indices would prevent this. But if you use indices, at least use local references to clean it up:
auto& inst = mEffect[fx].meshesPerMatBlended[mat].instance[m];
inst.blendedMeshIndexTemp[inst.blendedMeshOrderTemp[mi]];

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!