Drawing Board with Line renderer and XRITK

Hello,
I’m implementing a drawing board in VR, taking inspiration from this tutorial Oculus Hand Interaction: Drawing in VR. I’ve done some modifications/optimization and came down to this for the marker:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class InkGenerator : MonoBehaviour
{
    // Variable to store the prefab for the ink
    [SerializeField] private GameObject inkPrefab;
    // Variable to store the transform of the pencil
    [SerializeField] private Transform pencilTransform;
    // Variable to store the transform of the paper
    [SerializeField] private Transform paperTransform;
    // Variable to store the offset of the pencil
    [SerializeField] private Vector3 pencilOffset;
    // Variable to store the parent transform for the ink objects
    [SerializeField] private Transform parent;

    // Variable to store the InkTracer component
    private InkTracer ink;
    // Variable to keep track of whether the player is touching the whiteboard
    private bool isTouching = false;
    // Variable to store the newly created ink object
    private GameObject newInk = null;
    // Coroutine for generating ink
    private Coroutine generateInkCoroutine;

    // Called when another collider enters this object's trigger zone
    private void OnTriggerEnter(Collider otherObject)
    {
        // Check if the other collider has the tag "Whiteboard"
        if (otherObject.CompareTag("Whiteboard"))
        {
            // Set isTouching to true
            isTouching = true;
            // Start the coroutine to generate ink
            generateInkCoroutine = StartCoroutine(GenerateInk());
        }
    }

    // Called when another collider exits this object's trigger zone
    private void OnTriggerExit(Collider otherObject)
    {
        // Check if the other collider has the tag "Whiteboard"
        if (otherObject.CompareTag("Whiteboard"))
        {
            // Set isTouching to false
            isTouching = false;
            // Check if there is a new ink object
            if (newInk != null)
            {
                // Stop the coroutine for generating ink
                StopCoroutine(generateInkCoroutine);
                // Set newInk to null
                newInk = null;
            }
        }
    }

    // Coroutine for generating ink
    private IEnumerator GenerateInk()
    {
        // Continue looping while the player is touching the whiteboard
        while (isTouching)
        {
            // Check if there is no new ink object
            if (newInk == null)
            {
                // Instantiate a new ink object from the prefab
                newInk = Instantiate(inkPrefab);
                // Get the InkTracer component from the new ink object
                ink = newInk.GetComponent<InkTracer>();
            }

            // Check if there is a new ink object
            if (newInk != null)
            {
                // Calculate the position for the ink based on the pencil and paper positions, and the pencil offset
                Vector3 pos = new Vector3(pencilTransform.position.x, paperTransform.position.y, pencilTransform.position.z);
                // Update the line renderer of the ink with the calculated position
                ink.UpdateLineRenderer(pos + pencilOffset);
            }

            // Wait for the next frame
            yield return null;
        }
    }
}

and this for the ink component that is instantiated everytime the marker collider is triggered, hence creating a line at the given position:

using System.Collections.Generic;
using UnityEngine;
using System.Linq;

[RequireComponent(typeof(LineRenderer))]
public class InkTracer : MonoBehaviour
{
    // Variable to store the LineRenderer component
    private LineRenderer lineRenderer = null;
    // List to store the points of the ink stroke
    private List<Vector3> points = new List<Vector3>();
    // Threshold for determining if a new point should be added to the line renderer
    [SerializeField] private float drawingThreshold = 0.001f;

    // Called when the object is initialized
    private void Awake()
    {
        // Get the LineRenderer component attached to this object
        lineRenderer = GetComponent<LineRenderer>();
    }

    // Method to update the LineRenderer with a new position
    public void UpdateLineRenderer(Vector3 newPosition)
    {
        // Debug.Log(newPosition);
        // Check if adding a new point is required based on the drawing threshold
        if (IsUpdateRequired(newPosition))
        {
            // Add the new position to the list of points
            points.Add(newPosition);
            // Set the position count of the LineRenderer to match the number of points
            lineRenderer.positionCount = points.Count;
            // Set the position of the last added point in the LineRenderer
            lineRenderer.SetPosition(points.Count - 1, newPosition);
        }
    }

    // Method to determine if adding a new point is required based on the drawing threshold
    private bool IsUpdateRequired(Vector3 position)
    {
        // Check if there are no points yet
        if (points.Count == 0)
            return true;
        // Check if the distance between the last point and the new position is greater than the drawing threshold
        return Vector3.Distance(points.Last(), position) > drawingThreshold;
    }
}

Attached is my Line Renderer component setup.

Right now, everytime i try to draw, the drawing is like squished in front of the board, instead of in front of and facing me, like when writing on a real board.
Here is a video showing the result:

I don’t really know what is wrong here, so any help would be much appreciated. Thanks !

Try
InkGenerator Script:

```csharp
**using System.Collections;
using UnityEngine;

public class InkGenerator : MonoBehaviour
{
[SerializeField] private GameObject inkPrefab; // Variable to store the prefab for the ink
[SerializeField] private Transform pencilTransform; // Variable to store the transform of the pencil
[SerializeField] private Transform paperTransform; // Variable to store the transform of the paper
[SerializeField] private Vector3 pencilOffset; // Variable to store the offset of the pencil
[SerializeField] private Transform parent; // Variable to store the parent transform for the ink objects

private InkTracer ink; // Variable to store the InkTracer component
private bool isTouching = false; // Variable to keep track of whether the player is touching the whiteboard
private GameObject newInk = null; // Variable to store the newly created ink object
private Coroutine generateInkCoroutine; // Coroutine for generating ink

private void OnTriggerEnter(Collider otherObject)
{
    if (otherObject.CompareTag("Whiteboard"))
    {
        isTouching = true; // Set isTouching to true
        generateInkCoroutine = StartCoroutine(GenerateInk()); // Start the coroutine to generate ink
    }
}

private void OnTriggerExit(Collider otherObject)
{
    if (otherObject.CompareTag("Whiteboard"))
    {
        isTouching = false; // Set isTouching to false
        if (newInk != null)
        {
            StopCoroutine(generateInkCoroutine); // Stop the coroutine for generating ink
            newInk = null; // Set newInk to null
        }
    }
}

private IEnumerator GenerateInk()
{
    while (isTouching)
    {
        if (newInk == null)
        {
            newInk = Instantiate(inkPrefab, parent); // Instantiate ink as child of parent
            ink = newInk.GetComponent<InkTracer>(); // Get the InkTracer component from the new ink object
        }

        if (newInk != null)
        {
            Vector3 pos = paperTransform.position + pencilTransform.forward * 0.1f; // Calculate ink position based on paper and pencil orientation
            ink.UpdateLineRenderer(pos + pencilOffset); // Update the line renderer of the ink with the calculated position
        }

        yield return null;
    }
}

}**
```
Moved the comment “// Instantiate ink as child of parent” to indicate the addition of instantiating the ink as a child of the parent object.
- Moved the comment “// Instantiate ink as child of parent” to indicate the addition of instantiating the ink as a child of the parent object.

  • Added the comment “// Calculate ink position based on paper and pencil orientation” to clarify the calculation of the ink position based on the paper and pencil orientations

InkTracer Script

```csharp
**using System.Collections.Generic;
using UnityEngine;

[RequireComponent(typeof(LineRenderer))]
public class InkTracer : MonoBehaviour
{
private LineRenderer lineRenderer = null; // Variable to store the LineRenderer component
private List points = new List(); // List to store the points of the ink stroke
[SerializeField] private float drawingThreshold = 0.001f; // Threshold for determining if a new point should be added to the line renderer

private void Awake()
{
    lineRenderer = GetComponent<LineRenderer>(); // Get the LineRenderer component attached to this object
}

public void UpdateLineRenderer(Vector3 newPosition)
{
    if (IsUpdateRequired(newPosition)) // Check if adding a new point is required based on the drawing threshold
    {
        points.Add(newPosition); // Add the new position to the list of points
        lineRenderer.positionCount = points.Count; // Set the position count of the LineRenderer to match the number of points
        lineRenderer.SetPosition(points.Count - 1, newPosition); // Set the position of the last added point in the LineRenderer
    }
}

private bool IsUpdateRequired(Vector3 position)
{
    if (points.Count == 0)
        return true; // Check if there are no points yet
    return Vector3.Distance(points[points.Count - 1], position) > drawingThreshold; // Check if the distance between the last point and the new position is greater than the drawing threshold
}

}**
```

Thanks ! I’ve tried your solution, but it still seems that there a miscalculation somewhere. I was thinking that i should maybe get the contact points transform when colliding on the board and use them to update the Line Renderer component… Have to give it a try but do you think it could work ? I’m open to any suggestion !