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



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

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. windows下nginx的安装

    一. 下载 http://nginx.org/    (下载后解压) 二. 修改配置文件 nginx配置文件在 nginx-1.8.0\conf\nginx.conf http { gzip on; ...

  2. Git 与 SVN对比详解

    一.Git vs SVNGit 和 SVN 孰优孰好,每个人有不同的体验. Git是分布式的,SVN是集中式的 这是 Git 和 SVN 最大的区别.若能掌握这个概念,两者区别基本搞懂大半.因为 Gi ...

  3. 第一章:程序设计和C语言

    一.什么是计算机程序? 所谓程序就是一组计算机能识别和执行的指令.计算机的一切操作都是由程序控制的,本质是程序的机器,程序和指令是计算机系统最基本的概念. 二.什么是计算机语言? 人和计算机交流信息要 ...

  4. WPF 应用程序资源、内容和数据文件

    MSDN相关介绍: http://msdn.microsoft.com/zh-cn/library/aa970494(v=vs.100).aspx 内容文件(Content Files)内容文件简单的 ...

  5. FpSpread基本句法

    1,   在调用的.aspx页面开头注册:     "FarPoint.Web.Spread"   Assembly="FarPoint.Web.SpreadJ,   V ...

  6. 南京Uber优步司机奖励政策(12月28日到1月3日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  7. 苏州Uber优步司机奖励政策(12月14日到12月20日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  8. java对于Redis中jedis的操作

    package com.answer.redis; import java.util.HashMap; import java.util.List; import java.util.Map; imp ...

  9. Linux命令应用大词典-第40章 网络客户端

    40.1 elinks:字符模式的Web浏览器 40.2 wget:从Web网站下载文件 40.3 curl:传输URL 40.4 lynx:通用分布式信息的万维网浏览器 40.5 lftp:实现文件 ...

  10. JAVA中 "\" 和 "/" 的区别

    1.在java中路径一般用”/” 2.linux.unix中的路径一般用”/” 3.windows中的路径一般用”\” 所以在java中写windows路径一般用”/”,或用“\”将”\”转义一下(& ...