Drawing Wireframe as Quad using linelist rather than Tri

Started by
6 comments, last by iedoc 12 years, 5 months ago
Hi all.

I'm trying to draw a polygon mesh with quad outlines on it a la 3d studio max - please see picture.
As I have algorithms ready to be implemented on quad meshes, it would be REALLY nice if I could get the quad rendering working.

I draw the normal mesh on the first pass, and then want to draw the quad outlines in a second pass.
so (1 2 3)(1 3 4 1) becomes (1 2 3 4).

I've got this working with tris and vertex ticks, it's just the Quad drawing that is driving me nuts.
When I try to do this with LineList and 4 primitives, it works for the first 3 primitives and then goes nuts for the 4th.
It looks like the 4th one tries to draw a line from the last vertex to the world origin.

Autodesk have managed it in 3dsmax, so I know it IS possible. It was really easy back in the OpenGL days with GL_POLYGON. So what am I missing?
I've tried both algorithmically hiding the shared middle Tri line as well as creating a int[] with quad indices.

Any idea how I would do this?

Cheers,
Craig.
Advertisement
just wondering, when you say [color=#1C2837][size=2](1 2 3)(1 3 4 1), do you mean [color=#1C2837][size=2](1 2 3)(1 3 4)? Because that would make more sense to me.
[color=#1C2837][size=2]

[color=#1C2837][size=2]That sounds like a problem I had a little while ago. My problem was because I was setting up my index buffer wrong, and it seems very likely to me that you are having the same problem, would you mind posting the code that turns your index list from triangles to quads?
Hi Iedoc,

Thanks for replying.

The indicies (1 2 3)(1 3 4 1) are a typo, it was meant to be (1 2 3)(1 3 4).

The indicies aren't built algorithmically, they are imported into 2 buffers now, one for quads and one for tris.
The below picture is what I am getting. (you can't see the soild mesh in that shot, but it's just a quad)


private void RenderQuadLines(EditMesh SM)
{
if (SM.QuadMeshIndicies == null)
throw new Exception("No quad data.");

Material Store = RenderingDevice.Material;

Material LineMaterial = new Material();
LineMaterial.Diffuse = Color.White;

SnowflakeVertex[] vb = SM.LockVertexBuffer();
int[] ib = SM.LockIndexBuffer();

for (int i = 0; i < SM.QuadIndex.Length; i+=4)
{
// WHAT FUNCTION DO I USE HERE TO DRAW THE QUADS? THE TRIS HAVE BEEN DRAWN SOLID IN ANOTHER PASS.
}

SM.UnlockIndexBuffer();
SM.UnlockVertexBuffer();

RenderingMaterial.Material = Store;
}


Would you be willing to post your quad rendering code?
After much messing around, I can't figure out for the life of me what the correct drawing function is.

Thanks.
Craig.
I have a couple little suggestions. Drawing quads with a line list should not be too difficult.

So, from your code, i see that you have already created your index buffer at this point? I think your making a mistake in your comment when you ask what function to use to "draw" the quads, because you shoudn't have to do any buffer locking when drawing things. You only need to lock the buffer if you need to update it or something. I'm assuming you created a dynamic buffer? Can I ask why you created a dynamic buffer? are you planning on updating your buffers a lot?

So anyway, If you could post the code you use to read the indices and create your buffers that would be more helpful. You say you are loading the indices directly from the file as quads AND triangles? So the file contains both a quad set of indices and a triangle set?

Remember, if your drawing quads with a line list, you will need to have four lines for each quad, which means 8 indices per quad. for example, to turn a quad index into a line index:

quad index:
(1, 2, 3, 4)

line index:
(1, 2)
(2, 3)
(3, 4)
(4, 1)

The same would be for a triangle list to a line list for quads.

Thats my first suggestion to make sure your turning your quad index into the right line index. My second idea was that I wanted to point out that some formats (such as obj) assume arrays start with "1", while c++ starts arrays with "0". Because of this, you need to make sure that you subtract one from all indices if the format you are loading assumes arrays start with "1". I thought about this because in your example you used (1, 2, 3) which should actually be (0, 1, 2) in c++. This is easy to find out by looking at the very first index loaded from the file. If it is a "0", then you don't have to worry about it, but if it's a "1" then you need to subtract 1 from all indices (I probably shouldn't say this will always work, but every model i've ever seen starts its index with the first vertex.)

I hope that helps. Oh yeah, about your buffers again though. I don't know what your program does, but if you do not plan on updating your buffers other than storing the initial index list, you shouldn't create dynamic buffers, and you should store the indicies in the buffer at the same time as you create the buffer.
Hey iedoc,

Maya OBJ is a fucking horrible file format. But don't worry, when I import the indices, i decrement them down one.
Maybe it's more of a concept I need a little help with then. I think that the bit of the 8 indices required per quad is the reason why the lines aren't drawing correctly.

So.
If I import a mesh, it will have the following

Mesh
{
vertexbuffer
TriIndexBuffer 3 per triangle as a standard indexbuffer
LineIndexBuffer 8 per quad
}

The question is, if you don't have to manually lock the buffers, how do I switch between the index buffers?
The rendering is done in a 2-pass mode.

Firstly a normal render is done using Mesh.DrawSubset().
This uses the vertexbuffer and the Tri index buffer to draw a standard solid mesh.

What for rendering the extra lines? Do I have to bind the indexbuffer to the 8-stride Lineindexbuffer? Is this SetStreamSource?

How would you do this?
Cheers,
Craig.
You will create two index buffers, and switch between them depending on if you want to draw the triangles or the quads.

I'm sure you already know, but just in case, to bind an index buffer to the IA, you will use this:

ID3D11DeviceContext::IASetIndexBuffer()

If you still need help, let me see the DrawSubset() method and the one where you create your buffers

and yeah, it seems to me that every modeling program has their own idea of how the obj format should be exported. The file can look really ugly sometimes after being exported from some programs
Apologies for the delay in replying.

Thanks man, that's sorted it. Creating a separate buffer for the Lines (0, 1)(1,2)(2,3)...etc fixed it.
Fucking absolute waste though, stupid to have to maintain another buffer just to do this.

One random question, when rendering the solid pass and the line pass the lines are on the other side of the quad. Any idea how to fix \ work around this?
I know there are some renderstate blending settings that can do this, but can't remember them at the minute :)
I think you could create a ID3D11DepthStencilState[color="#2A2A2A"] and set it's depth description's depthFunc to D3D11_COMPARISON_GREATER_EQUAL[font="Segoe UI"]
[/font]
[color="#2A2A2A"]So something like this might work

[color="#2A2A2A"] // Declared Globably
[color="#2A2A2A"] ID3D11DepthStencilState* [color="#2A2A2A"]DSGreaterEqual

[color="#2A2A2A"] // Setting up your scene
[font="Segoe UI"][color="#2a2a2a"] D3D11_DEPTH_STENCIL_DESC dssDesc;[/font]
[font="Segoe UI"][color="#2a2a2a"] ZeroMemory(&dssDesc, sizeof(D3D11_DEPTH_STENCIL_DESC));[/font]
[font="Segoe UI"][color="#2a2a2a"] dssDesc.DepthEnable = true;[/font]
[font="Segoe UI"][color="#2a2a2a"] dssDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;[/font]
[font="Segoe UI"][color="#2a2a2a"] dssDesc.DepthFunc = D3D11_COMPARISON_GREATER_EQUAL;[/font]
[font="Segoe UI"][color="#2a2a2a"] d3d11Device->CreateDepthStencilState(&dssDesc, &DSGreaterEqual);[/font]

[font="Segoe UI"][color="#2a2a2a"] // When drawing your scene[/font]
[font="Segoe UI"][color="#2a2a2a"] d3d11DevCon->OMSetDepthStencilState([/font][color="#2A2A2A"]DSGreaterEqual[font="Segoe UI"][color="#2a2a2a"], 0);[/font]
[font="Segoe UI"][color="#2a2a2a"] // Draw lines[/font]
[font="Segoe UI"][color="#2a2a2a"] [/font][font="Segoe UI"][color="#2a2a2a"]d3d11DevCon->OMSetDepthStencilState([/font][color="#2A2A2A"]NULL[font="Segoe UI"][color="#2a2a2a"], 0); // Set the depth stencil state back to its default[/font]

[font="Segoe UI"][color="#2a2a2a"] [/font]

This topic is closed to new replies.

Advertisement