WebGL: Drawing Edge Lines

←Back

Related Topics: Loading OBJ, Vector3 class

Overview

edges of poygons
Shared edges are common edges of 2 adjacent triangles

An edge is a line segment joining 2 vertices of a polygon, for example, a triangle has 3 edges. A geometry consists of multiple triangles and some triangles in the geometry may share common edges by the neighbour triangles. Sometimes, you want to find the edges of a 3D geometry, particularly hard edges, which are sharp angle between 2 neighbour faces. Or, you want to the outline of 3D object from the view point or draw the wireframe of the 3D model.

This page explains how to find the edge lines from a 3D model.

Finding Edges

Edge class is used to define an edge from the given vertex array of a 3D gemetry. It consists of 2 endpoint vertices as Vector3 class. It also stores 2 face normals; one for the current face and the other for the adjacent face to determine if it is hard edge or not.

It also provides a class function, Edge.generateEdges() to find all edges from the input vertex list of a 3D mesh. (The geometry must be triangulated first.) The steps to find all edges are;

  1. Find 3 edge segments from a single triangle and its face normal
  2. Store each edge to the edge list if it is new
  3. Update the second normal of the edge if it already exits in th edge list (shared edge)
  4. Repeat the above steps for every triangle

The following code is finding all the edges after loading an OBJ model. Edge.generateEdges() returns an array of Edge objects.


// global var
let gl = {};
...

// load OBJ file
gl.obj = new ObjModel();
gl.obj.read("cube.obj").then(obj =>
{
    // convert vertices to an array of Vector3 objects
    let vertices = ObjModel.toVertices(obj);

    // find edges from vertex list
    let edges = Edge.generateEdges(vertices);

    // can convert to Float32Array for VBO
    let vboVertices = Edge.toFloat32Array(edges)
});
...

Finding Hard Edges

hard edges
Hard edge is determined by the angle between 2 face normals at the shared edge

A class function Edge.generateHardEdges() will return only hard edges from the given edge list and angle. Each edge object contains 2 normals of 2 adjacent faces. If the angle between 2 face normals is greater than the given value, it is considered as a hard edge. The angle is calculated by the inner product of 2 face normals.
angle between 2 normals

The following code is generating the hard edges where the angle is greater than or equal to 90 degree.


// global var
let gl = {};
...

// load OBJ file
gl.obj = new ObjModel();
gl.obj.read("cube.obj").then(obj =>
{
    // convert vertices to an array of Vector3 objects
    let vertices = ObjModel.toVertices(obj);

    // find edges from vertex list
    let edges = Edge.generateEdges(vertices);

    // find hard edges with 90 degree 
    let hardEdges = Edge.generateHardEdges(edges, 90);

    // copy hard edges to VBO
    gl.vbo = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, gl.vbo);
    let vboData = Edge.toFloat32Array(hardEdges);
    gl.bufferData(gl.ARRAY_BUFFER, vboData, gl.STATIC_DRAW);
});
...

Example

This example is to find all edges and hard edge lines from an OBJ model. You can slide the hard edge angle to determine the hard edges. The angle represents the sharpness at the shared edges, a greater angle is shaper edge.

Note that some edges are not shown when you render it with the surface together. It is because of failing the depth test at the same Z value. One solution to avoid this depth testing issue is to offset the Z value of the edge lines slightly forward to the view. Please see gles_flatOffset.vert shader for details.


decoration Fullscreen Demo: test_edge.html
decoration GitHub Repo: test_edge.html

←Back
 
Hide Comments
comments powered by Disqus