gpt4 book ai didi

c# - 当我是 "drawing"线时,如何将点平均分配到 LineRenderer 的宽度曲线?

转载 作者:行者123 更新时间:2023-12-05 04:41:47 24 4
gpt4 key购买 nike

我正在使用线渲染器创建一个“绘图”应用程序,现在我正尝试在 LineRenderer 上使用宽度曲线启用笔压。问题是 AnimationCurve 的“时间”值(水平轴)从 0 归一化为 1,所以每次添加位置时我不能只在它的末尾添加一个值。除非有我不知道的功能,否则我能想到的唯一解决方案是找到一种方法,在我画线时将所有数百个以前的值按精确百分比移动,并在添加位置时执行此操作。这似乎过分了。

我在这里不知所措。

这是我用笔绘制时每帧添加点的基本线。

curve.AddKey(1.0f, penPressureValue);

“1.0f”是曲线上的位置(1 是最后一个),所以这只是在每一帧的末尾添加一个点,在我绘制时改变整条线的宽度。

最佳答案

不幸的是,我认为没有一种方法可以在某种程度上不离奇且性能高。

当然你可以计算它(假设 LineRenderer 从位置计数 = 0 开始),例如

public LineRenderer line;
private int positionCount;
private float totalLengthOld;

private void AddPoint(Vector3 position, float width)
{
// increase the position count by one
positionCount++;

// set the count back to the line
line.positionCount = positionCount;

// add our new point
line.SetPosition(positionCount - 1, position);

// now get the current width curve
var curve = line.widthCurve;

// Is this the beginning of the line?
if (positionCount == 1)
{
// First point => simply set the first keyframe
curve.MoveKey(0, new Keyframe(0f, width));
}
else
{
// otherwise get all positions
var positions = new Vector3[positionCount];
line.GetPositions(positions);

// sum up the distances between positions to obtain the length of the line
var totalLengthNew = 0f;
for (var i = 1; i < positionCount; i++)
{
totalLengthNew += Vector3.Distance(positions[i - 1], positions[i]);
}

// calculate the time factor we have to apply to all already existing keyframes
var factor = totalLengthOld / totalLengthNew;

// then store for the next added point
totalLengthOld = totalLengthNew;

// now move all existing keys which are currently based on the totalLengthOld to according positions based on the totalLengthNew
// we can skip the first one as it will stay at 0 always
var keys = curve.keys;
for (var i = 1; i < keys.Length; i++)
{
var key = keys[i];
key.time *= factor;

curve.MoveKey(i, key);
}

// add the new last keyframe
curve.AddKey(1f, width);
}

// finally write the curve back to the line
line.widthCurve = curve;
}

只是一个小演示

public class Example : MonoBehaviour
{
public LineRenderer line;
public Transform pen;
[Range(0.01f, 0.5f)] public float width;
public float drawThreshold = 0.1f;

private int positionCount;
private float totalLengthOld;
private Vector3 lastPenPosition;

private void Awake()
{
line = GetComponent<LineRenderer>();
line.useWorldSpace = true;
line.positionCount = 0;

lastPenPosition = pen.position;
}

private void Update()
{
// just for the demo simply ping-pong the width over time
width = Mathf.Lerp(0.01f, 0.8f, Mathf.PingPong(Time.time, 1f));

var currentPenPosition = pen.position;

if (Vector3.Distance(lastPenPosition, currentPenPosition) >= drawThreshold)
{
lastPenPosition = currentPenPosition;
AddPoint(currentPenPosition, width);
}
}

private void AddPoint(Vector3 position, float width)
{
positionCount++;

line.positionCount = positionCount;
line.SetPosition(positionCount - 1, position);

var curve = line.widthCurve;

if (positionCount == 1)
{
curve.MoveKey(0, new Keyframe(0f, width));
}
else
{
var positions = new Vector3[positionCount];
line.GetPositions(positions);

var totalLengthNew = 0f;
for (var i = 1; i < positionCount; i++)
{
totalLengthNew += Vector3.Distance(positions[i - 1], positions[i]);
}

var factor = totalLengthOld / totalLengthNew;

totalLengthOld = totalLengthNew;

var keys = curve.keys;
for (var i = 1; i < keys.Length; i++)
{
var key = keys[i];
key.time *= factor;

curve.MoveKey(i, key);
}

curve.AddKey(1f, width);
}

line.widthCurve = curve;
}
}

enter image description here


当然,这会在一定数量的分数后达到性能极限。但我认为目前您可以使用 LineRenderer 到此为止。否则,LineRenderer 可能不是正确的绘图工具。

您当然可以使用技巧,在一定数量的点后使用 LineRenderer.BakeMesh 将现有线烘焙到单独的固定网格中并以最后一点作为起点开始一条新的新线。

在这种情况下,只有线的未烘焙部分实际上会受到宽度曲线键移动的影响。

有点像例如

public int meshBakeThreshold = 50;

private void AddPoint(Vector3 position, float width)
{
......

if (positionCount >= meshBakeThreshold)
{
CreateSnapShotAndStartOver(position, width);
}
}

private void CreateSnapShotAndStartOver(Vector3 position, float width)
{
// create a new GameObject that will receive the line snapsho mesh
var snapshotObject = new GameObject("LineSnapshot", typeof(MeshRenderer), typeof(MeshFilter));

// set the material
var renderer = snapshotObject.GetComponent<Renderer>();
renderer.material = line.material;

// bake and set the mesh
var meshFilter = snapshotObject.GetComponent<MeshFilter>();
var mesh = new Mesh();
line.BakeMesh(mesh, Camera.main, true);
meshFilter.mesh = mesh;

// start with a new line at the same current position
positionCount = 0;
AddPoint(position, width);
}

enter image description here

您需要稍微调整一下阈值,50 可能有点低,只是用于演示。您希望在迭代所有关键帧和烘焙网格的性能成本之间找到平衡;)

关于c# - 当我是 "drawing"线时,如何将点平均分配到 LineRenderer 的宽度曲线?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69982636/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com