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



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

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. day 26 网络知识 01

    一.    c/s 架构: 客户端(client)/服务端(server)架构       服务端: 提供服务的      客户端: 享受服务的     B/S 架构:浏览器(browser)/服务端 ...

  2. hadoop生态搭建(3节点)-10.spark配置

    # https://www.scala-lang.org/download/2.12.4.html# ================================================= ...

  3. STM32(1)——使用Keil MDK以及标准外设库创建STM32工程

    转载来自:http://emouse.cnblogs.com 1.1 开发工具与开发环境 1. 软件版本 本节所使用Keil MDK 为目前的最新版V4.21.其他版本差别不大,读者可以根据自己使用的 ...

  4. Python-变量与基础数据类型

    ·变量(variable)  笔记: 变量本质上是一个占位符.变量可以用来存储整数.字符串.列表等.简单的可以理解为一个座位,可以坐老人也可以坐小孩,可以坐男孩,也可以坐女孩. 在python里,标识 ...

  5. 如何在VMware Fusion中导入windows下的虚拟机

    最近换了新款的mbp,因为偷懒,便将之前在windows台式机上的虚拟机搬了过来. 特此记录下搬运过程,方便以后查看. 一 操作过程 安装激活VMware 常规操作,无需赘言 拷贝windows下虚拟 ...

  6. HyperLedger Fabric 1.4 Solo模式简介(10.1)

    Solo模式指单节点通信模式,该环境中只有一个排序(orderer)服务,从节点(peer)发送来的消息由一个orderer进行排序和产生区块:由于排序(orderer)服务只有一个orderer为所 ...

  7. Hibernate学习笔记三

    1.1.1 Hibernate的关联关系映射:(多对多) 1.1.1.1 多对多的配置: 步骤一创建实体和映射: Student: public class Student { private Int ...

  8. 【8086汇编-Day8】实验九

    Lab1 代码 ; 在屏幕上输出内存单元中的十进制两位数 assume cs:code, ds:data data segment db db , ; 前一个字节用于保存商,后一个字节用于保存余数 d ...

  9. 聊天功能插件Socket.io

    一.Socket.io是什么 是基于时间的实时双向通讯库 基于websocket协议的 前后端通过时间进行双向通讯 配合express快速开发实时应用 二.Socket.io和ajax区别 基于不同的 ...

  10. css dropdown menu

    <ul> <li class="left">abc</li> <li class="middle" id=" ...