2

I am getting the Mouse-Input to draw a line onto a Texture from point A to point B. I've realized that I am not hitting every pixel, so moving my Mouse from the very left to the very right of the screen, it will skip some values, leading to gaps. When I move my mouse slowly it get's better.

I am getting the mouse position using:

var viewPortPosition = Camera.main.ScreenToViewportPoint (Input.mousePosition);

enter image description here

Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
user1767754
  • 23,311
  • 18
  • 141
  • 164

2 Answers2

1

What I've ended up doing is running the so far collected mouse Positions through a Bresenham's Line Drawing function to rasterize the lines.

Source:

    public void line(Vector2 pointA, Vector2 pointB, Texture2D texture) {
    int x = (int)pointA.x;
    int y = (int)pointA.y;

    int x2 = (int)pointB.x;
    int y2 = (int)pointB.y;

    int w = x2- x ;
    int h = y2 - y;
    int dx1 = 0, dy1 = 0, dx2 = 0, dy2 = 0 ;
    if (w<0) dx1 = -1 ; else if (w>0) dx1 = 1 ;
    if (h<0) dy1 = -1 ; else if (h>0) dy1 = 1 ;
    if (w<0) dx2 = -1 ; else if (w>0) dx2 = 1 ;
    int longest = Math.Abs(w) ;
    int shortest = Math.Abs(h) ;
    if (!(longest>shortest)) {
        longest = Math.Abs(h) ;
        shortest = Math.Abs(w) ;
        if (h<0) dy2 = -1 ; else if (h>0) dy2 = 1 ;
        dx2 = 0 ;            
    }
    int numerator = longest >> 1 ;
    for (int i=0;i<=longest;i++) {
        texture.SetPixel (x, y, Color.red);

        numerator += shortest ;
        if (!(numerator<longest)) {
            numerator -= longest ;
            x += dx1 ;
            y += dy1 ;
        } else {
            x += dx2 ;
            y += dy2 ;
        }
    }
}

enter image description here

Original Source of Code but modified for Unity C#: All cases covered Bresenham's line-algorithm

user1767754
  • 23,311
  • 18
  • 141
  • 164
0

If you want to draw a line I suggest you using the line renderer. Assuming you implemented the code in the Update() function - this is called every frame rendered. So even though your movement is quite slow, obviously it is already sufficient enough to leave gaps in your drawn lines.

Below is some code from this link which should work fine for you:

using System.Collections.Generic;
 using UnityEngine;

 [RequireComponent(typeof(LineRenderer))]
 public class LineRendererTest : MonoBehaviour
 {
     List<Vector3> linePoints = new List<Vector3>();
     LineRenderer lineRenderer;
     public float startWidth = 1.0f;
     public float endWidth = 1.0f;
     public float threshold = 0.001f;
     Camera thisCamera;
     int lineCount = 0;

     Vector3 lastPos = Vector3.one * float.MaxValue;


     void Awake()
     {
         thisCamera = Camera.main;
         lineRenderer = GetComponent<LineRenderer>();
     }

     void Update()
     {
         Vector3 mousePos = Input.mousePosition;
         mousePos.z = thisCamera.nearClipPlane;
         Vector3 mouseWorld = thisCamera.ScreenToWorldPoint(mousePos);

         float dist = Vector3.Distance(lastPos, mouseWorld);
         if(dist <= threshold)
             return;

         lastPos = mouseWorld;
         if(linePoints == null)
             linePoints = new List<Vector3>();
         linePoints.Add(mouseWorld);

         UpdateLine();
     }


     void UpdateLine()
     {
         lineRenderer.SetWidth(startWidth, endWidth);
         lineRenderer.SetVertexCount(linePoints.Count);

         for(int i = lineCount; i < linePoints.Count; i++)
         {
             lineRenderer.SetPosition(i, linePoints[i]);
         }
         lineCount = linePoints.Count;
     }
Fabian Bigler
  • 10,403
  • 6
  • 47
  • 70
  • I'm aware of the LineRenderer, and I've used it before and was actually thinking as well using the LineRenderer to parametrize and rasterize a curve onto a texture. The reason I don't want to go with the LineRenderer approach is, that at one point I will run out of memory. Painting on a texture will give me always a fixed canvas. – user1767754 Jul 09 '17 at 18:21
  • @user1767754 You can easily implement to avoid running out of memory in reusing the same memory for example by using a buffer. So I would still go for the LineRenderer. – Fabian Bigler Jul 09 '17 at 18:24
  • You can reuse the same memory if you don't need the memory anymore. But when you want to constantly draw and keep the lines, it can be tricky. A problem I won't have if I have a fixed canvas. I probably have to go for a Hybrid solution of drawing the lines with the Linerenderer, splatting them onto a texture when done. Still i am confused why the mouse positions are skipped. – user1767754 Jul 09 '17 at 18:38