2

I'm relatively new to JavaScript and to get a grip on it I've been working on a 3D engine and I stumbled on something odd. When I render a filled mesh with wire-frame disabled, a gap shows up between my triangles.

Here's an example:

// vertices
var v1 = [40,20];
var v2 = [125,35];
var v3 = [165,105];
var v4 = [35,95];

// draw on screen 1
var canvas = document.getElementById("screen");
var context = canvas.getContext("2d");
triangle(v1,v2,v3,context,true);
triangle(v3,v4,v1,context,true);

// draw on screen 2
var canvas = document.getElementById("screen2");
var context = canvas.getContext("2d");
triangle(v1,v2,v3,context,false);
triangle(v3,v4,v1,context,false);

// draw triangle method
function triangle(v1,v2,v3, context,wireframe)
{
  context.beginPath();
  context.moveTo(v1[0],v1[1]);
  context.lineTo(v2[0],v2[1]);
  context.lineTo(v3[0],v3[1]);
  context.lineTo(v1[0],v1[1]);
  context.closePath();
  context.fillStyle = "#333";
  context.fill();
  if (wireframe)
  {
    context.strokeStyle = "#0f3";
    context.stroke();
  }
}
body
{
 background-color: #ddd;
}
canvas 
{
  border:2px solid #000;
}
<canvas id="screen" width="200" height="150" ></canvas>
<canvas id="screen2" width="200" height="150"></canvas>

In essence, the two polygons don't seem to connect properly.

  • Making the wire-frame the same colour as triangle is not a solution. I want to apply a texture without seeing the edge.
  • Drawing connected polygons isn't a solution, each triangle may have its own texture transformation.
  • Should I overdraw triangles to close the gaps?
  • Is this an Anti-Aliasing issue?

Thanks in advance.

enter image description here Above: Shows gap between triangles when the wire-frame has been disabled

UPDATE 9-apr-2017

I've considered various options to solve my issue, including writing a triangle routine. Picture down below. However, drawing two triangles tanks my FPS quite a lot. I need a faster way to put pixels on the canvas, but that's for another post since it's off topic.

However, I think that expanding the triangle half a pixel is a better/faster solution since the fill() method is executed by the browser internally instead of JavaScript.

enter image description here

  • Thanks for the edit, gman. I'm still figuring out how StackOverflow works. –  Apr 05 '17 at 16:58

1 Answers1

0

One solution would be to inflate the triangles by a little bit to fill the gaps. This code inflates by 1%.

I think more ideal would be code that inflates by 0.5 pixels, however, that code would be a little more expensive as it would involve calculating vector lenghts...

// vertices
var v1 = [80,40];
var v2 = [250,70];
var v3 = [230,210];
var v4 = [70,190];

// draw on screen 1
var canvas = document.getElementById("screen");
var context = canvas.getContext("2d");
triangle(v1,v2,v3,context,true);
triangle(v3,v4,v1,context,true);

// draw on screen 2
var canvas = document.getElementById("screen2");
var context = canvas.getContext("2d");
inflateTriangle(v1,v2,v3,context,false);
inflateTriangle(v3,v4,v1,context,false);

// draw triangle method
function inflateTriangle(v1,v2,v3, context,wireframe)
{
 //centre of tri
  xc=(v1[0]+v2[0]+v3[0])/3;
  yc=(v1[1]+v2[1]+v3[1])/3;
  
  //inflate tri by 1%
  x1= xc+(v1[0]-xc)*1.01;
  x2= xc+(v2[0]-xc)*1.01;
  x3= xc+(v3[0]-xc)*1.01;
  y1= yc+(v1[1]-yc)*1.01;
  y2= yc+(v2[1]-yc)*1.01;
  y3= yc+(v3[1]-yc)*1.01;
  


  context.beginPath();
  context.moveTo(x1,y1);
  context.lineTo(x2,y2);
  context.lineTo(x3,y3);
  
  context.closePath();
  context.fillStyle = "#333";
  context.fill();
  if (wireframe)
  {
    context.strokeStyle = "#0f3";
    context.stroke();
  }
}
<body>

<canvas id="screen" width="400" height="300" style="border:2px solid #000;"></canvas>
<canvas id="screen2" width="400" height="300" style="border:2px solid #000;"></canvas>

</body>
Ken
  • 4,367
  • 4
  • 28
  • 41
  • Thanks. I thought about that as well. Calculating vector lengths is no issue. The engine works with vectors internally, so projecting a vector a bit beyond its magnitude is no problem. It's a last resort though. You'd think browsers would have code that fills triangles properly. –  Apr 05 '17 at 17:16
  • I'm accepting this as the solution. You can see my reasoning in an update in my original question. If you have new suggestions, I'd love to hear them. Thanks. –  Apr 09 '17 at 11:23