Jump to content
  • Advertisement
Sign in to follow this  
cozzie

Using directxmath, like this?

This topic is 1668 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 started 'migrating' from D3DX to DirectXmath. It takes some time to get the hang of it, but I'm starting to get the feeling.

Can someone give me some pointers or approval that the way I'm doing things below is the way to go? (or are there easier ways)

 

Any input is appreciated.

 

3 examples, using D3DX:

// OLD functions

void OBB::Update(const D3DXMATRIX &pWorldMat, const AABB &pAABB)
{
	D3DXVec3TransformCoord(&Center, &pAABB.Center(), &pWorldMat);

	Extents = pAABB.Extents();

	D3DXVECTOR3 mAx, mAy, mAz;
	// orientation: rotation/ scaling (NOT in worldspace)
	mAx = D3DXVECTOR3(pWorldMat._11, pWorldMat._12, pWorldMat._13);		
	mAy = D3DXVECTOR3(pWorldMat._21, pWorldMat._22, pWorldMat._23);		
	mAz = D3DXVECTOR3(pWorldMat._31, pWorldMat._32, pWorldMat._33);

	XHalfExtent = mAx * Extents.x / 2.0f;
	YHalfExtent = mAy * Extents.y / 2.0f;
	ZHalfExtent = mAz * Extents.z / 2.0f;
}

void AABBWORLD::Update(const OBB &pOBB)
{
/*	1. calculate the 8 corners based on the OBB half extents

       E              F
	   /-------------|				A = -X	-Y	-Z
	  / |          / |				B = +X	-Y	-Z
	 /  |         /  |              C = +X	+Y	-Z	
  A	/------------|B  |              D = -X	+Y	-Z
	|   |	     |   |              
	|  / - - - - | - | G			E = -X	-Y	+Z
	| / H        |  /				F = +X	-Y	+Z
	|/           | /				G = +X	+Y	+Z
  	|------------|/					H = -X	+Y	+Z
  D	              C
	*/

	D3DXVECTOR3 OBBcorners[8];
	
	OBBcorners[0] = -pOBB.XHalfExtent -pOBB.YHalfExtent -pOBB.ZHalfExtent;
	OBBcorners[1] = +pOBB.XHalfExtent -pOBB.YHalfExtent -pOBB.ZHalfExtent;
	OBBcorners[2] = +pOBB.XHalfExtent +pOBB.YHalfExtent -pOBB.ZHalfExtent;
	OBBcorners[3] = -pOBB.XHalfExtent +pOBB.YHalfExtent -pOBB.ZHalfExtent;

	OBBcorners[4] = -pOBB.XHalfExtent -pOBB.YHalfExtent +pOBB.ZHalfExtent;
	OBBcorners[5] = +pOBB.XHalfExtent -pOBB.YHalfExtent +pOBB.ZHalfExtent;
	OBBcorners[6] = +pOBB.XHalfExtent +pOBB.YHalfExtent +pOBB.ZHalfExtent;
	OBBcorners[7] = -pOBB.XHalfExtent +pOBB.YHalfExtent +pOBB.ZHalfExtent;

//	2. Find the min and max X Y Z of the corners to get AABB in worldspace

	_Min = OBBcorners[0];
	_Max = _Min;

	for(int j=1;j<8;++j)
	{
		_Min = D3DXVECTOR3((std::min)(OBBcorners[j].x, _Min.x),
						   (std::min)(OBBcorners[j].y, _Min.y),
						   (std::min)(OBBcorners[j].z, _Min.z));

		_Max = D3DXVECTOR3((std::max)(OBBcorners[j].x, _Max.x),
					  	   (std::max)(OBBcorners[j].y, _Max.y),
						   (std::max)(OBBcorners[j].z, _Max.z));
	}

//	3. Transfom Min/Max to worldspace by adding world center to the _Min and _Max
	Center = pOBB.Center;
	_Min += Center;
	_Max += Center;
}


/**************************************************************************************/
/***							COORD TO COORD DIST									***/
/*** ==> usage: when distance between 2 D3DX vectors is needed						***/
/*** ==> returns the distance as a float value (non squared)						***/
/**************************************************************************************/

float CoordToCoordDist(const D3DXVECTOR3 &pv1, const D3DXVECTOR3 &pv2)
{
	return D3DXVec3Length(&D3DXVECTOR3(pv1 - pv2));
}

And the new versions, using Directxmath:

void OBB::Update(const XMFLOAT4X4 &pWorldMat, const AABB &pAABB)
{
	XMVECTOR tempCenter = XMLoadFloat3(&pAABB.Center());
	XMMATRIX tempWorldMat = XMLoadFloat4x4(&pWorldMat);
	XMVECTOR tempNewCenter = XMVector3TransformCoord(tempCenter, tempWorldMat);

	XMStoreFloat3(&Center, tempNewCenter);
	Extents = pAABB.Extents();

	// orientation: rotation/ scaling (NOT in worldspace)
	XMVECTOR mAx = { pWorldMat._11, pWorldMat._12, pWorldMat._13 };
	XMVECTOR mAy = { pWorldMat._21, pWorldMat._22, pWorldMat._23 };
	XMVECTOR mAz = { pWorldMat._31, pWorldMat._32, pWorldMat._33 };

	XMVECTOR tempXHalf = XMVectorScale(XMVectorScale(mAx, Extents.x), 0.5f);
	XMVECTOR tempYHalf = XMVectorScale(XMVectorScale(mAy, Extents.y), 0.5f);
	XMVECTOR tempZHalf = XMVectorScale(XMVectorScale(mAy, Extents.z), 0.5f);

	XMStoreFloat3(&XHalfExtent, tempXHalf);
	XMStoreFloat3(&YHalfExtent, tempYHalf);
	XMStoreFloat3(&ZHalfExtent, tempZHalf);
}

void AABBWORLD::Update(const OBB &pOBB)
{
/*	1. calculate the 8 corners based on the OBB half extents

       E              F
	   /-------------|				A = -X	-Y	-Z
	  / |          / |				B = +X	-Y	-Z
	 /  |         /  |              C = +X	+Y	-Z	
  A	/------------|B  |              D = -X	+Y	-Z
	|   |	     |   |              
	|  / - - - - | - | G			E = -X	-Y	+Z
	| / H        |  /				F = +X	-Y	+Z
	|/           | /				G = +X	+Y	+Z
  	|------------|/					H = -X	+Y	+Z
  D	              C
	*/

	XMVECTOR tempXHalf = XMLoadFloat3(&pOBB.XHalfExtent);
	XMVECTOR tempYHalf = XMLoadFloat3(&pOBB.YHalfExtent);
	XMVECTOR tempZHalf = XMLoadFloat3(&pOBB.ZHalfExtent);

	XMVECTOR OBBcorners[8];
	OBBcorners[0] = XMVectorAdd(XMVectorAdd(	-tempXHalf,		-tempYHalf),	-tempZHalf);
	OBBcorners[1] = XMVectorAdd(XMVectorAdd(	+tempXHalf,		-tempYHalf),	-tempZHalf);
	OBBcorners[2] = XMVectorAdd(XMVectorAdd(	+tempXHalf,		+tempYHalf),	-tempZHalf);
	OBBcorners[3] = XMVectorAdd(XMVectorAdd(	-tempXHalf,		+tempYHalf),	-tempZHalf);

	OBBcorners[4] = XMVectorAdd(XMVectorAdd(	-tempXHalf,		-tempYHalf),	+tempZHalf);
	OBBcorners[5] = XMVectorAdd(XMVectorAdd(	+tempXHalf,		-tempYHalf),	+tempZHalf);
	OBBcorners[6] = XMVectorAdd(XMVectorAdd(	+tempXHalf,		+tempYHalf),	+tempZHalf);
	OBBcorners[7] = XMVectorAdd(XMVectorAdd(	-tempXHalf,		+tempYHalf),	+tempZHalf);

//	2. Find the min and max X Y Z of the corners to get AABB in worldspace

	XMStoreFloat3(&_Min, OBBcorners[0]);
	_Max = _Min;

	for(int j=1;j<8;++j)
	{
		_Min = XMFLOAT3((std::min)(XMVectorGetX(OBBcorners[j]), _Min.x),
						(std::min)(XMVectorGetY(OBBcorners[j]), _Min.y),
						(std::min)(XMVectorGetZ(OBBcorners[j]), _Min.z));

		_Max = XMFLOAT3((std::max)(XMVectorGetX(OBBcorners[j]), _Max.x),
					  	(std::max)(XMVectorGetY(OBBcorners[j]), _Max.y),
						(std::max)(XMVectorGetZ(OBBcorners[j]), _Max.z));
	}
		
//	3. Transfom Min/Max to worldspace by adding world center to the _Min and _Max
	Center = pOBB.Center;
	_Min = XMFLOAT3(_Min.x + Center.x, _Min.y + Center.y, _Min.z + Center.z);
	_Max = XMFLOAT3(_Max.x + Center.x, _Max.y + Center.y, _Max.z + Center.z);
}

float CoordToCoordDist(const XMFLOAT3 &pv1, const XMFLOAT3 &pv2)
{
	XMVECTOR temp1 = XMLoadFloat3(&pv1);
	XMVECTOR temp2 = XMLoadFloat3(&pv2);

	XMVECTOR result = XMVector3Length(XMVectorSubtract(temp1, temp2));
	return XMVectorGetX(result);
}

Share this post


Link to post
Share on other sites
Advertisement

I would like to hear people's opinions on that, too. When I started to use DIrectXMath it was really uncomfortable for me. I thought that I was missing something, since I did a lot of repetitive things, like loading and storing vectors every time I needed to do some calculations and my lines became ridiculously long with all those DXMath calls.

Share this post


Link to post
Share on other sites

I would like to hear people's opinions on that, too. When I started to use DIrectXMath it was really uncomfortable for me. I thought that I was missing something, since I did a lot of repetitive things, like loading and storing vectors every time I needed to do some calculations and my lines became ridiculously long with all those DXMath calls.

 

Those store/loads are there because of the SEE implementation of the library. It is needed because of the memory alignment needed by the __m128 type (used for XMVECTOR XMMATRIX).

 

About the code... Usage of the library depends on your target platform. I suggest you to read carefully this http://msdn.microsoft.com/en-us/library/windows/desktop/ee418730(v=vs.85).aspx and a paper focused on data alignment.

Edited by imoogiBG

Share this post


Link to post
Share on other sites

Do you really need XHalfExtent. YHalfExtent and ZHalfExtent as XMFLOATx ?

 

I use XMStoreTypex and XMLoadTypex only when I need to store/load values to/from external objects. For internal class values I always use __m128 type. Yes, if the class object is dynamically allocated I need to align it to 16-byte, but that's not a big deal.

Edited by Alessio1989

Share this post


Link to post
Share on other sites
Thanks for the replies.
@Alessio: I need to save them to be able to use them for culling and collisions later on. For now my classes and structs only keep XMFLOATxx types, because of alignment issues if I don't save them as XMVECTOR's etc. As members. I might look into "anual alignment" later on, so I can have the class members also as XMVECTOR and XMMATRIX types

Share this post


Link to post
Share on other sites

 

I would like to hear people's opinions on that, too. When I started to use DIrectXMath it was really uncomfortable for me. I thought that I was missing something, since I did a lot of repetitive things, like loading and storing vectors every time I needed to do some calculations and my lines became ridiculously long with all those DXMath calls.

 

Those store/loads are there because of the SEE implementation of the library. It is needed because of the memory alignment needed by the __m128 type (used for XMVECTOR XMMATRIX).

 

About the code... Usage of the library depends on your target platform. I suggest you to read carefully this http://msdn.microsoft.com/en-us/library/windows/desktop/ee418730(v=vs.85).aspx and a paper focused on data alignment.

 

 

I know the reason why we load and store data and SSE behind it. However, the usage of the library becomes really tedious when you do that each time you want to process XMFLOAT. If you nest operations they become very long very quickly and there is lots of redundant code flying around. Thats why I am curios if everyone uses DXMath library like that or if they have found the ways to overcome those downsides. 

Share this post


Link to post
Share on other sites

Hi. I've finished my migration from d3dx to directxmath the way we described above.

And actually it's not so bad when you get used to I. After some time, you'll find ways to get clean code.

 

For example, for the temporary XMVECTOR and XMMATRIX types, I now use a var name starting with xm, this really helps.

Like this:

		XMVECTOR xmCenterOld = XMLoadFloat3(&mSphereCenterModel);
		XMMATRIX xmMatWorld = XMLoadFloat4x4(&mMatWorld);
		XMVECTOR xmCenterNew = XMVector3TransformCoord(xmCenterOld, xmMatWorld);
		XMStoreFloat3(&mBoundingSphere.WorldCenter, xmCenterNew);

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.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!