在Unity中实现点云的效果
介绍 在unity中实现点云的效果可以丰富我们的场景,并且可以与kinect等rgbd相机结合,增加互动。如果要在unity中实现点云的效果这里有两种方法: 一种是用自带的粒子系统,将每个点云中的点对应于每个粒子,并把对应的坐标,颜色赋值给粒子。 第二种是用游戏物体的MeshFilter组件,只渲染顶点而不Mesh,再重写shader,赋予每个顶点颜色。每种方法各有利弊,下面是实现过程: 1.利用Unity中的粒子系统usingUnityEngine;usingSystem.Collections;usingSystem.IO;publicclassGetPointCloudFromTXT:MonoBehaviour{ParticleSystemparticleSystem;//整个粒子系统ParticleSystem.Particle[]allParticles;//所有粒子的集合intpointCount;//粒子数目//UsethisforinitializationvoidStart(){particleSystem=GetComponentParticleSystem();//1\.读取数据//提前将点云存成txt文件放在Assert/StreamingAssets文件夹下,文本的每行代表一个点,由点的x,y,z,r,g,b六个float组成stringfileAddress=(Application.streamingAssetsPath+"/"+"jiao.txt");FileInfofInfo0=newFileInfo(fileAddress);//Debug.Log(fileAddress);strings="";StreamReaderr;ArrayListarrayListXYZ=newArrayList();ArrayListarrayListRGB=newArrayList();if(fInfo0.Exists){r=newStreamReader(fileAddress);}else{Debug.Log("NOTHISFILE!");return;}//将文本中的点云数据读入分别存到xyz数组和rgb数组中while((s=r.ReadLine())!=null){string[]words=s.Split(""[0]);Vector3xyz=newVector3(float.Parse(words[0]),-float.Parse(words[1]),float.Parse(words[2]));arrayListXYZ.Add(xyz);ColorcolorRGB=newColor(float.Parse(words[3])/.0f,float.Parse(words[4])/.0f,float.Parse(words[5])/.0f);arrayListRGB.Add(colorRGB);//Debug.Log(xyz.ToString()+","+colorRGB.ToString());}//2\.设置粒子系统particleSystem.startSpeed=0.0f;//设置粒子的初始速度为0particleSystem.startLifetime=.0f;//粒子的生命周期尽量长//3\.渲染出来(动态加载点云的时候再改这部分代码)pointCount=arrayListRGB.Count;allParticles=newParticleSystem.Particle[pointCount];particleSystem.maxParticles=pointCount;//设置粒子系统粒子数的最大值particleSystem.Emit(pointCount);//发射pointCount个粒子particleSystem.GetParticles(allParticles);//获取当前还存活的粒子数,不能少的一步,但是不是很清楚为什么for(inti=0;ipointCount;i++){allParticles[i].position=(Vector3)arrayListXYZ[i];//设置每个点的位置allParticles[i].startColor=(Color)arrayListRGB[i];//设置每个点的rgballParticles[i].startSize=0.01f;//设置点的大小,注意还要在unity界面上将粒子系统下面的Render模块中的Min/MaxParticleSize改小--0.01差不多了}particleSystem.SetParticles(allParticles,pointCount);//将点云载入粒子系统}}2.利用Mesh编写Shader 一次最多只能渲染出个点的模型所以要动态生成多个模型组合形成一个完整的点云 VertexColor.shader Shader"Custom/VertexColor"{SubShader{Pass{LODCGPROGRAM#pragmavertexvert#pragmafragmentfragstructVertexInput{float4v:POSITION;float4color:COLOR;};structVertexOutput{float4pos:SV_POSITION;float4col:COLOR;};VertexOutputvert(VertexInputv){VertexOutputo;o.pos=mul(UNITY_MATRIX_MVP,v.v);o.col=v.color;returno;}float4frag(VertexOutputo):COLOR{returno.col;}ENDCG}}} usingUnityEngine;usingSystem.Collections;usingSystem.IO;publicclassDisplayPointCloudByGpu:MonoBehaviour{intnumPoints=;voidStart(){//1\.读取数据//提前将点云存成txt文件放在Assert/StreamingAssets文件夹下,文本的每行代表一个点,由点的x,y,z,r,g,b六个float组成stringfileAddress=(Application.streamingAssetsPath+"/"+"test.txt");FileInfofInfo0=newFileInfo(fileAddress);//Debug.Log(fileAddress);strings="";StreamReaderr;ArrayListarrayListXYZ=newArrayList();ArrayListarrayListRGB=newArrayList();if(fInfo0.Exists){r=newStreamReader(fileAddress);}else{Debug.Log("NOTHISFILE!");return;}//将文本中的点云数据读入分别存到xyz数组和rgb数组中while((s=r.ReadLine())!=null){string[]words=s.Split(""[0]);Vector3xyz=newVector3(float.Parse(words[0]),-float.Parse(words[1]),float.Parse(words[2]));arrayListXYZ.Add(xyz);ColorcolorRGB=newColor(float.Parse(words[3])/.0f,float.Parse(words[4])/.0f,float.Parse(words[5])/.0f);arrayListRGB.Add(colorRGB);//Debug.Log(xyz.ToString()+","+colorRGB.ToString());}//2\.渲染intnum=arrayListRGB.Count;intmeshNum=num/numPoints;intleftPointsNum=num%numPoints;inti=0;for(;imeshNum;i++){GameObjectobj=newGameObject();obj.name=i.ToString();obj.AddComponentMeshFilter();obj.AddComponentMeshRenderer();MeshtempMesh=newMesh();CreateMesh(reftempMesh,refarrayListXYZ,refarrayListRGB,i*numPoints,numPoints);Materialmaterial=newMaterial(Shader.Find("Custom/VertexColor"));obj.GetComponentMeshFilter().mesh=tempMesh;obj.GetComponentMeshRenderer().material=material;}GameObjectobjLeft=newGameObject();objLeft.name=i.ToString();objLeft.transform.position=newVector3(Random.Range(-10,10),Random.Range(-10,10),Random.Range(-10,10));objLeft.AddComponentMeshFilter();objLeft.AddComponentMeshRenderer();MeshtempMeshLeft=newMesh();CreateMesh(reftempMeshLeft,refarrayListXYZ,refarrayListRGB,i*numPoints,leftPointsNum);MaterialmaterialLeft=newMaterial(Shader.Find("Custom/VertexColor"));objLeft.GetComponentMeshFilter().mesh=tempMeshLeft;objLeft.GetComponentMeshRenderer().material=materialLeft;}voidCreateMesh(refMeshmesh,refArrayListarrayListXYZ,refArrayListarrayListRGB,intbeginIndex,intpointsNum){Vector3[]points=newVector3[pointsNum];Color[]colors=newColor[pointsNum];int[]indecies=newint[pointsNum];for(inti=0;ipointsNum;++i){points[i]=(Vector3)arrayListXYZ[beginIndex+i];indecies[i]=i;colors[i]=(Color)arrayListRGB[beginIndex+i];}mesh.vertices=points;mesh.colors=colors;mesh.SetIndices(indecies,MeshTopology.Points,0);}}总结 利用粒子系统可以模拟出点云的效果,并且可以调整点的大小和形状,但是点一多起来就很很难渲染。而利用Mesh直接画点,不能调整大小(旧版本Shader中可以用PSIZE调整点渲染的大小,但目前已不支持),但是可以流畅得显示很多点。 版权声明:本文为博主原创文章,遵循CC4.0BY-SA版权协议,转载请附上原文出处链接和本声明。 本文链接: |
转载请注明地址:http://www.zibeichia.com/zbcyxxg/6837.html
- 上一篇文章: 站桩时,这一点不容忽视,否则效果大打折扣
- 下一篇文章: 实用性满点的功能性瑜伽解剖学