调了半天发现是逻辑错误,改了一下终于没那么奇怪了:



  但是有的接触点很明显跑偏了。再回顾一下自己是怎么求的,我是直接用的下面的代码求解一个点是否在另一个物体内部:

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开发日志(七)的更多相关文章

  1. Kinect For Windows V2开发日志七:照片合成与背景消除

    上一篇里讲到了Kinect可以从环境中区分出人体来.因此可以利用这个功能,来把摄像头前的人合成进照片里,和利用Photoshop不同的是,这样合成进去的人是动态且实时的. 简单的思路 BodyInde ...

  2. 3dContactPointAnnotationTool开发日志(三四)

      今天就是让背景图可以变大变小,变透明度,然后将3d的点投影到图片上,输出2d接触点信息:   可以看到输出了正确的接触点信息:   然后还把空物体的包围盒大小设置为边长为0.1的的正方体,点击选中 ...

  3. 3dContactPointAnnotationTool开发日志(三三)

      添加背景图片后发现Runtime Transform Gizmo无法选中物体了:   于是改了一下EditorObjectSelection.cs中的WereAnyUIElementsHovere ...

  4. 3dContactPointAnnotationTool开发日志(三二)

      今天就是看怎么把论文的python源码预测出来的smpl模型的姿势和形状参数弄到unity版本的smpl里,但是python版本的和unity版本的不一样.   先看看他的fit_3d.py:   ...

  5. 3dContactPointAnnotationTool开发日志(三一)

      在玩的时候遇到了一个python的问题: Traceback (most recent call last): File ".\convert.py", line 13, in ...

  6. 3dContactPointAnnotationTool开发日志(三十)

      在vs2017里生成opencv时遇到了无法打开python27_d.lib的问题,具体解决请看这个,不过我用的是方法2,python37_d.lib找不到同理.   Windows下可以用的op ...

  7. 3dContactPointAnnotationTool开发日志(二九)

      今天想着在Windows平台上跑通那个代码,不过它的官网上写的支持平台不包括windows,但我还是想试试,因为看他的依赖好像和平台的关系不是特别大.   看了下它的py代码,不知道是py2还是p ...

  8. 3dContactPointAnnotationTool开发日志(二八)

      师姐说物体间不能有穿透,于是我试了下给物体加rigidbody和meshCollider   然后就报错:   说是用meshCollider要么去掉刚体要么就把刚体设置为iskinematic. ...

  9. 3dContactPointAnnotationTool开发日志(二七)

      今天的主要工作是把选中物体以及复制删除物体和右边三个面板联系起来,就是通过鼠标框选住物体,右边面板的对应项的颜色也会改变,而且通过右边面板也能控制物体的选中状态,被选中的物体成cyan青色,并且包 ...

随机推荐

  1. phpcms v9 完美更换整合Ueditor 1.3

    phpcms这套系统相信大家不陌生,它做的很不错,但是也有好多地方不满足我们的需求,比如在线编辑器. 它自带的是CKEditor编辑器,功能较少,比如代码加亮功能就没有. 所以我来说一下怎么替换php ...

  2. 数据结构之栈和队列及其Java实现

    栈和队列是数据结构中非常常见和基础的线性表,在某些场合栈和队列使用很多,因此本篇主要介绍栈和队列,并用Java实现基本的栈和队列,同时用栈和队列相互实现. 栈:栈是一种基于“后进先出”策略的线性表.在 ...

  3. Solr与Lucene的区别

    Lucene是一个优秀的开源搜索库,Solr是在Lucene上封装的完善的搜索引擎.通俗地说,如果Solr是汽车,那么Lucene就是发动机,没有发动机,汽车就没法运转,但对于用户来说只可开车,不能开 ...

  4. python2.7入门---CGI编程&文件上传&文件下载

        这次我们来看下文件下载和上传的操作.首先是上传,HTML设置上传文件的表单需要设置 enctype 属性为 multipart/form-data,代码如下所示: <!DOCTYPE h ...

  5. 20145202马超《网络对抗》Exp7 网络欺诈技术防范

    本实践的目标理解常用网络欺诈背后的原理,以提高防范意识,并提出具体防范方法.具体有(1)简单应用SET工具建立冒名网站(2)ettercap DNS spoof(3)结合应用两种技术,用DNS spo ...

  6. 20145226夏艺华 JAVA预备作业1

    博客阅读总结 关于师生关系: 学生和老师之间我觉得关系时多元化的,不能拘泥于单独的一种关系:灌输与被灌输,教授与被教授--我认为,在不同的课程阶段,师生之间的关系都可以发生变化.前期的老师更像是一个指 ...

  7. 下载地图瓦片(包括各种格式的,Openstreetmap,googlemap, bingmap)

    参考第三方开源库Brutile 个人的程序托管在github上

  8. C++11 type_traits 之is_same源码分析

    请看源码: template<typename _Tp, _Tp __v> struct integral_constant { static const _Tp value = __v; ...

  9. vue watch监控对象

    1.普通的watch data() { return { frontPoints: 0 } }, watch: { frontPoints(newValue, oldValue) { console. ...

  10. 【QT】常用类

    官方文档 doc QWidget QWidget类是所有用户界面对象的基类. 窗口部件是用户界面的一个基本单元:它从窗口系统接收鼠标.键盘和其它事件,并且在屏幕上绘制自己. 每一个窗口部件都是矩形的, ...