国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 編程 > C# > 正文

Unity實(shí)現(xiàn)VR中在黑板上寫字效果

2020-01-24 00:04:00
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

本文實(shí)例為大家分享了Unity實(shí)現(xiàn)VR中在黑板上寫字的具體代碼,供大家參考,具體內(nèi)容如下

一、工具

1.開發(fā)用的是Unity 5.6.2版本

2.VR中的物理交互用的是VRTK插件,這個(gè)插件集成了比較好的物理交互功能;

3.HTC Vive

二、概述

實(shí)現(xiàn)的功能: 在一個(gè)白板上,用不同顏色的筆,在白板畫出任何想要的圖形;

因?yàn)橹皇且粋€(gè)初級(jí)篇所以只是用兩個(gè)腳本簡(jiǎn)單的實(shí)現(xiàn),而且并沒(méi)有黑板擦等功能 ,也不能兩個(gè)筆同時(shí)畫畫,這些功能將會(huì)在未來(lái)的升級(jí)篇中寫出;

三、知識(shí)點(diǎn)

其實(shí)這個(gè)功能很簡(jiǎn)單,只是簡(jiǎn)單的運(yùn)用Unity Texure2D類中的兩個(gè)函數(shù):

public void SetPixels32(int x, int y, int blockWidth, int blockHeight, Color32[] colors, int miplevel = 0);

前面4個(gè)參數(shù)相當(dāng)于一個(gè)矩形,x和y就是矩形的左下角的那個(gè)點(diǎn),blockWidth和blockHeight分別是矩形的寬和高,這個(gè)矩形所代表的范圍就是blockWidth*blockHeight個(gè)像素所在的位置,不妨稱這個(gè)矩形范圍為一個(gè)色塊;

colors這個(gè)參數(shù)的大小必須等于blockWidth*blockHeight,因?yàn)檫@個(gè)方法就是給坐標(biāo)(x,y)開始,從左到右,從下到上,一行一行的對(duì)矩形范圍內(nèi)的每個(gè)像素賦值;

也就是把colors[0]~colors[blockWidth - 1]分別賦值到坐標(biāo)為(x,y)~(x + blockWidth,y)的像素,以此類推;

最后一個(gè)參數(shù),因?yàn)槲覀冇玫膱D片把Generate Min Maps這個(gè)選項(xiàng)關(guān)閉了,所以用默認(rèn)的可選參數(shù)0;

public void Apply(bool updateMipmaps = true, bool makeNoLongerReadable = false);

當(dāng)對(duì)圖片改動(dòng)完成以后,需要調(diào)用這個(gè)方法,才能讓改動(dòng)真正的應(yīng)用在圖片上;

四、場(chǎng)景搭建

1.畫板

在場(chǎng)景中建一個(gè)Quad,把它的x和y方向的Scale分別設(shè)置為1.92和1.08(或者其它尺寸);注意這個(gè)Quad一定要用Mesh Collider作為碰撞體,不然到時(shí)候射線獲取的紋理坐標(biāo)有誤,并為它設(shè)置一個(gè)Tag為Board;

2.筆

建一個(gè)尺寸合適的筆,創(chuàng)建一個(gè)空的子物體,命名為SnapPoint,并設(shè)置SnapPoint的Z方向指向筆尖方向,這個(gè)子物體就是,手柄拿筆的位置就是,并且保證筆的姿態(tài)是相當(dāng)于人正常拿筆的樣子;

3.其它

創(chuàng)建一個(gè)放筆的物體,讓筆處于比較好拿的位置;

我的場(chǎng)景中代表畫板的是WhiteBoard下的Board物體;

五、代碼實(shí)現(xiàn)功能

這個(gè)腳本是掛在代表畫板的物體上的:

using System.Linq;using UnityEngine;/// <summary>/// 畫板/// </summary>public class Board : MonoBehaviour{ //當(dāng)畫筆移動(dòng)速度很快時(shí),為了不出現(xiàn)斷斷續(xù)續(xù)的點(diǎn),所以需要對(duì)兩個(gè)點(diǎn)之間進(jìn)行插值,lerp就是插值系數(shù) [Range(0, 1)] public float lerp = 0.05f; //初始化背景的圖片 public Texture2D initailizeTexture; //當(dāng)前背景的圖片 private Texture2D currentTexture; //畫筆所在位置映射到畫板圖片的UV坐標(biāo) private Vector2 paintPos; private bool isDrawing = false;//當(dāng)前畫筆是不是正在畫板上 //離開時(shí)畫筆所在的位置  private int lastPaintX; private int lastPaintY; //畫筆所代表的色塊的大小 private int painterTipsWidth = 30; private int painterTipsHeight = 15; //當(dāng)前畫板的背景圖片的尺寸 private int textureWidth; private int textureHeight; //畫筆的顏色 private Color32[] painterColor; private Color32[] currentColor; private Color32[] originColor; private void Start() { //獲取原始圖片的大小  Texture2D originTexture = GetComponent<MeshRenderer>().material.mainTexture as Texture2D; textureWidth = originTexture.width;//1920  textureHeight = originTexture.height;//1080 //設(shè)置當(dāng)前圖片 currentTexture = new Texture2D(textureWidth, textureHeight, TextureFormat.RGBA32, false, true); currentTexture.SetPixels32(originTexture.GetPixels32()); currentTexture.Apply(); //賦值給黑板 GetComponent<MeshRenderer>().material.mainTexture = currentTexture; //初始化畫筆的顏色 painterColor = Enumerable.Repeat<Color32>(new Color32(255, 0, 0, 255), painterTipsWidth * painterTipsHeight).ToArray<Color32>(); } private void LateUpdate() { //計(jì)算當(dāng)前畫筆,所代表的色塊的一個(gè)起始點(diǎn) int texPosX = (int)(paintPos.x * (float)textureWidth - (float)(painterTipsWidth / 2)); int texPosY = (int)(paintPos.y * (float)textureHeight - (float)(painterTipsHeight / 2)); if (isDrawing) {  //改變畫筆所在的塊的像素值  currentTexture.SetPixels32(texPosX, texPosY, painterTipsWidth, painterTipsHeight, painterColor);  //如果快速移動(dòng)畫筆的話,會(huì)出現(xiàn)斷續(xù)的現(xiàn)象,所以要插值  if (lastPaintX != 0 && lastPaintY != 0)  {  int lerpCount = (int)(1 / lerp);  for (int i = 0; i <= lerpCount; i++)  {   int x = (int)Mathf.Lerp((float)lastPaintX, (float)texPosX, lerp);   int y = (int)Mathf.Lerp((float)lastPaintY, (float)texPosY, lerp);   currentTexture.SetPixels32(x, y, painterTipsWidth, painterTipsHeight, painterColor);  }  }  currentTexture.Apply();  lastPaintX = texPosX;  lastPaintY = texPosY; } else {  lastPaintX = lastPaintY = 0; } } /// <summary> /// 設(shè)置當(dāng)前畫筆所在的UV位置 /// </summary> /// <param name="x"></param> /// <param name="y"></param> public void SetPainterPositon(float x, float y) { paintPos.Set(x, y); } /// <summary> /// 畫筆當(dāng)前是不是在畫畫 /// </summary> public bool IsDrawing { get {  return isDrawing; } set {  isDrawing = value; } } /// <summary> /// 使用當(dāng)前正在畫板上的畫筆的顏色 /// </summary> /// <param name="color"></param> public void SetPainterColor(Color32 color) { if (!painterColor[0].IsEqual(color)) {  for (int i = 0; i < painterColor.Length; i++)  {  painterColor[i] = color;  } } }}public static class MethodExtention{ /// <summary> /// 用于比較兩個(gè)Color32類型是不是同種顏色 /// </summary> /// <param name="origin"></param> /// <param name="compare"></param> /// <returns></returns> public static bool IsEqual(this Color32 origin, Color32 compare) { if (origin.g == compare.g && origin.r == compare.r) {  if (origin.a == compare.a && origin.b == compare.b)  {  return true;  } } return false; }}

下面這個(gè)腳本是掛在畫筆上的:

using UnityEngine;public class Painter : MonoBehaviour{ /// <summary> /// 畫筆的顏色 /// </summary> public Color32 penColor; public Transform rayOrigin; private RaycastHit hitInfo; //這個(gè)畫筆是不是正在被手柄抓著 private bool IsGrabbing; private static Board board;//設(shè)置成類型的成員,而不是類型實(shí)例的成員,因?yàn)樗挟嫻P都是用的同一個(gè)board private void Start() { //將畫筆部件設(shè)置為畫筆的顏色,用于識(shí)別這個(gè)畫筆的顏色 foreach (var renderer in GetComponentsInChildren<MeshRenderer>()) {  if (renderer.transform == transform)  {  continue;  }  renderer.material.color = penColor; } if (!board) {  board = FindObjectOfType<Board>(); }  } private void Update() { Ray r = new Ray(rayOrigin.position, rayOrigin.forward); if (Physics.Raycast(r, out hitInfo, 0.1f)) {  if (hitInfo.collider.tag == "Board")  {  //設(shè)置畫筆所在位置對(duì)應(yīng)畫板圖片的UV坐標(biāo)   board.SetPainterPositon(hitInfo.textureCoord.x, hitInfo.textureCoord.y);  //當(dāng)前筆的顏色  board.SetPainterColor(penColor);  board.IsDrawing = true;  IsGrabbing = true;  } } else if(IsGrabbing) {  board.IsDrawing = false;  IsGrabbing = false; } }}

六、等待完善的地方

1.畫筆所能畫的最小點(diǎn)是有大小的,也就是SetPixels參數(shù)中的blockWidth*blockHeight的大小,當(dāng)這個(gè)畫筆在畫板的邊緣的時(shí)候,那么這個(gè)畫筆所能畫的色塊的矩形范圍就到圖片之外去了,這會(huì)引起未處理異常;

2.同時(shí)只有一個(gè)筆能在畫板上畫畫;

3.沒(méi)有黑板擦功能;

4.沒(méi)有顏色混合功能;

5.畫筆是純粹的顏色,其實(shí)可以用一個(gè)圖片設(shè)置畫筆的形狀;

6.筆可以穿透畫板

這些問(wèn)題都將在升級(jí)篇中完善;

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持武林網(wǎng)。

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 喀喇| 宝山区| 阳西县| 醴陵市| 昌都县| 商城县| 兴海县| 诸城市| 正镶白旗| 六枝特区| 英超| 天峻县| 道真| 迁西县| 新平| 桂林市| 南雄市| 漳浦县| 通州区| 康定县| 湛江市| 延边| 乌拉特后旗| 天峨县| 靖远县| 枣阳市| 哈密市| 西丰县| 宁阳县| 泰和县| 农安县| 正定县| 浑源县| 西乌珠穆沁旗| 勐海县| 浪卡子县| 武陟县| 滦平县| 泗水县| 梅州市| 绵竹市|