Jan
15
2012

Xiaolin Wu’s line algorithm to Unity Javascript

Converted this function to Unity3D Javascript : http://en.wikipedia.org/wiki/Xiaolin_Wu%27s_line_algorithm
(Still has few bugs left..see that vertical line in screenshot..)

Webplayer:
coming later
Can anyone find the error in this code? Why doesnt it draw vertical lines..?
!note, couple lines are commented out, swapping x<>y,
if I enable that, line position doesnt match with mouse click.

// Xiaolin Wu's line algorithm - converted to unity- mgear - http://unitycoder.com/blog
// original source: http://en.wikipedia.org/wiki/Xiaolin_Wu%27s_line_algorithm
// *attach this scrip to a plane, then draw with mouse: click startpoint, click endpoint

private var texture:Texture2D;
public var texture_width:int=256;
public var texture_height:int=256;
private var point1:boolean = false;
private var point2:boolean = false;
private var startpoint:Vector2;
private var endpoint:Vector2;

function Start()
{
texture = new Texture2D (texture_width, texture_height);
renderer.material.mainTexture = texture;
}

function Update()
{
// draw lines with mouse
if (Input.GetMouseButtonDown(0))
{
var ray:Ray = Camera.main.ScreenPointToRay(Input.mousePosition);
var hit:RaycastHit;
if (Physics.Raycast(ray,hit, 100))
{
if (!point1)
{
pixelUV = hit.textureCoord;
pixelUV.x *= texture.width;
pixelUV.y *= texture.height;
startpoint = Vector2(pixelUV.x, pixelUV.y);
point1=true;

print (startpoint);
}else{
pixelUV = hit.textureCoord;
pixelUV.x *= texture.width;
pixelUV.y *= texture.height;
endpoint = Vector2(pixelUV.x, pixelUV.y);
point1=false;
drawLine(startpoint.x,startpoint.y,endpoint.x,endpoint.y);
print (endpoint);
}
}
}
}


// the actual code from wiki :

function plot(x, y, c)
{
texture.SetPixel (x,y,Color(c,c,c,1));
}

function ipart(x)
{
return Mathf.Floor(x);
}

function round(x)
{
return Mathf.RoundToInt(x+0.5);
}

function fpart(x)
{
return x - ipart(x);
}

function rfpart(x)
{
return 1 - fpart(x);
}

function drawLine(x1,y1,x2,y2)
{
var dx:float = x2 - x1;
var dy:float = y2 - y1;
if (Mathf.Abs(dx) < Mathf.Abs(dy))
{
// ** Commented these out, I dont get it how / why x & y should be swapped..?
//      tmp = x1; x1=x2; x2=tmp;
//      tmp = y1; y1=y2; y2=tmp;
//      tmp = dx; dx=dy; dy=tmp;
}
if (x2 < x1)
{
tmp = x1; x1=x2; x2=tmp;
tmp = y1; y1=y2; y2=tmp;
}
gradient = dy / dx;

// handle first endpoint
xend = round(x1);
yend = y1 + gradient * (xend - x1);
xgap = rfpart(x1 + 0.5);
xpxl1 = xend;  // this will be used in the main loop
ypxl1 = ipart(yend);
plot(xpxl1, ypxl1, rfpart(yend) * xgap);
plot(xpxl1, ypxl1 + 1, fpart(yend) * xgap);
intery = yend + gradient; // first y-intersection for the main loop

// handle second endpoint
xend = round (x2);
yend = y2 + gradient * (xend - x2);
xgap = fpart(x2 + 0.5);
xpxl2 = xend;  // this will be used in the main loop
ypxl2 = ipart (yend);
plot (xpxl2, ypxl2, rfpart (yend) * xgap);
plot (xpxl2, ypxl2 + 1, fpart (yend) * xgap);

// main drawing loop
for (x=xpxl1+1;x<xpxl2-1;x++)
{
plot (x, ipart (intery), rfpart (intery));
plot (x, ipart (intery) + 1, fpart (intery));
intery = intery + gradient;
}
texture.Apply();
}

1 Comment + Add Comment

  • The reason to swap x and y is that you want the algorithm to be running down a gradient -1<=y/x<=+1, otherwise it'll skip pixels along the line (as is happening without it). By swapping them, you effectively guarantee instead that -1<=x/y<=+1. However, you then have an algorithm that's running along the y axis in unit steps and accumulating the (smaller in magnitude) x- increment, instead of accumulating multiples of the gradient as you move along the x-axis in unit steps (the unswapped action). As a result, and if you swap them, each and every call to plot needs to have its first two arguments swapped over as well. (More formally, x* is y*, so need to be the second arguments in the calls to plot; the calculated/accumulated 'y-coordinates' produced by the algorithm are actually the x-coordinates so should be the first arguments.)

    AL

Leave a comment

Connect

Twitter View LinkedIn profile Youtube Youtube Join Discord Twitch

UnityLauncherPro

Get UnityLauncherPRO and work faster with Unity Projects!
*free unity hub alternative

@unitycoder_com

Subscribe to Blog via Email

Enter your email address to subscribe to this blog and receive notifications of new posts by email.