unity3d 模型顶点坐标

2018-05-31 15:19:48 WUYIDUER 阅读数 912
  • Unity 值得看的500+ 技术内容列表

    Unity3D是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏、建筑可视化、实时三维动画等类型互动内容的多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。

用鼠标拾取模型的顶点,  那么首先要做的是获取鼠标发出的射线与模型的碰撞点.
代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ll : MonoBehaviour {
    private object spheretransform;
    // Use this for initialization
    void Start () {
  
 }
 
 // Update is called once per frame
 void Update () {
        RaycastHit hit;
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
        if (Physics.Raycast(ray, out hit, 100))
        {
            Debug.Log(hit.collider.gameObject.name);
            Debug.DrawLine(ray.origin, hit.point, Color.red);
    }
}

 那么要注意几个问题:

         1.场景中的摄像机必须是主摄像机,就是摄像机的tag是MainCamera

 2. Ray ray = Camera.mainCamera.ScreenPointToRay(Input.mousePosition);

         Camera.ScreenPointToRay()方法其实就是“通过2D屏幕坐标在

3D空间中拾取”,我们的3D场景经过摄像机的投影,变成了2D图像,显示在了屏幕上,那么通过逆运算,就可以换算出鼠标点的位置的3D位置,从而可以进一步选取3D场景中的物体!当然这个摄像机是离不开的,是那个摄像机渲染的当前场景,就要用哪个摄像机进行ScreenPointToRay()来进行运算!

 先说一下射线,射线是什么东西呢?

         Ray,Ray有两个字段,origin和direction,其中origin就是摄像的起始点,

         direction是射线的方向!

         Physics.Raycast(Ray ray,out RaycastHit,float distance)

         第一个参数就是一条射线,就是判断射线与其它物体的碰撞!

          碰撞之后会返回RaycastHit信息,distance是射线发出的距离。

  通过Physics.Raycast()可以out出一个参数(形参),RaycastHit,这个可以获取到碰撞点RaycastHit.point;那么为了明显的看到它,我用了一个红色材质的球体,球体要小一些,不断设置球体的位置为碰撞点的位置,大家就很容易看到结果对不对!

          在调试的过程中,我发现红色的球不断的向屏幕移动过来,不解到底是什么原因,后来分析是因为,射线不断的红球发生了碰撞,碰撞点在球的表面,所以球就不断向屏幕外移动,所以要加一句

          if (hit.collider.gameObject.name == "Sphere") return;
  拾取原理   
                   拾取主要用来表示能过鼠标在屏幕上单击来选中某个3D模型,然后就可以获取这个模型信息,同时也可以对这个模型进行编辑。   
            拾取算法的主要思想是:得到鼠标点击处的屏幕坐标,通过投影矩阵和观察矩阵把该坐标转换为通过视点和鼠标点击点的一条射入场景的光线,该光线如果与场景模型的三角形相交,则获取该相交三角形的信息。   
            拾取的具体过程如下:   
                   1.使用获取鼠标当前状态。   
                   2.把屏幕坐标转换为屏幕空间坐标。   屏幕中心是(0, 0),屏幕右下角是 (1*(屏幕宽度/屏幕高度), 1)。屏幕空间的x坐标这样计算: ((鼠标x坐标) / (屏幕宽度/2))-1.0f) *(屏幕宽度/屏幕高度)   屏幕空间的y坐标这样计算: (1.0f ? ((鼠标y坐标) / (屏幕高度/ 2 ) )   
                   3.计算摄像机视图中的宽度和高度的截距比。如下计算:   view ratio = tangent(camera field of view / 2 )   通常,你只需要一次,然后保存这个结果供以后使用。在摄像机视野改变的时候,你需要重新计算。   
                   4.把屏幕空间坐标转换成摄像机空间坐标系近景裁剪平面中的一个点。   Near point = ((屏幕空间x坐标)*(近景裁剪平面的Z值)*(view ratio ),   (屏幕空间y坐标)*(近景裁剪平面的Z值)*(view ratio ),   (-近景裁剪平面的Z值) )   
                   5.把屏幕空间坐标转换成摄像机空间坐标系远景裁剪平面中的一个点。   Far point = ((屏幕空间x坐标)* (远景裁剪平面的Z值)*(view ratio ),   (屏幕空间y坐标)*(远景裁剪平面的Z值 )*(view ratio),   (-远景裁剪平面的Z值) )   
                   6.使用Invert 获得摄像机视图矩阵的一个Invert的拷贝。使用摄像机视图矩阵(Matrix)来把世界坐标转化成摄像机坐标,使用这个反转的矩阵可以把摄像机坐标转化成世界坐标。   Matrix invView = Matrix.Invert(view);   
                   7.使用反转的视图矩阵(view Matrix ) 和Transform方法把远景点和近景点转换成世界空间坐标。   Vector3 worldSpaceNear = Vector3.Transform(cameraSpaceNear, invView);   Vector3 worldSpaceFar = Vector3.Transform(cameraSpaceFar, invView);   
                   8.创建一个射线(Ray)类的对象,起点是近景点,指向远景点。   Ray pickRay = new Ray(worldSpaceNear, worldSpaceFar - worldSpaceNear);   
                   9.对世界空间中的所有物体循环调用 Intersects 方法来检测 Ray 是否与其相交。如果相交,则检测是不是目前为止距玩家最近的物体,如果是,记录下这个物体以及距离值,替换掉之前找到的最近的物体的记录。当完成对所有物体的检测后,最后一次记录的那个物体就是玩家用鼠标点击的距离玩家最近的物体。


实现效果:
2019-07-05 10:46:00 weixin_30377461 阅读数 83
  • Unity 值得看的500+ 技术内容列表

    Unity3D是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏、建筑可视化、实时三维动画等类型互动内容的多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。

 1 public SkinnedMeshRenderer rendererBody;
 2 Mesh mesh;
 3 
 4 private void Awake()
 5 {
 6     Instance = this;
 7 
 8     mesh = new Mesh();
 9 }
10 
11 public Vector3[] GetMeshBodyWorldPoint()
12 {
13     Vector3[] v3s = null;
14     if (rendererBody != null)
15     {
16         //这里是关键,将一个蒙皮动画的某个时间点上的动作,Bake成一个不带蒙皮的Mesh
17         rendererBody.BakeMesh(mesh);
18         int count = mesh.vertexCount;
19         v3s = new Vector3[count];
20         Vector3[] meshv3s = mesh.vertices;
21         for (int i = 0; i < count; i++)
22         {
23             v3s[i] = transform.TransformPoint(meshv3s[i]);
24         }
25     }
26     return v3s;
27 }

 

转载于:https://www.cnblogs.com/luoyanghao/p/11136928.html

2016-04-15 09:51:37 Fatestay_DC 阅读数 2475
  • Unity 值得看的500+ 技术内容列表

    Unity3D是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏、建筑可视化、实时三维动画等类型互动内容的多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。

Shader "Custom/test1" {

    SubShader {
        pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag 

            #include "unitycg.cginc"

            float4x4 mvp;

            struct v2f{
                float4 pos:POSITION;
                fixed4 col:COLOR;
            };


            v2f vert(appdata_base v)
            {
                v2f o;
                o.pos = mul(mvp,v.vertex);
                //o.pos = mul(UNITY_MATRIX_MVP,v.vertex);

                //对于模型坐标的判断
                //if(v.vertex.x>0)
                //  o.col = fixed4(1,0,0,1);
                //else
                //  o.col = fixed4(0,0,1,1);

                //if(v.vertex.x==0.5&&v.vertex.y==0.5&&v.vertex.z==0.5)
                //  o.col = fixed4(1,0,0,1);
                //else
                //  o.col = fixed4(0,0,1,1);

                //模型坐标转向世界坐标的控制
                float4 wpos = mul(_Object2World,v.vertex);
                if(v.vertex.x>0)
                    o.col = fixed4(1,0,0,1);
                else
                    o.col = fixed4(0,0,1,1);
                return o;
            }

            fixed4 frag(v2f IN):COLOR
            {
                return IN.col;
            }
            ENDCG
        }
    }

}
2015-04-29 18:17:18 peanut__love 阅读数 7356
  • Unity 值得看的500+ 技术内容列表

    Unity3D是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏、建筑可视化、实时三维动画等类型互动内容的多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。


获得顶点数据,并将数据反作用于模型:

using UnityEngine;
using System.Collections;
 
[RequireComponent(typeof(MeshFilter))]
 public class example : MonoBehaviour {

	 void Update() {
	      Mesh mesh = this.transform.GetComponent<MeshFilter>().mesh;
		  Vector3 [] vertices = mesh.vertices;
		  int p = 0;
		  int flag = -1;
		  float maxheight = 0.0F;
	      while (p < vertices.Length) {
		     if(vertices[p].z > maxheight) {
			     maxheight = vertices[p].z;
			     flag = p;    
			 }
		        p++;
		   }
	     //vertices[flag] += new Vector3(0, 0, maxheight);
		         
		 mesh.vertices = vertices;
	     mesh.RecalculateNormals();
	    }
	void OnGUI(){
		if (GUI.Button (new Rect (0, 0, 100, 30), "Mesh")) {
			Mesh mesh = this.transform.GetComponent<MeshFilter>().mesh;
			Vector3 [] vertices = mesh.vertices;
			for(int i=0;i<vertices.Length;i++){
				Debug.Log("vertices["+i+"].x  " + vertices[i].x + "   vertices["+i+"].y  " + vertices[i].y + "   vertices["+i+"].z  " + vertices[i].z);
				vertices[i].x *= 2;
				vertices[i].y *= 2;
				vertices[i].z *= 2;

			}
			mesh.vertices = vertices;


		}
	}
  }


获取模型的顶点、三角形、法线数据

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

public class MeshPrinter : MonoBehaviour {  
	
	private string text_name;  
	private string text_vertices;  
	private string text_normals;  
	private string text_triangles;  
	private string text_uv;  
	private string text_tangents;  
	
	public MeshFilter mCurrentFilter;  
	
	public List<MeshFilter> targets;  
	
	void Start () {  
		
		targets = new List<MeshFilter>();  
		AddAllTargets();  
		
		mCurrentFilter = null;  
		
	}  
	
	void Update () {  
		
		if(Input.GetKeyUp(KeyCode.Tab)){  
			TargetMesh();  
			FillText();  
		}  
	}  
	
	void OnGUI(){  
		
		
		float _x = 10;  
		Vector2 textSize = GUI.skin.label.CalcSize (new GUIContent(text_name));  
		GUI.Label(new Rect(_x, 10 ,textSize.x, textSize.y), text_name);  
		
		textSize = GUI.skin.label.CalcSize (new GUIContent(text_triangles));  
		GUI.Label(new Rect(_x, 30 ,textSize.x, textSize.y), text_triangles);  
		
		_x += textSize.x +20;  
		textSize = GUI.skin.label.CalcSize (new GUIContent(text_vertices));  
		GUI.Label(new Rect(_x, 30 ,textSize.x, textSize.y), text_vertices);  
		
		_x += textSize.x +20;  
		textSize = GUI.skin.label.CalcSize (new GUIContent(text_normals));  
		GUI.Label(new Rect(_x, 30 ,textSize.x, textSize.y), text_normals);  
		
		_x += textSize.x +20;  
		textSize = GUI.skin.label.CalcSize (new GUIContent(text_tangents));  
		GUI.Label(new Rect(_x, 30 ,textSize.x, textSize.y), text_tangents);  
		
		_x += textSize.x +20;  
		textSize = GUI.skin.label.CalcSize (new GUIContent(text_uv));  
		GUI.Label(new Rect(_x, 30 ,textSize.x, textSize.y), text_uv);  
		
	}  
	
	public void AddAllTargets(){  
		
		GameObject[] gos = GameObject.FindObjectsOfType(typeof(GameObject)) as GameObject[];  
		foreach(GameObject go in gos)  
			if(go.GetComponent<MeshFilter>() != null)  
				AddTarget( go.GetComponent<MeshFilter>());  
	}  
	
	public void AddTarget(MeshFilter target){  
		
		targets.Add(target);  
	}  
	
	private void TargetMesh(){  
		
		if(mCurrentFilter == null){  
			mCurrentFilter = targets[0];  
		}else{  
			int index = targets.IndexOf(mCurrentFilter);  
			if(index < targets.Count-1){  
				index ++;  
			}else{  
				index = 0;  
			}  
			mCurrentFilter = targets[index];  
		}  
	}  
	
	private void FillText(){  
		
		text_name = "Name: " + mCurrentFilter.gameObject.name;  
		
		Mesh mesh = mCurrentFilter.mesh;  
		
		int size = mesh.vertexCount;  
		text_vertices = "vertices: "+ size + "\n";  
		for(int i = 0; i<size; i++){  
			text_vertices +=  i + ": " + mesh.vertices[i][0]+","+mesh.vertices[i][1]+","+mesh.vertices[i][2]+";\n";   
		}  
		
		size = mesh.normals.Length;  
		text_normals = "normals: " + size + "\n";  
		for(int i = 0; i<size; i++){  
			text_normals += mesh.normals[i].x +","+ mesh.normals[i].y +","+mesh.normals[i].z +";\n";  
		}  
		
		size = mesh.triangles.Length ;  
		text_triangles = "triangles: " + size + "\n";  
		for(int i = 0; i<size/3; i++){  
			text_triangles += mesh.triangles [3*i] +","+ mesh.triangles [3*i+1] +","+mesh.triangles [3*i+2] +";\n";  
		}  
		
		size = mesh.uv.Length ;  
		text_uv = "uv: " + size + "\n";  
		for(int i = 0; i<size; i++){  
			text_uv += mesh.uv [i][0] +","+ mesh.uv [i][1] +";\n";  
			
		}  
		size = mesh.tangents.Length ;text_tangents = "tangents: " + size + "\n";  
		for(int i = 0; i<size; i++){  
			text_tangents += mesh.tangents[i][0] + ", "+ mesh.tangents[i][1] + ", "+mesh.tangents[i][2] + ", "+mesh.tangents[i][3] +";\n";  
		}  
	}  
}  


2017-09-25 10:17:17 m0_37250299 阅读数 6290
  • Unity 值得看的500+ 技术内容列表

    Unity3D是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏、建筑可视化、实时三维动画等类型互动内容的多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。

using UnityEngine;
using System.Collections;

/// <summary>
/// 获取模型的所有顶点坐标
/// </summary>
public class GetVertex : MonoBehaviour {

	void Start () 
	{
		Mesh mesh = GetComponent<MeshFilter>().mesh;

		Vector3[] vertices = mesh.vertices;

		foreach(Vector3 vertex in vertices)
		{
			Debug.Log(vertex);
		}
	}

}

将这个脚本拖到模型上,就可以获取到模型的所有顶点坐标了。