[GOOD NEWS! READ PLEASE] How to generate adjacency?

Started by
34 comments, last by XVincentX 15 years, 9 months ago
Mmm, let's make some proves

uint i0, i1, i2;uint j0, j1, j2;for(uint i=0; i<numIndices; i+=3){	i0 = Indices[i*3+0];	i1 = Indices[i*3+1];	i2 = Indices[i*3+2];	pAdj[i*6+0] = i0;	pAdj[i*6+1] = 0xffffffff;	pAdj[i*6+2] = i1;	pAdj[i*6+3] = 0xffffffff;	pAdj[i*6+4] = i2;	pAdj[i*6+5] = 0xffffffff;


This code simply loads vertices in even indices.
So, i = 0
	i0 = Indices[0*3+0];	i1 = Indices[0*3+1];	i2 = Indices[0*3+2];	pAdj[0*6+0] = i0;	pAdj[0*6+1] = 0xffffffff;	pAdj[0*6+2] = i1;	pAdj[0*6+3] = 0xffffffff;	pAdj[0*6+4] = i2;	pAdj[0*6+5] = 0xffffffff;


Ok, first 3 indices in first 3 even position.
i+=3

	i0 = Indices[3*3+0]; //9	i1 = Indices[3*3+1]; //10	i2 = Indices[3*3+2]; //11//And 4-5-6-7-8?? where are?? we do not take it?	pAdj[3*6+0] = i0; //18	pAdj[3*6+1] = 0xffffffff;//19	pAdj[3*6+2] = i1;//20	pAdj[3*6+3] = 0xffffffff;//21	pAdj[3*6+4] = i2;//22	pAdj[3*6+5] = 0xffffffff;//23


And all other indices? Do we jump it?
mabye i've not understand the way?
Advertisement
This loads odd and even vertices
	pAdj[0*6+0] = i0;	pAdj[0*6+1] = 0xffffffff;	pAdj[0*6+2] = i1;	pAdj[0*6+3] = 0xffffffff;	pAdj[0*6+4] = i2;	pAdj[0*6+5] = 0xffffffff;

equals
	pAdj[0] = i0; // even	pAdj[1] = 0xffffffff; // odd	pAdj[2] = i1; // even	pAdj[3] = 0xffffffff; // odd	pAdj[4] = i2; // even	pAdj[5] = 0xffffffff; // odd

0*6+3 == 3! [smile]

EDIT:
i=0 loads pAdj 0 through 5
i=1 loads pAdj 6 through 11
etc.
EDIT2:
Remember, the subscript is evaluated as (i*6)+3, not i*(6+3).

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

Quote:Original post by Buckeye
EDIT:
i=0 loads pAdj 0 through 5
i=1 loads pAdj 6 through 11



Yes but i never = 1 becouse in for cycle, it's written i+=3!
If in multiplication you use 6, i must be i++ and not +3, as i wrote upper.

If with i and j you indicate a triangle face, then the cycle should be

for(unsigned int j=0; j<this->MeshData.ColladaBuffer.Indici/3; j++)


This code works (on compiling and buffer size side, but not in the D3D10 side)

UINT *pAdj = new UINT[2 * this->MeshData.ColladaBuffer.Indici];	unsigned int i0, i1, i2;	unsigned int j0, j1, j2;	for(unsigned int i=0; i<this->MeshData.ColladaBuffer.Indici/3; i++)	{		i0 = this->MeshData.Indices[i*3+0];		i1 = this->MeshData.Indices[i*3+1];		i2 = this->MeshData.Indices[i*3+2];		pAdj[i*6+0] = i0;		pAdj[i*6+1] = 0xffffffff;		pAdj[i*6+2] = i1;		pAdj[i*6+3] = 0xffffffff;		pAdj[i*6+4] = i2;		pAdj[i*6+5] = 0xffffffff;		for(unsigned int j=0; j<this->MeshData.ColladaBuffer.Indici/3; j++)		{			if( j != i ) // don't check a triangle against itself			{				j0 = this->MeshData.Indices[j*3+0];				j1 = this->MeshData.Indices[j*3+1];				j2 = this->MeshData.Indices[j*3+2];				// check for i0 and i1				if( j0 == i0 )				{					if(j1==i1) pAdj[i*6+1] = j2;					else if(j2==i1) pAdj[i*6+1] = j1;				} else if( j1==j0 )				{					if(j0==i1) pAdj[i*6+1] = j2;					else if(j2==i1) pAdj[i*6+1] = j0;				} else if( j2==i0 )				{					if(j0==i1) pAdj[i*6+1] = j1;					else if(j1==i1) pAdj[i*6+1] = j0;				}				// check for i1 and i2				if( j0 == i1 )				{					if(j1==i2) pAdj[i*6+3] = j2;					else if(j2==i2) pAdj[i*6+3] = j1;				} else if( j1==i1 )				{					if(j0==i2) pAdj[i*6+3] = j2;					else if(j2==i2) pAdj[i*6+3] = j0;				} else if( j2==i1 )				{					if(j0==i2) pAdj[i*6+3] = j1;					else if(j1==i2) pAdj[i*6+3] = j0;				}				// check for i2 and i0				if( j0 == i2 )				{					if(j1==i0) pAdj[i*6+5] = j2;					else if(j2==i0) pAdj[i*6+5] = j1;				} else if( j1==i2 )				{					if(j0==i0) pAdj[i*6+5] = j2;					else if(j2==i0) pAdj[i*6+5] = j0;				} else if( j2==i2 )				{					if(j0==i0) pAdj[i*6+5] = j1;					else if(j1==i0) pAdj[i*6+5] = j0;				}			}		}		}	ID3D10Device *device;	D3D10_BUFFER_DESC desc;	this->MeshData.ColladaBuffer.IndexBuffer->GetDesc(&desc);	this->MeshData.ColladaBuffer.IndexBuffer->GetDevice(&device);	this->MeshData.ColladaBuffer.IndexBuffer->Release();	desc.ByteWidth *= 2;	desc.CPUAccessFlags = 0;	desc.Usage = D3D10_USAGE_DEFAULT;	D3D10_SUBRESOURCE_DATA sub;	sub.pSysMem = pAdj;	device->CreateBuffer(&desc,&sub,&this->MeshData.ColladaBuffer.IndexBuffer);	delete[] pAdj;		this->MeshData.ColladaBuffer.Indici *= 2;
You're absolutely correct, XVincentX! How embarassing! I apologize. I didn't play close enough attention to your comments.

How about:
for(uint i=0; i<numIndices/3; i++){	i0 = Indices[i*3+0];	i1 = Indices[i*3+1];	i2 = Indices[i*3+2];	pAdj[i*6+0] = i0;	pAdj[i*6+1] = 0xffffffff;	pAdj[i*6+2] = i1;	pAdj[i*6+3] = 0xffffffff;	pAdj[i*6+4] = i2;	pAdj[i*6+5] = 0xffffffff;


EDIT:
And, of course, j=0; j < numIndices/3; j++

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

There is another error, now. (i was going on while i was waiting your answer)
Using your code and generating Adjacency, with this rendering function

	shader->GetTechniqueByIndex(0)->GetPassByIndex(0)->Apply(0);	device->IASetInputLayout(Alien.layout);	device->IASetIndexBuffer(Alien.MeshData.ColladaBuffer.IndexBuffer,DXGI_FORMAT_R32_UINT,0);	device->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ);		device->IASetVertexBuffers(0,1,&Alien.MeshData.ColladaBuffer.VertexBuffer,&Alien.MeshData.Stride,&Alien.MeshData.Offset);		device->DrawIndexed(Alien.MeshData.ColladaBuffer.Indici,0,0);


And using the most simple shader (that works without the Adjacency generation)

I receive this -> http://img105.imageshack.us/img105/2330/34771042qv4.jpg

The same function works if i do not call the GenerateAdjacency function: i can see (i'm using TRIANGLELIST_ADJ) not completely the mesh, but some trinagles less, and it's right becouse the DrawFunction does not sendd to the shader the adjacency vertices.

The buffer is completely filled, becouse if i replace with
UINT *pAdj = new UINT[2 * this->MeshData.ColladaBuffer.Indici-1];

I receive an error: buffer beyond the heap.

So the vertices are not mapped in the right positions...sob sob...
Try using just
for(uint i=0; i<numIndices/3; i++){	i0 = Indices[i*3+0];	i1 = Indices[i*3+1];	i2 = Indices[i*3+2];	pAdj[i*6+0] = i0;	pAdj[i*6+1] = 0xffffffff;	pAdj[i*6+2] = i1;	pAdj[i*6+3] = 0xffffffff;	pAdj[i*6+4] = i2;	pAdj[i*6+5] = 0xffffffff;}

That is, fill pAdj and don't make the adjacency tests. How does that render?

EDIT: In the docs, the comment is made, "a leading vertex is the first non-adjacent vertex in a primitive." I'm not sure how to interpret that. It may be that you do not have any "non-adjacent" vertices if your mesh has no free edges. That's why I suggested the above pAdj.

A "non-adjacent" vertex may be a vertex that is not adjacent to exactly 3 other triangles. If so, the algorithm I came up with would have to be revised extensively!

Also, be aware that the value 0xffffffff was just a guess for indicating a "null" index. However, I don't know what other value could be used.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

I made some logs of buffer, i created with this 3 codes

	char tmp2[10];	FILE *fil2 = fopen("original.txt","w");	for (int i = 0; i <this->MeshData.ColladaBuffer.Indici;i++)	{		sprintf(tmp2,"%d",this->MeshData.Indices);		fwrite(tmp2,1,strlen(tmp2),fil2);		fwrite(" \n",1,strlen(" \n"),fil2);	}	fclose(fil2);	char tmp[10];	FILE *fil = fopen("adjacency.txt","w");	for (int i = 0; i <2*this->MeshData.ColladaBuffer.Indici;i++)	{		sprintf(tmp,"%d",pAdj);		fwrite(tmp,1,strlen(tmp),fil);		fwrite(" \n",1,strlen(" \n"),fil);	}	fclose(fil);	char tmp3[10];	FILE *fil3 = fopen("indexfromadjacency.txt","w");	for (int i = 0; i <2*this->MeshData.ColladaBuffer.Indici;i+=2)	{		sprintf(tmp3,"%d",pAdj);		fwrite(tmp3,1,strlen(tmp),fil3);		fwrite(" \n",1,strlen(" \n"),fil3);	}	fclose(fil3);


To have a situation of original index buffer, the adjacency buffer generated and the index buffer taken from the adjacency (only even positions).
Results are here:
http://xvincentx.netsons.org/inices.rar
and all them looks like ok.

Using only that code on the screen nothing appears!
I will try using PIX to see what happens!
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM...


I tried to change the 0xffffff with 0.
Now the mesh it's visualized correctly!!!
I do not know why...


EDIT: even if i write 1,2,3,4,5,6,7 it works...


Another strange thing it's the shader.
I'm using this 2 simple shaders: one for drawing mesh, another for silhouette detecting:

float4x4	ViewMatrix;float4x4	WorldMatrix;float4x4	ProjMatrix;float4		LightDirection = float4(0.557,0.557,0.557,1);float4		MaterialColor;float3		EyePosition;texture2D	Texture;SamplerState SamplText{	Filter = MIN_MAG_MIP_LINEAR;	AddressU = Wrap;	AddressV = Wrap;};DepthStencilState StencilShadow{    DepthEnable = true;    DepthWriteMask = ZERO;    DepthFunc = LESS;        StencilEnable = true;    StencilReadMask = 0xFFFFFFFF;    StencilWriteMask = 0xFFFFFFFF;        FrontFaceStencilFunc = ALWAYS;    FrontFaceStencilPass = INCR;    FrontFaceStencilFail = Keep;        BackFaceStencilFunc = ALWAYS;    BackFaceStencilPass = DECR;    BackFaceStencilFail = Keep;};DepthStencilState DefaultDepth{	DepthEnable = true;	DepthFunc = LESS;	DepthWriteMask = ALL;	StencilEnable = false;};struct VS_INPUT{	float4	Pos	:	POSITION;	float3	Tex	:	TEXCOORD;	float3	Nor	:	NORMAL;};struct PS_INPUT{	float4	Pos	:	SV_POSITION;	float4	WorldPos	:	WORLDPOSITION;	float3	Tex	:	TEXCOORD;	float3	Nor	:	NORMAL;};float3 GetNormal( float3 A, float3 B, float3 C ){	float3 AB = B - A;	float3 AC = C - A;	return normalize( cross(AB,AC) );}PS_INPUT vs_main(VS_INPUT Input){	PS_INPUT Out = (PS_INPUT)0;	Out.Pos = mul(mul(mul(Input.Pos,WorldMatrix),ViewMatrix),ProjMatrix);	Out.Tex = Input.Tex;	Out.WorldPos = Input.Pos;	Out.Nor = Input.Nor;	return Out;}float4 ps_main(PS_INPUT In)	:	SV_TARGET{		float3 L = normalize(LightDirection.xyz);			float4 D = saturate(dot(In.Nor,L)  * float4(0.5,0.3,0.4,1) * MaterialColor);		float3 V = normalize(EyePosition - In.WorldPos);		float3 R = normalize(2.0F * In.Nor * dot(In.Nor,L) - L);		float4 S = pow(max(0.0F,dot(R,V)),2);				return saturate(D + S);	}VS_INPUT vs_shadow(VS_INPUT In){	In.Pos = mul(In.Pos,WorldMatrix);	In.Nor = mul(In.Nor,WorldMatrix);		return In;}[maxvertexcount(24)]void gs_shadow(triangleadj VS_INPUT In[6],inout TriangleStream<PS_INPUT> Stream){/*	Dalla documentazione di D3D10, i vertici originali sono quelli pari, gli	adiacenti quelli dispari.*/		if (dot(normalize(LightDirection),GetNormal(In[0].Pos.xyz,In[2].Pos.xyz,In[4].Pos.xyz)) > 0.0f)	{		PS_INPUT vertex = (PS_INPUT)0;		for( uint i = 0; i < 6; i+=2)		{			uint next = (i+2) % 6;			if (dot(LightDirection,GetNormal(In.Pos.xyz,In[i+1].Pos.xyz,In[next].Pos.xyz)) < 0.0f)			{				vertex.WorldPos = In.Pos;				vertex.Pos = mul(mul(In.Pos,ViewMatrix),ProjMatrix);				vertex.Nor = In.Nor;				vertex.Tex = In.Tex;								Stream.Append(vertex);								vertex.WorldPos = In[next].Pos;				vertex.Pos = mul(mul(In[next].Pos,ViewMatrix),ProjMatrix);				vertex.Nor = In[next].Nor;				vertex.Tex = In[next].Tex;								Stream.Append(vertex);								Stream.RestartStrip();			}		}			}}float4 ps_shadow(float4 Pos:SV_Position)	: SV_TARGET{	return float4(1,0,0,1);}technique10 ShadowVolume{	Pass Geometrie	{		SetVertexShader( CompileShader( vs_4_0, vs_main() ) );		SetGeometryShader(NULL);		SetPixelShader( CompileShader( ps_4_0, ps_main() ) );		SetDepthStencilState(DefaultDepth,0);	}		Pass Shadow	{		SetVertexShader( CompileShader( vs_4_0, vs_shadow() ) );		SetGeometryShader( CompileShader ( gs_4_0, gs_shadow() ) );		SetPixelShader( CompileShader( ps_4_0, ps_shadow() ) );	}	}


The draw functions uses first and second pass.
PIX say me an horrible thing!!!
IMG HERE-> http://img71.imageshack.us/img71/4364/immaginefx1.jpg

Mabye it want to say me that it's not giving out any kind of primitive?

[Edited by - XVincentX on June 28, 2008 11:35:46 AM]
I made other proves: geometry shader says null becose no primitive it's rendered from it. If i change code with normal rendering (Appending only even vertices) it works.
Anyway, there is yet the problem of what value give to non adjacent vertices, and, anyway, the geometry shader does not detect silhouettes...

EDIT: i found another mistake

				if( j0 == i0 )				{					if(j1==i1) pAdj[i*6+1] = j2;					else if(j2==i1) pAdj[i*6+1] = j1;				} else if( j1==j0 )				{


What does it means the black row?

[Edited by - XVincentX on June 28, 2008 11:29:52 AM]

This topic is closed to new replies.

Advertisement