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青色,并且包 ...
随机推荐
- layui sleect获取value值
<div class="layui-form-item"> <label for="username" class="layui-f ...
- Set的源码分析
Set的内部实现其实是一个Map.即HashSet的内部实现是一个HashMap,TreeSet的内部实现是一个TreeMap,LinkedHashSet的内部实现是一个LinkedHashMap. ...
- Vue.js的小例子--随便写的
1.领导安排明天给同事们科普下vue 2.简单写了两个小例子 3.话不多说直接上代码 <!DOCTYPE html> <html> <head> <meta ...
- 嵌入式GPIO接口及操作(二)
目标:C语言实现点亮LED灯 首先是main函数,并不特殊,它是被系统调用来执行的,main函数结束后要返回调用main函数的地址处,那么裸机程序,没有操作系统做这些工作,就要自己写调用main函数的 ...
- 组播___IGMP
一.基本概念: 1.协议概述: 是运行在主机和与主机直连的路由器之间,其实现的功能是双向的:一方面,主机通过IGMP通知路由器希望接收某个特定组播组的信息:另一方面,路由器通过IGMP周期性地查询局域 ...
- 【数据结构】循环链表&&双向链表详解和代码实例
喜欢的话可以扫码关注我们的公众号哦,更多精彩尽在微信公众号[程序猿声] 01 循环链表 1.1 什么是循环链表? 前面介绍了单链表,相信大家还记得相关的概念.其实循环链表跟单链表也没有差别很多,只是在 ...
- 【8086汇编-Day6】关于loop的实验
实验内容 因为是要复制代码,所以常规来做是取代码段地址来用,所以把cs值mov给ax,但是这只是临时的,ax之后还有别的用途,那就把指令当作数据来存(把ax值 mov给ds,表示这一段地址用作代码段, ...
- 青岛Uber优步司机奖励政策(1月11日~1月17日)
滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...
- Java: 数组、列表和集合的互相转换
1. Array 转 List String[] city = {"Nanjing","Shanghai","Beijing"}; List ...
- 用最简单的MVC模式输出内容
MVC是模型(model)-视图(view)-控制器(controller)的缩写,它的作用是使代码分离,可维护性高.重用性高 编写Model层: <?php class model{ publ ...