# High quality line drawing / illustration mode

This topic is 3379 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Dear forum, Adobe PDF allows the inclusion of 3D objects and can display them using various different drawing methods, i.e. wireframe, solid shading and "illustration": The "illustration" drawing mode looks very clean and has a high quality and accuracy. I want to reproduce this. Currently, I'm doing this via adjacency information, normals and some planar calculations to find creases in the object (C#, Managed DirectX). This produces a line list, which I draw with DrawPrimitive, and it looks like this:
protected static float DistanceOfPointToPlane(Vector3 planeA, Vector3 planeB, Vector3 planeC, Vector3 point)
{
Matrix matrix = new Matrix();
matrix.M11 = point.X - planeA.X;
matrix.M12 = point.Y - planeA.Y;
matrix.M13 = point.Z - planeA.Z;

matrix.M21 = point.X - planeB.X;
matrix.M22 = point.Y - planeB.Y;
matrix.M23 = point.Z - planeB.Z;

matrix.M31 = point.X - planeC.X;
matrix.M32 = point.Y - planeC.Y;
matrix.M33 = point.Z - planeC.Z;

matrix.M44 = 1;

return matrix.Determinant / 25f;
}

protected static bool IsEdge(Vector3 normalA, Vector3 normalB)
{
return (normalA - normalB).Length() > 0.01f;
}

protected static bool IsAdjacent(Vector3 positionA, Vector3 positionB)
{
return positionA == positionB;
}

protected static bool IsAdjacentEdge(CustomVertex.PositionNormal vertexA, CustomVertex.PositionNormal vertexB)
{
return (IsAdjacent(vertexA.Position, vertexB.Position) && IsEdge(vertexA.Normal, vertexB.Normal));
}

protected static CustomVertex.PositionOnly[] GenerateEdges(Mesh mesh, int[] adjacency)
{
CustomVertex.PositionNormal[] vertices = null;
ushort[] indices = null;
try
{
vertices = mesh.VertexBuffer.Lock(0, typeof(CustomVertex.PositionNormal),
LockFlags.ReadOnly, mesh.NumberVertices) as CustomVertex.PositionNormal[];

indices = mesh.IndexBuffer.Lock(0, typeof(ushort), LockFlags.ReadOnly,
mesh.IndexBuffer.Description.Size / (mesh.IndexBuffer.Description.Is16BitIndices ? 2 : 4)) as ushort[];

List<CustomVertex.PositionOnly> lineList = new List<CustomVertex.PositionOnly>();
for (int nIndex = 0; nIndex < indices.Length; nIndex += 3)
{
for (int nEdge = 0; nEdge < 3; nEdge++)
{
int nEdge1 = nEdge;
int nEdge2 = ((nEdge + 1) % 3);

if (adjacency[nIndex + nEdge] != -1)
{
bool hasEdge = false;
hasEdge |= IsAdjacentEdge(vertices[indices[nIndex + nEdge1]], vertices[indices[(adjacency[nIndex + nEdge] * 3) + 0]]);
hasEdge |= IsAdjacentEdge(vertices[indices[nIndex + nEdge1]], vertices[indices[(adjacency[nIndex + nEdge] * 3) + 1]]);
hasEdge |= IsAdjacentEdge(vertices[indices[nIndex + nEdge1]], vertices[indices[(adjacency[nIndex + nEdge] * 3) + 2]]);

hasEdge |= IsAdjacentEdge(vertices[indices[nIndex + nEdge2]], vertices[indices[(adjacency[nIndex + nEdge] * 3) + 0]]);
hasEdge |= IsAdjacentEdge(vertices[indices[nIndex + nEdge2]], vertices[indices[(adjacency[nIndex + nEdge] * 3) + 1]]);
hasEdge |= IsAdjacentEdge(vertices[indices[nIndex + nEdge2]], vertices[indices[(adjacency[nIndex + nEdge] * 3) + 2]]);

if (!hasEdge)
{
vertices[indices[(adjacency[nIndex + nEdge] * 3) + 0]].Position) ||
vertices[indices[(adjacency[nIndex + nEdge] * 3) + 0]].Position);

vertices[indices[(adjacency[nIndex + nEdge] * 3) + 1]].Position) ||
vertices[indices[(adjacency[nIndex + nEdge] * 3) + 1]].Position);

vertices[indices[(adjacency[nIndex + nEdge] * 3) + 2]].Position) ||
vertices[indices[(adjacency[nIndex + nEdge] * 3) + 2]].Position);

if ((vertex1Adj ? 1 : 0) + (vertex2Adj ? 1 : 0) + (vertex3Adj ? 1 : 0) == 2)
{
Vector3 testVertex = new Vector3();
if (!vertex1Adj) testVertex = vertices[indices[(adjacency[nIndex + nEdge] * 3) + 0]].Position;
else if (!vertex2Adj) testVertex = vertices[indices[(adjacency[nIndex + nEdge] * 3) + 1]].Position;
else if (!vertex3Adj) testVertex = vertices[indices[(adjacency[nIndex + nEdge] * 3) + 2]].Position;

float distance = Math.Abs(DistanceOfPointToPlane(
vertices[indices[nIndex + 0]].Position,
vertices[indices[nIndex + 1]].Position,
vertices[indices[nIndex + 2]].Position,
testVertex));

float perimeter = (float)(
(vertices[indices[nIndex + 0]].Position - vertices[indices[nIndex + 1]].Position).Length() +
(vertices[indices[nIndex + 1]].Position - vertices[indices[nIndex + 2]].Position).Length() +
(vertices[indices[nIndex + 2]].Position - vertices[indices[nIndex + 0]].Position).Length());
if (distance < perimeter / 5000)
continue;
}
}
}

if (vertices[indices[nIndex + nEdge1]].Position != vertices[indices[nIndex + nEdge2]].Position)
{
lineList.Add(new CustomVertex.PositionOnly(vertices[indices[nIndex + nEdge1]].Position));
lineList.Add(new CustomVertex.PositionOnly(vertices[indices[nIndex + nEdge2]].Position));
}
}

continue;
}
if (lineList.Count == 0)
return null;

return lineList.ToArray();
}
finally
{
if (vertices != null) mesh.VertexBuffer.Unlock();
if (indices != null) mesh.IndexBuffer.Unlock();
}
}


However, with my method, you won't see the outline of a completely round object, like a simple sphere, because no creases can be found. How could one reproduce the effect of the "illustration" mode with the same quality? Thank you in advance, Alexander

##### Share on other sites
You need to find and draw silhouette edges. A silhouette edge is an edge shared by two faces, where one of them is front facing the camera and the other is not.

##### Share on other sites
Quote:
 Original post by hirezYou need to find and draw silhouette edges. A silhouette edge is an edge shared by two faces, where one of them is front facing the camera and the other is not.

Thank you, I understand. Any other ideas, maybe example code or a project which already does this, preferably open source? My edge-finding algorithm looks more like a dirty hack and not like a reasonable solution.

##### Share on other sites
You could draw it (in monochrome?), and then use a 2D edge detection filter.

##### Share on other sites
Quote:
 Original post by Adam_42You could draw it (in monochrome?), and then use a 2D edge detection filter.

I also looked into this solution, however, you don't get the same clean look from image filters, you don't get edges with very similar or completely similar colored faces and edges appear and disappear when the object, camera or lightning is moved around.

##### Share on other sites
hey thanks for it i really like it and i understand it clearly .

1. 1
2. 2
3. 3
Rutin
20
4. 4
5. 5
khawk
14

• 9
• 11
• 11
• 23
• 12
• ### Forum Statistics

• Total Topics
633655
• Total Posts
3013181
×