Sign in to follow this  
belfegor

[DX9] Point inside pyramid

Recommended Posts

belfegor    2834
I have created model of pyramid (four sided), with tip (top) at origin and it is facing positive Z axis. Height is 1 (Z = 1) and its "base" four sides are all 2.

I need to know if my camera is inside this volume, so i write code to extract triangles normal:

[code]
...
hr = D3DXLoadMeshFromX(TEXT("pyramid_light_volume.x"), D3DXMESH_MANAGED, d3d9device, 0, 0, 0, 0, &pyramidLightMesh);
if(FAILED(hr))
{
MessageBox(0, TEXT("D3DXLoadMeshFromX() failed!"), 0, 0);
return false;
}

D3DVERTEXELEMENT9 decl[MAX_FVF_DECL_SIZE];
hr = pyramidLightMesh->GetDeclaration(decl);
if(FAILED(hr))
{
MessageBox(0, TEXT("Failed to load obtain pyramidLightMesh mesh declaration!"), 0, 0);
return false;
}

WORD offsetToPosition = 0;

for(UINT i = 0; i < MAX_FVF_DECL_SIZE; ++i)
{
if(decl[i].Stream == 0xFF || decl[i].Stream != 0)
{
break;
}

if((decl[i].Usage == D3DDECLUSAGE_POSITION) && (decl[i].Type == D3DDECLTYPE_FLOAT3))
{
offsetToPosition = decl[i].Offset;
continue;
}
}

DWORD numVertices = pyramidLightMesh->GetNumVertices();
DWORD numIndices = pyramidLightMesh->GetNumFaces() * 3;
DWORD vertSz = pyramidLightMesh->GetNumBytesPerVertex();

std::vector<D3DXVECTOR3> vPositions;

BYTE* pVertices;
pyramidLightMesh->LockVertexBuffer(0, (LPVOID*)&pVertices);
for(DWORD i = 0; i < numVertices; ++i)
{
D3DXVECTOR3 pos;
pos.x = *reinterpret_cast<float*>((i * vertSz) + pVertices + offsetToPosition);
pos.y = *reinterpret_cast<float*>((i * vertSz) + pVertices + offsetToPosition + sizeof(float));
pos.z = *reinterpret_cast<float*>((i * vertSz) + pVertices + offsetToPosition + sizeof(float) * 2);
vPositions.push_back(pos);
}
pyramidLightMesh->UnlockVertexBuffer();

for(USHORT i = 0; i < numIndices; i += 3)
{
D3DXVECTOR3 norm;
norm = GetTriNormal(vPositions[i+2], vPositions[i+1], vPositions[i]);
vPyramidLightNormals.push_back(norm);
}
[/code]

where GetTriNormal is:

[code]
D3DXVECTOR3 GetTriNormal(const D3DXVECTOR3& v0, const D3DXVECTOR3& v1, const D3DXVECTOR3& v2)
{
D3DXVECTOR3 n;
n.x = (v2.y - v0.y) * (v1.z - v0.z) - (v1.y - v0.y) * (v2.z - v0.z);
n.y = (v2.z - v0.z) * (v1.x - v0.x) - (v1.z - v0.z) * (v2.x - v0.x);
n.z = (v2.x - v0.x) * (v1.y - v0.y) - (v1.x - v0.x) * (v2.y - v0.y);
float fac1 = std::sqrt((n.x * n.x) + (n.y * n.y) + (n.z * n.z));
n.x = n.x / fac1;
n.y = n.y / fac1;
n.z = n.z / fac1;
return n;
}
[/code]


and then i check if cam is inside this pyramid:

[code]
for(std::size_t i = 0; i < vPyramidLightNormals.size(); ++i)
{
D3DXPLANE plane;
D3DXPlaneFromPointNormal(&plane, &lightPos, &vPyramidLightNormals[i]);
if(D3DXPlaneDotCoord(&plane, &cam->Position) < 0.0f)
{
result = false;
break;
}
}
[/code]

But it is not working correctly. What am i doing wrong? Any other idea?

Thanks for your time.

Share this post


Link to post
Share on other sites
Xashmi    115
This line
[source lang="java"] D3DXPlaneFromPointNormal(&plane, &lightPos, &vPyramidLightNormals[i]);[/source]
Here you should use one of the points in the pyramid corresponding to the normal instead of lightPos.

Unless you need the normals for anything else I think you'd be better off if you just computed the plane directly. Instead of your "GetTriNormal", use a "GetTriPlane". Edited by Xashmi

Share this post


Link to post
Share on other sites
belfegor    2834
Looks like it works, i am not sure if i got it all right so please correct me if you see more mistakes:

I grabbed positions in a vector:
[code]
for(std::size_t i = 0; i < vPyramidLightPoints.size(); i+=3)
{
D3DXVECTOR3 v0 = vPyramidLightPoints[i+2];
D3DXVECTOR3 v1 = vPyramidLightPoints[i+1];
D3DXVECTOR3 v2 = vPyramidLightPoints[i];
D3DXVec3TransformCoord(&v0, &v0, &transform);
D3DXVec3TransformCoord(&v1, &v1, &transform);
D3DXVec3TransformCoord(&v2, &v2, &transform);
D3DXPLANE plane;
D3DXPlaneFromPoints(&plane, &v0, &v1, &v2) ;
if(D3DXPlaneDotCoord(&plane, &cam->Position) + cam->Near < 0.0f)
{
result = false;
break;
}
}
[/code]

'transform' is a matrix used to transform pyramid to correct size/orientation so is it right to transform those points this way?

Share this post


Link to post
Share on other sites
belfegor    2834
I am rendering 6 pyramids to form 1 point light shadows/light, but i got some "offset error" although it should not be as pyramids are tightly placed:

[img]http://www.dodaj.rs/f/3q/uH/4CNs9xWk/error.jpg[/img]

Solved. Changed Clamp instead Border address mode.
Now only issue i have is when geometry is being clipped by cam near plane and its position is still "outside". Edited by belfegor

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