3dContactPointAnnotationTool开发日志(七)
调了半天发现是逻辑错误,改了一下终于没那么奇怪了:

但是有的接触点很明显跑偏了。再回顾一下自己是怎么求的,我是直接用的下面的代码求解一个点是否在另一个物体内部:
var bounds = uso.mesh.bounds;
if (bounds.Contains(mesh.vertices[mesh.triangles[i+j]]))
{
xj = true;
}
这个bounds我又去unity文档上查了一下,发现它只是物体的包围盒,所以显然会得到多余的点,没办法只能再改了。
既然unity没有自带的方法那就自己算得了,思路是对于一个给定点枚举另一个三维模型的三角面片通过面片法向量和面上一点通过点积的正负来判断。一个三角面片的法向量貌似是通过obj模型对应顶点对应的点的法向量相加再除以3得到的。然而网上的那个代码没有把顶点法向量读到gameobject中,于是自己修改如下:
using UnityEngine;
using System.IO;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
namespace Hont
{
public static class ObjFormatAnalyzerFactory
{
public static List<GameObject> AnalyzeToGameObject(string objFilePath)
{
if (!File.Exists(objFilePath)) return null;
var objFormatAnalyzer = new ObjFormatAnalyzer();
objFormatAnalyzer.Analyze(File.ReadAllText(objFilePath));
int length = objFormatAnalyzer.ObjFaceBegin.Length;
var re = new List<GameObject>();
var sourceVertexArr = objFormatAnalyzer.VertexArr;
var sourceVertexNormalArr = objFormatAnalyzer.VertexNormalArr;
var sourceUVArr = objFormatAnalyzer.VertexTextureArr;
var faceArr = objFormatAnalyzer.FaceArr;
for (int objId = 0; objId < length; objId++)
{
var go = new GameObject();
go.name = objFormatAnalyzer.ObjName[objId];
var meshRenderer = go.AddComponent<MeshRenderer>();
var meshFilter = go.AddComponent<MeshFilter>();
var mesh = new Mesh();
var vertexList = new List<Vector3>();
var vertexNormalList = new List<Vector3>();
var uvList = new List<Vector2>();
int faceBeginId = objFormatAnalyzer.ObjFaceBegin[objId];
int faceEndId = faceArr.Length;//左闭右开
if (objId < length - 1)
faceEndId = objFormatAnalyzer.ObjFaceBegin[objId + 1];
int triangleNum = 0;
for (int i = faceBeginId; i < faceEndId; i++)
if (faceArr[i].IsQuad)
triangleNum += 6;
else triangleNum += 3;
var triangles = new int[triangleNum];
for (int i = faceBeginId, j = 0; i < faceEndId; i++)
{
var currentFace = faceArr[i];
triangles[j] = j;
triangles[j + 1] = j + 1;
triangles[j + 2] = j + 2;
var vec = sourceVertexArr[currentFace.Points[0].VertexIndex - 1];
vertexList.Add(new Vector3(vec.X, vec.Y, vec.Z));
vec = sourceVertexNormalArr[currentFace.Points[0].VertexIndex - 1];
vertexNormalList.Add(new Vector3(vec.X, vec.Y, vec.Z));
var uv = sourceUVArr[currentFace.Points[0].TextureIndex - 1];
uvList.Add(new Vector2(uv.X, uv.Y));
vec = sourceVertexArr[currentFace.Points[1].VertexIndex - 1];
vertexList.Add(new Vector3(vec.X, vec.Y, vec.Z));
vec = sourceVertexNormalArr[currentFace.Points[1].VertexIndex - 1];
vertexNormalList.Add(new Vector3(vec.X, vec.Y, vec.Z));
uv = sourceUVArr[currentFace.Points[1].TextureIndex - 1];
uvList.Add(new Vector2(uv.X, uv.Y));
vec = sourceVertexArr[currentFace.Points[2].VertexIndex - 1];
vertexList.Add(new Vector3(vec.X, vec.Y, vec.Z));
vec = sourceVertexNormalArr[currentFace.Points[2].VertexIndex - 1];
vertexNormalList.Add(new Vector3(vec.X, vec.Y, vec.Z));
uv = sourceUVArr[currentFace.Points[2].TextureIndex - 1];
uvList.Add(new Vector2(uv.X, uv.Y));
if (currentFace.IsQuad)
{
triangles[j + 3] = j + 3;
triangles[j + 4] = j + 4;
triangles[j + 5] = j + 5;
j += 3;
vec = sourceVertexArr[currentFace.Points[0].VertexIndex - 1];
vertexList.Add(new Vector3(vec.X, vec.Y, vec.Z));
vec = sourceVertexNormalArr[currentFace.Points[0].VertexIndex - 1];
vertexNormalList.Add(new Vector3(vec.X, vec.Y, vec.Z));
uv = sourceUVArr[currentFace.Points[0].TextureIndex - 1];
uvList.Add(new Vector2(uv.X, uv.Y));
vec = sourceVertexArr[currentFace.Points[2].VertexIndex - 1];
vertexList.Add(new Vector3(vec.X, vec.Y, vec.Z));
vec = sourceVertexNormalArr[currentFace.Points[2].VertexIndex - 1];
vertexNormalList.Add(new Vector3(vec.X, vec.Y, vec.Z));
uv = sourceUVArr[currentFace.Points[2].TextureIndex - 1];
uvList.Add(new Vector2(uv.X, uv.Y));
vec = sourceVertexArr[currentFace.Points[3].VertexIndex - 1];
vertexList.Add(new Vector3(vec.X, vec.Y, vec.Z));
vec = sourceVertexNormalArr[currentFace.Points[3].VertexIndex - 1];
vertexNormalList.Add(new Vector3(vec.X, vec.Y, vec.Z));
uv = sourceUVArr[currentFace.Points[3].TextureIndex - 1];
uvList.Add(new Vector2(uv.X, uv.Y));
}
j += 3;
}
mesh.vertices = vertexList.ToArray();
mesh.normals = vertexNormalList.ToArray();
mesh.uv = uvList.ToArray();
mesh.triangles = triangles;
meshFilter.mesh = mesh;
meshRenderer.material = new Material(Shader.Find("Standard"));
//meshRenderer.material = new Material(Shader.Find("UCLA Game Lab/Wireframe/Single-Sided"));
re.Add(go);
}
return re;
}
}
}
发现得到模型的光照效果也不一样了,加入法向量之后的效果:

之前的没加法向量的效果:

然后拿这些法向量来算,发现压根算不出接触点来。到底是什么问题呢?用Debug.DrawLine图形化显示一下(只能在scene中看到线),发现根本不是我想的那样。
Debug.DrawLine(c, c+n/10,Color.red,10000);
顶点和顶点法向量:

三顶点相加/3和顶点法向量相加/3:

貌似这个法向量是只影响光照的,和几何半毛钱关系没有,所以只能用叉积来算了。
用叉积算完还是不对,再图形化看看,发现有的三角面片竟然有两个朝向的法向量,简直无语。

看了一下obj模型,竟然还有这样的三角面片,明明是同一个但是顺序相反,真是坑爹。

所以只能再结合一下光照法向量了,毕竟他们都是朝外的。
实验发现他们并不都是朝外的,GG!
而且回想一下发现这个方法只对凸的物体有用,那些不规则的物体是不能用这种方法的。
为何不用射线法呢?具体怎么实现明天再弄吧。
3dContactPointAnnotationTool开发日志(七)的更多相关文章
- Kinect For Windows V2开发日志七:照片合成与背景消除
上一篇里讲到了Kinect可以从环境中区分出人体来.因此可以利用这个功能,来把摄像头前的人合成进照片里,和利用Photoshop不同的是,这样合成进去的人是动态且实时的. 简单的思路 BodyInde ...
- 3dContactPointAnnotationTool开发日志(三四)
今天就是让背景图可以变大变小,变透明度,然后将3d的点投影到图片上,输出2d接触点信息: 可以看到输出了正确的接触点信息: 然后还把空物体的包围盒大小设置为边长为0.1的的正方体,点击选中 ...
- 3dContactPointAnnotationTool开发日志(三三)
添加背景图片后发现Runtime Transform Gizmo无法选中物体了: 于是改了一下EditorObjectSelection.cs中的WereAnyUIElementsHovere ...
- 3dContactPointAnnotationTool开发日志(三二)
今天就是看怎么把论文的python源码预测出来的smpl模型的姿势和形状参数弄到unity版本的smpl里,但是python版本的和unity版本的不一样. 先看看他的fit_3d.py: ...
- 3dContactPointAnnotationTool开发日志(三一)
在玩的时候遇到了一个python的问题: Traceback (most recent call last): File ".\convert.py", line 13, in ...
- 3dContactPointAnnotationTool开发日志(三十)
在vs2017里生成opencv时遇到了无法打开python27_d.lib的问题,具体解决请看这个,不过我用的是方法2,python37_d.lib找不到同理. Windows下可以用的op ...
- 3dContactPointAnnotationTool开发日志(二九)
今天想着在Windows平台上跑通那个代码,不过它的官网上写的支持平台不包括windows,但我还是想试试,因为看他的依赖好像和平台的关系不是特别大. 看了下它的py代码,不知道是py2还是p ...
- 3dContactPointAnnotationTool开发日志(二八)
师姐说物体间不能有穿透,于是我试了下给物体加rigidbody和meshCollider 然后就报错: 说是用meshCollider要么去掉刚体要么就把刚体设置为iskinematic. ...
- 3dContactPointAnnotationTool开发日志(二七)
今天的主要工作是把选中物体以及复制删除物体和右边三个面板联系起来,就是通过鼠标框选住物体,右边面板的对应项的颜色也会改变,而且通过右边面板也能控制物体的选中状态,被选中的物体成cyan青色,并且包 ...
随机推荐
- 泛型List集合转化为DateTable
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; name ...
- Java使用zxing生成解读QRcode二维码
1.maven的pom配置jar包,如果不实用maven请手动下载jar包 <dependency> <groupId>com.google.zxing</groupId ...
- 数据结构之链表及其Java实现
数据的存储一般分线性存储结构和链式存储结构两种.前者是一种顺序的存储方式,在内存中用一块连续的内存空间存储数据,即逻辑上相连的物理位置相邻,比较常见的就是数组:后者是一种链式存储方式,不保证顺序性,逻 ...
- Django中的模型继承
1.使用最原始的方式继承 class Animal(models.Model): name = models.CharField(max_length=20) age = models.Integer ...
- RTL8188EUS之MAC地址烧写(使用利尔达模组)
1. 手上有几个RTL8188EUS的wifi模块,打算把台式机装个无线网卡,但是插上之后发现没有MAC,没办法只能自己去找个烧写MAC的软件.RTL8188内部有个eFuse,用来配置之类的.这个e ...
- 三、并行流与串行流 Fork/Join框架
一.并行流概念: 并行流就是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流. java8中将并行进行了优化,我们可以很容易的对数据进行并行操作.Stream API可以声明性的通过pa ...
- web漏洞原理 (需要每周更新此篇文章)
SQL注入攻击简介 结构化查询语言SQL是用来和关系数据库进行交互的文本语言.它允许用户对数据进行有效的管理,包含了对数据的查询.操作.定义和控制等几个方面,例如向数据库写入.插入数据,从数据库读取数 ...
- Windows运行机理——消息与消息队列
Windows运行机理这系列文章都是来至于<零基础学Qt4编程>——吴迪,个人觉得写得很好,所以进行了搬运和个人加工 Windows程序设计时一种基于消息的时机驱动方式的设计模式,完全不同 ...
- 苏醒的巨人----CSRF
一.CSRF 跨站请求伪造(Cross-Site Request Forgery,CSRF)是指利用 受害者尚未失效的身份认证信息(cookie.会话等),诱骗其点 击恶意链接或者访问包含攻击代码的页 ...
- SqlServer的两种插入方式效率对比
protected void button1_Click(object sender, EventArgs e) { DataTable dtSource = new DataTable(); dtS ...