Sign in to follow this  
Anddos

Drawing picked triangles of a mesh

Recommended Posts

I am trying to draw the picked triangles on a mesh but debugging is stopping on these lines with a crash... d3ddev->SetVertexDeclaration(Decl); d3ddev->SetStreamSource(0, vb, 0, sizeof(Decl)); does anyone know how to fix it?
void detect_picking(LPD3DXMESH Mesh,DWORD &gfaceIndex,LPDIRECT3DDEVICE9 d3ddev)
{
    // get the current transform matrices
    D3DXMATRIX matProjection, matView, matWorld, matInverse;
    d3ddev->GetTransform(D3DTS_PROJECTION, &matProjection);
    d3ddev->GetTransform(D3DTS_VIEW, &matView);
    d3ddev->GetTransform(D3DTS_WORLD, &matWorld);

    // use the mouse coordinates to get the mouse angle
	POINT MousePos;
    GetCursorPos(&MousePos);
	//SetCursorPos(800/2,600/2);
	//ScreenToClient(hWnd,&MousePos);
	//SetWindowText(hWnd,((LPCWSTR)MousePos.x));
    float xAngle = (((2.0f * MousePos.x) / SCREEN_WIDTH) - 1.0f) / matProjection(0, 0);
    float yAngle = (((-2.0f * MousePos.y) / SCREEN_HEIGHT) + 1.0f) / matProjection(1, 1);

	

    D3DXVECTOR3 origin, direction;
    origin = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
    direction = D3DXVECTOR3(xAngle, yAngle, 1.0f);

    // find the inverse matrix
    D3DXMatrixInverse(&matInverse, NULL, &(matWorld * matView));

    // convert origin and direction into model space
    D3DXVec3TransformCoord(&origin, &origin, &matInverse);
    D3DXVec3TransformNormal(&direction, &direction, &matInverse);
    D3DXVec3Normalize(&direction, &direction);

    // detect picking
    BOOL hit;
	char Buffer[64];
	float Dist;
	DWORD faceIndex;
	D3DXIntersect(Mesh, &origin, &direction, &hit, &faceIndex, NULL, NULL, &Dist, NULL, NULL);
    if(hit)
	{
        d3ddev->SetRenderState(D3DRS_LIGHTING, FALSE);
	    d3ddev->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);
		gfaceIndex = faceIndex;
		// Yes, draw the picked triangle in solid mode.
			IDirect3DVertexBuffer9* vb = 0;
			IDirect3DIndexBuffer9* ib = 0;
			Mesh->GetVertexBuffer(&vb);
			Mesh->GetIndexBuffer(&ib);

			d3ddev->SetIndices(ib);
			d3ddev->SetVertexDeclaration(Decl);
			d3ddev->SetStreamSource(0, vb, 0, sizeof(Decl));

			// faceIndex identifies the picked triangle to draw.
			d3ddev->DrawIndexedPrimitive(
				D3DPT_TRIANGLELIST, 0, 0, Mesh->GetNumVertices(), faceIndex*3, 1);
			
			
	}
	else
	{
		d3ddev->SetRenderState(D3DRS_LIGHTING, TRUE);
		d3ddev->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
	}
}

Share this post


Link to post
Share on other sites
Quote:
Try using mesh->GetNumBytesPerVertex().

Not sizeof(...), just the number of bytes. [wink]

EDIT: d3ddev->SetStreamSource(0, vb, 0, Mesh->GetNumBytesPerVertex());

sizeof( numberOfBytes ) will return the sizeof(DWORD), which is what GetNumBytesPerVertex returns.

Share this post


Link to post
Share on other sites
No but i just tried and i am stuck with the parameter for it
Mesh->GetDeclaration , its asking for a D3DVERTEXELEMENT9
this stuff is new terriotry to me

Share this post


Link to post
Share on other sites
Still crashing mate , here's what i have.

IDirect3DVertexBuffer9* vb = 0;
IDirect3DIndexBuffer9* ib = 0;
Mesh->GetVertexBuffer(&vb);
Mesh->GetIndexBuffer(&ib);
d3ddev->SetIndices(ib);
D3DVERTEXELEMENT9 Decls[MAX_FVF_DECL_SIZE];
Mesh->GetDeclaration(Decls);
d3ddev->SetVertexDeclaration(Decl);
d3ddev->SetStreamSource(0, vb, 0, Mesh->GetNumBytesPerVertex());

Share this post


Link to post
Share on other sites
I'm an idiot. You're not using a shader.

You have to use dev->SetFVF with DrawIndexedPrimitive. You'll have to get that with mesh->GetFVF.

Depending on the mesh vertex structure, you may not be able to specify a compatible FVF, as only certain constructions are allowed.

Try mesh->GetFVF and dev->SetFVF being sure to check the error return from GetFVF, in case it's not compatible.

From the docs:
Quote:
This method can return 0 if the vertex format cannot be mapped directly to an FVF code. This will occur for a mesh created from a vertex declaration that doesn't have the same order and elements supported by the FVF codes.

EDIT: if the mesh vertex format isn't compatible with an FVF declaration, you may have to create a vertex buffer with an FVF, extract vertex information from the mesh to put in that vertex buffer, and render the FVF type vertex buffer.

Share this post


Link to post
Share on other sites
Quote:
Try mesh->GetFVF and dev->SetFVF being sure to check the error return from GetFVF, in case it's not compatible.

You can try SetFVF(mesh->GetFVF()) but it may result in an error. That's why I posted the above.

EDIT: Friendly advice - take the time to check return codes from your DirectX calls. You'll never notice a performance hit, but it will save you hours of trying to find problems.

DWORD meshfvf = mesh->GetFVF();
if( meshfvf==0 ) { .. tell yourself you have a problem .. }
else {
dev->SetFVF(meshfvf);
...
}

Share this post


Link to post
Share on other sites
my book actually uses this method but i get an error
error LNK2001: unresolved external symbol "public: static struct IDirect3DVertexDeclaration9 * VertexPNT::Decl" (?Decl@VertexPNT@@2PAUIDirect3DVertexDeclaration9@@A)
1>C:\Users\Anddos\Desktop\DirectX Stuff\PickMesh\Release\PickMesh.exe : fatal error LNK1120: 1 unresolved externals


vertex.h
struct VertexPNT
{
VertexPNT()
:pos(0.0f, 0.0f, 0.0f),
normal(0.0f, 0.0f, 0.0f),
tex0(0.0f, 0.0f){}
VertexPNT(float x, float y, float z,
float nx, float ny, float nz,
float u, float v):pos(x,y,z), normal(nx,ny,nz), tex0(u,v){}
VertexPNT(const D3DXVECTOR3& v, const D3DXVECTOR3& n, const D3DXVECTOR2& uv)
:pos(v),normal(n), tex0(uv){}

D3DXVECTOR3 pos;
D3DXVECTOR3 normal;
D3DXVECTOR2 tex0;

static IDirect3DVertexDeclaration9* Decl;
};

vertex.cpp
D3DVERTEXELEMENT9 VertexPNTElements[] =
{
{0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
{0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
{0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
D3DDECL_END()
};
HR(gd3dDevice->CreateVertexDeclaration(VertexPNTElements, &VertexPNT::Decl));


// Yes, draw the picked triangle in solid mode.
IDirect3DVertexBuffer9* vb = 0;
IDirect3DIndexBuffer9* ib = 0;
HR(mMesh->GetVertexBuffer(&vb));
HR(mMesh->GetIndexBuffer(&ib));

HR(gd3dDevice->SetIndices(ib));
HR(gd3dDevice->SetVertexDeclaration(VertexPNT::Decl));
HR(gd3dDevice->SetStreamSource(0, vb, 0, sizeof(VertexPNT)));

// faceIndex identifies the picked triangle to draw.
HR(gd3dDevice->DrawIndexedPrimitive(
D3DPT_TRIANGLELIST, 0, 0, mMesh->GetNumVertices(), faceIndex*3,



sorry i didnt say this before

Share this post


Link to post
Share on other sites
VertPNT is just a structure declaration. Do you declare an instance of VertPNT somewhere? (EDIT: I see where you set it)

By the way, are you using a shader?

EDIT: By the way, if you're not using a shader, you can't use SetVertexDeclaration. Even if you are, and if VertPNT is the same structure you use for the mesh, GetFVF will work fine.

Share this post


Link to post
Share on other sites
ok so i have the code compiles fine but when i put the cursor over the box i dont see the triangle face etc..


IDirect3DVertexBuffer9* vb = 0;
IDirect3DIndexBuffer9* ib = 0;
Mesh->GetVertexBuffer(&vb);
Mesh->GetIndexBuffer(&ib);
d3ddev->SetIndices(ib);


DWORD meshfvf = Mesh->GetFVF();
if( meshfvf==0 ) { MessageBox(NULL,L"Error",L"",0); }
else {
d3ddev->SetFVF(meshfvf);
}


d3ddev->SetStreamSource(0, vb, 0, Mesh->GetNumBytesPerVertex());

Share this post


Link to post
Share on other sites
i think i have it working using this method


void LockMesh(LPD3DXMESH Mesh)
{
BYTE* lpbVb;
int numIndices;
BYTE *lpIB;
DWORD idxVbVert0, idxVbVert1, idxVbVert2;
D3DINDEXBUFFER_DESC ibdesc;
LPDIRECT3DINDEXBUFFER9 lpIndexBuffer = NULL;
Mesh->LockVertexBuffer(D3DLOCK_READONLY, (VOID**)&lpbVb);
Mesh->LockIndexBuffer ( D3DLOCK_READONLY, (VOID**)&lpIB);
Mesh->GetIndexBuffer( &lpIndexBuffer );
lpIndexBuffer->GetDesc( &ibdesc );
if(ibdesc.Format == D3DFMT_INDEX32)
{
//MessageBox(NULL,"ibdesc.Format 32","",0);
numIndices = ibdesc.Size / sizeof(DWORD);
}
else
{
//MessageBox(NULL,"ibdesc.Format 16","",0);
numIndices = ibdesc.Size / sizeof(WORD);

SetRect(&textbox, 0, 60, 640, 480);
sprintf(OutBuffer,"%s %s\n","ibdesc.Format","16");
// draw the Hello World text
dxfont->DrawTextA(NULL,
OutBuffer,
strlen(OutBuffer),
&textbox,
NULL,//DT_CENTER | DT_VCENTER,
D3DCOLOR_ARGB(255, 255, 0, 0));

SetRect(&textbox, 0, 80, 640, 480);
sprintf(OutBuffer,"%s %d\n","numIndices",numIndices);
// draw the Hello World text
dxfont->DrawTextA(NULL,
OutBuffer,
strlen(OutBuffer),
&textbox,
NULL,//DT_CENTER | DT_VCENTER,
D3DCOLOR_ARGB(255, 255, 0, 0));

}

DWORD numBytesPerVertex = Mesh->GetNumBytesPerVertex();


for(int i=0; i<numIndices; i += 3 )
{
idxVbVert0 = ((WORD*)lpIB)[ i ];
idxVbVert1 = ((WORD*)lpIB)[ i+1 ];
idxVbVert2 = ((WORD*)lpIB)[ i+2 ];

D3DXVECTOR3 v0 = *(D3DXVECTOR3*) &lpbVb[ idxVbVert0 * numBytesPerVertex ];
D3DXVECTOR3 v1 = *(D3DXVECTOR3*) &lpbVb[ idxVbVert1 * numBytesPerVertex ];
D3DXVECTOR3 v2 = *(D3DXVECTOR3*) &lpbVb[ idxVbVert2 * numBytesPerVertex ];

if(i == 12)
{
GVert1 = v0;
GVert2 = v1;
GVert3 = v2;
}

sprintf(OutBuffer,"%s %f %f %f\n","v0",v0.x,v0.y,v0.z);
//myfile << OutBuffer;
sprintf(OutBuffer,"%s %f %f %f\n","v1",v1.x,v1.y,v1.z);
//myfile << OutBuffer;
sprintf(OutBuffer,"%s %f %f %f\n","v2",v2.x,v2.y,v2.z);
//myfile << OutBuffer;
sprintf(OutBuffer,"%s %d\n","i",i);
//myfile << OutBuffer;
}


Mesh->UnlockVertexBuffer();
Mesh->UnlockVertexBuffer();
}


[img]http://img692.imageshack.us/img692/372/pickq.jpg[/img]

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