赞
踩
以上文字用人话来讲:
Vectrosity自2010年横空出世以来——牢记使命不忘初心,迄今已成为最为高端、大气、上档次的画线工具。
特点: Vectrosity是一个非开源的商业包。
本文讨论的内容:基于Vectrosity包进行画线涂鸦
asset store中的Vectrosity包。
【1】按下鼠标左键开始单笔涂鸦,松开鼠标左键则停止本笔涂鸦。
【2】再次按下则开始画另一笔涂鸦。
【3】每一笔涂鸦信息用Vectrosity中的一个line对象来保存
【4】涂鸦的时候,取点的位置是屏幕鼠标位置【2D取xy,3D自动取xy同时自动加一个固定的z】
【5】用Vectrosity来显示所有的line对象
// The DrawLinesTouch script adapted to work with mouse input, with the option for 3D or 2D lines using UnityEngine; using Vectrosity; using System.Collections.Generic; /// <summary> /// 屏幕涂鸦: /// 【1】按下鼠标左键开始单笔涂鸦,松开鼠标左键则停止本笔涂鸦。 /// 【2】再次按下则开始画另一笔涂鸦。 /// 【3】每一笔涂鸦信息用Vectrosity中的一个line对象来保存 /// 【4】涂鸦的时候,取点的位置是屏幕鼠标位置【2D取xy,3D自动取xy同时自动加一个固定的z】 /// 【5】用Vectrosity来显示所有的line对象 /// </summary> public class DrawLinesMouseV2 : MonoBehaviour { public Texture2D lineTex; public int maxPoints = 5000; public float lineWidth = 4.0f; public int minPixelMove = 5; // Must move at least this many pixels per sample for a new segment to be recorded public bool useEndCap = false; public Texture2D capLineTex; public Texture2D capTex; public float capLineWidth = 20.0f; // If line3D is true, the line is drawn in the scene rather than as an overlay. Note that in this demo, the line will look the same // in the game view either way, but you can see the difference in the scene view. public bool line3D = false; public float distanceFromCamera = 1.0f; /// <summary> /// line的对象 /// </summary> private VectorLine line; /// <summary> /// 所有的线:有很多很多根线 /// </summary> private List<VectorLine> lines = new List<VectorLine>(); private Vector3 previousPosition; private int sqrMinPixelMove; private bool canDraw = false; /// <summary> /// line被创建了?,没被创建的话,按下鼠标左键则会创建一根线。 /// </summary> private bool hasCreated; private float useLineWidth; private Texture2D tex; void Start() { if (useEndCap) { VectorLine.SetEndCap("RoundCap", EndCap.Mirror, capLineTex, capTex); tex = capLineTex; useLineWidth = capLineWidth; } else { tex = lineTex; useLineWidth = lineWidth; } // Used for .sqrMagnitude, which is faster than .magnitude sqrMinPixelMove = minPixelMove * minPixelMove; } void Update() { //获取鼠标位置 var newPoint = GetMousePos(); // 按下鼠标左键,则开始一笔新的涂鸦(对应为一根新的线)。Mouse button clicked, so start a new line if (Input.GetMouseButtonDown(0)) { if (!hasCreated) { if (line3D) { line = new VectorLine("DrawnLine3D", new List<Vector3>(), tex, useLineWidth, LineType.Continuous, Joins.Weld); } else { line = new VectorLine("DrawnLine", new List<Vector2>(), tex, useLineWidth, LineType.Continuous, Joins.Weld); } line.endPointsUpdate = 2; // Optimization for updating only the last couple points of the line, and the rest is not re-computed if (useEndCap) { line.endCap = "RoundCap"; } hasCreated = true; } if (line3D) { line.points3.Clear(); line.Draw3D(); } else { line.points2.Clear(); //line.Draw(); //显示多笔涂鸦信息 if(! lines.Contains(line)) lines.Add(line); lines.ForEach(line=>line.Draw()); } previousPosition = Input.mousePosition; if (line3D) { line.points3.Add(newPoint); } else { line.points2.Add(newPoint); } canDraw = true; } // Mouse button held down and mouse has moved far enough to make a new point //鼠标左键一直按着,并且鼠标在移动,新点与上一个点距离达到一定程度时,该点才能被取样 else if (Input.GetMouseButton(0) && (Input.mousePosition - previousPosition).sqrMagnitude > sqrMinPixelMove && canDraw) { previousPosition = Input.mousePosition; int pointCount; if (line3D) { line.points3.Add(newPoint); pointCount = line.points3.Count; line.Draw3D(); } else { line.points2.Add(newPoint); pointCount = line.points2.Count; line.Draw(); if (pointCount >= maxPoints) { canDraw = false; } } } //松开鼠标左键,本次画线结束,hasCreated置空,后面再次按下的时候,可以创建新的线 if (Input.GetMouseButtonUp(0)) { hasCreated = false; } Vector3 GetMousePos() { var p = Input.mousePosition; if (line3D) { p.z = distanceFromCamera; return Camera.main.ScreenToWorldPoint(p); } return p; } } }
/***********************************************************
*实现原理:
* 【0】使用的包asset store 中的Vectrosity
* 【1】从摄像机发射一条射线,方向指向屏幕的鼠标位置
* 【2】白板Plane上设置一个BoxCollider,把BoxCollider扩大一点,
* 特别是靠近相机的一边,要覆盖白板,让字显示在白板前面,而不是白板上【不然模型重叠会闪烁】
* 【3】每帧刷新射线,捕捉在白板上的碰撞点
* 【4】鼠标按下时开始涂鸦,弹起时完成一笔涂鸦,调用Vectrosity把该笔涂鸦的点显示出来
* 【5】调用Vectrosity显示每一笔涂鸦的点
***********************************************************/
using UnityEngine; using Vectrosity; //asset store search [Vectrosity] using System.Collections.Generic; /// <summary> /// 白板涂鸦 /// 白板——就是一个3D Plane,增加一个BOX碰撞体包围框 /// </summary> public class DrawOnWhiteBoard : MonoBehaviour { /*********************************************************** *实现原理: * 【0】使用的包asset store 中的Vectrosity * 【1】从摄像机发射一条射线,方向指向屏幕的鼠标位置 * 【2】白板Plane上设置一个BoxCollider,把BoxCollider扩大一点, * 特别是靠近相机的一边,要覆盖白板,让字显示在白板前面,而不是白板上【不然模型重叠会闪烁】 * 【3】每帧刷新射线,捕捉在白板上的碰撞点 * 【4】鼠标按下时开始涂鸦,弹起时完成一笔涂鸦,调用Vectrosity把该笔涂鸦的点显示出来 * 【5】调用Vectrosity显示每一笔涂鸦的点 ***********************************************************/ /// <summary> /// 主相机 /// </summary> public Camera camera; /// <summary> /// 白板的名字 /// </summary> public string whiteBoardName; public Texture2D lineTex; public int maxPoints = 5000; public float lineWidth = 4.0f; public int minPixelMove = 5; // Must move at least this many pixels per sample for a new segment to be recorded public bool useEndCap = false; public Texture2D capLineTex; public Texture2D capTex; public float capLineWidth = 20.0f; // If line3D is true, the line is drawn in the scene rather than as an overlay. Note that in this demo, the line will look the same // in the game view either way, but you can see the difference in the scene view. public bool line3D = false; public float distanceFromCamera = 1.0f; /// <summary> /// line的对象:单笔涂鸦的信息 /// </summary> private VectorLine line; /// <summary> /// 所有的线:很多根线,多笔涂鸦信息 /// </summary> private List<VectorLine> lines = new List<VectorLine>(); private Vector3 previousPosition; private int sqrMinPixelMove; private bool canDraw = false; /// <summary> /// line被创建了?,没被创建的话,按下鼠标左键则会创建一根线。 /// </summary> private bool hasCreated; private float useLineWidth; private Texture2D tex; // Start is called before the first frame update void Start() { if (useEndCap) { VectorLine.SetEndCap("RoundCap", EndCap.Mirror, capLineTex, capTex); tex = capLineTex; useLineWidth = capLineWidth; } else { tex = lineTex; useLineWidth = lineWidth; } // Used for .sqrMagnitude, which is faster than .magnitude sqrMinPixelMove = minPixelMove * minPixelMove; } // Update is called once per frame void Update() { Vector3 newPoint = new Vector3(); bool canWrite = false; //鼠标按下在白板上涂鸦时,为true //相机激发射线穿过屏幕鼠标 RaycastHit hit; Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); if (Physics.Raycast(ray, out hit, Mathf.Infinity)) { //鼠标【碰到】白板 if (hit.transform.name == whiteBoardName) { newPoint = hit.point; canWrite = true; } } // if (canWrite) { // 按下鼠标左键,则开始一根新的线。 if (Input.GetMouseButtonDown(0)) { if (!hasCreated) //本笔涂鸦的线存在,则不创建,不然要创建新的line { if (line3D) { line = new VectorLine("DrawnLine3D", new List<Vector3>(), tex, useLineWidth, LineType.Continuous, Joins.Weld); } else { line = new VectorLine("DrawnLine", new List<Vector2>(), tex, useLineWidth, LineType.Continuous, Joins.Weld); } line.endPointsUpdate = 2; // Optimization for updating only the last couple points of the line, and the rest is not re-computed if (useEndCap) { line.endCap = "RoundCap"; } hasCreated = true; } if (line3D) { line.points3.Clear(); if (!lines.Contains(line)) lines.Add(line); lines.ForEach(line => line.Draw3D()); } else { line.points2.Clear(); if (!lines.Contains(line)) lines.Add(line); lines.ForEach(line => line.Draw()); } previousPosition = Input.mousePosition; if (line3D) { line.points3.Add(newPoint); } else { line.points2.Add(newPoint); } canDraw = true; } // Mouse button held down and mouse has moved far enough to make a new point //鼠标左键一直按着,并且鼠标在移动,新点与上一个点距离达到一定程度时,该点才能被取样 else if (Input.GetMouseButton(0) && (Input.mousePosition - previousPosition).sqrMagnitude > sqrMinPixelMove && canDraw) { previousPosition = Input.mousePosition; int pointCount; if (line3D) { line.points3.Add(newPoint); pointCount = line.points3.Count; line.Draw3D(); } else { line.points2.Add(newPoint); pointCount = line.points2.Count; line.Draw(); if (pointCount >= maxPoints) { canDraw = false; } } } //松开鼠标左键,本笔涂鸦的画线结束,hasCreated置空,后面再次按下的时候,可以创建新一笔的涂鸦 if (Input.GetMouseButtonUp(0)) { hasCreated = false; } } Vector3 GetMousePos() { var p = Input.mousePosition; if (line3D) { p.z = distanceFromCamera; return Camera.main.ScreenToWorldPoint(p); } return p; } } }
实际上,要能够愉快的涂鸦,还得增加许多功能,比如全部清屏,部分擦除,颜色设置等等。
如果单纯只是涂鸦的话,用texture的setpixels可能更“勤俭节约”。
备注:本案例只在Win10 + Unity Editor 环境中测试过
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。